blob: e5dc43f7f22917081184014a7f5e8a35181f5ec5 [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 Shmidt5a1480c2014-05-12 09:46:02 -070054#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080055#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056
57const char *wpa_supplicant_version =
58"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080059"Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060
61const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080062"This software may be distributed under the terms of the BSD license.\n"
63"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064#ifdef EAP_TLS_OPENSSL
65"\nThis product includes software developed by the OpenSSL Project\n"
66"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
67#endif /* EAP_TLS_OPENSSL */
68;
69
70#ifndef CONFIG_NO_STDOUT_DEBUG
71/* Long text divided into parts in order to fit in C89 strings size limits. */
72const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080073"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080075"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076"\n"
77"Redistribution and use in source and binary forms, with or without\n"
78"modification, are permitted provided that the following conditions are\n"
79"met:\n"
80"\n";
81const char *wpa_supplicant_full_license3 =
82"1. Redistributions of source code must retain the above copyright\n"
83" notice, this list of conditions and the following disclaimer.\n"
84"\n"
85"2. Redistributions in binary form must reproduce the above copyright\n"
86" notice, this list of conditions and the following disclaimer in the\n"
87" documentation and/or other materials provided with the distribution.\n"
88"\n";
89const char *wpa_supplicant_full_license4 =
90"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
91" names of its contributors may be used to endorse or promote products\n"
92" derived from this software without specific prior written permission.\n"
93"\n"
94"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
95"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
96"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
97"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
98const char *wpa_supplicant_full_license5 =
99"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
100"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
101"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
102"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
103"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
104"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
105"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
106"\n";
107#endif /* CONFIG_NO_STDOUT_DEBUG */
108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700109/* Configure default/group WEP keys for static WEP */
110int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
111{
112 int i, set = 0;
113
114 for (i = 0; i < NUM_WEP_KEYS; i++) {
115 if (ssid->wep_key_len[i] == 0)
116 continue;
117
118 set = 1;
119 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
120 i, i == ssid->wep_tx_keyidx, NULL, 0,
121 ssid->wep_key[i], ssid->wep_key_len[i]);
122 }
123
124 return set;
125}
126
127
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700128int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
129 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700130{
131 u8 key[32];
132 size_t keylen;
133 enum wpa_alg alg;
134 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800135 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136
137 /* IBSS/WPA-None uses only one key (Group) for both receiving and
138 * sending unicast and multicast packets. */
139
140 if (ssid->mode != WPAS_MODE_IBSS) {
141 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
142 "IBSS/ad-hoc) for WPA-None", ssid->mode);
143 return -1;
144 }
145
146 if (!ssid->psk_set) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
148 "WPA-None");
149 return -1;
150 }
151
152 switch (wpa_s->group_cipher) {
153 case WPA_CIPHER_CCMP:
154 os_memcpy(key, ssid->psk, 16);
155 keylen = 16;
156 alg = WPA_ALG_CCMP;
157 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700158 case WPA_CIPHER_GCMP:
159 os_memcpy(key, ssid->psk, 16);
160 keylen = 16;
161 alg = WPA_ALG_GCMP;
162 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700163 case WPA_CIPHER_TKIP:
164 /* WPA-None uses the same Michael MIC key for both TX and RX */
165 os_memcpy(key, ssid->psk, 16 + 8);
166 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
167 keylen = 32;
168 alg = WPA_ALG_TKIP;
169 break;
170 default:
171 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
172 "WPA-None", wpa_s->group_cipher);
173 return -1;
174 }
175
176 /* TODO: should actually remember the previously used seq#, both for TX
177 * and RX from each STA.. */
178
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800179 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
180 os_memset(key, 0, sizeof(key));
181 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182}
183
184
185static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
186{
187 struct wpa_supplicant *wpa_s = eloop_ctx;
188 const u8 *bssid = wpa_s->bssid;
189 if (is_zero_ether_addr(bssid))
190 bssid = wpa_s->pending_bssid;
191 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
192 MAC2STR(bssid));
193 wpa_blacklist_add(wpa_s, bssid);
194 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800195 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700196 wpa_s->reassociate = 1;
197
198 /*
199 * If we timed out, the AP or the local radio may be busy.
200 * So, wait a second until scanning again.
201 */
202 wpa_supplicant_req_scan(wpa_s, 1, 0);
203}
204
205
206/**
207 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
208 * @wpa_s: Pointer to wpa_supplicant data
209 * @sec: Number of seconds after which to time out authentication
210 * @usec: Number of microseconds after which to time out authentication
211 *
212 * This function is used to schedule a timeout for the current authentication
213 * attempt.
214 */
215void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
216 int sec, int usec)
217{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700218 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700219 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
220 return;
221
222 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
223 "%d usec", sec, usec);
224 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
225 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
226}
227
228
229/**
230 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
231 * @wpa_s: Pointer to wpa_supplicant data
232 *
233 * This function is used to cancel authentication timeout scheduled with
234 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
235 * been completed.
236 */
237void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
238{
239 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
240 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
241 wpa_blacklist_del(wpa_s, wpa_s->bssid);
242}
243
244
245/**
246 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
247 * @wpa_s: Pointer to wpa_supplicant data
248 *
249 * This function is used to configure EAPOL state machine based on the selected
250 * authentication mode.
251 */
252void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
253{
254#ifdef IEEE8021X_EAPOL
255 struct eapol_config eapol_conf;
256 struct wpa_ssid *ssid = wpa_s->current_ssid;
257
258#ifdef CONFIG_IBSS_RSN
259 if (ssid->mode == WPAS_MODE_IBSS &&
260 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
261 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
262 /*
263 * RSN IBSS authentication is per-STA and we can disable the
264 * per-BSSID EAPOL authentication.
265 */
266 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
267 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
268 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
269 return;
270 }
271#endif /* CONFIG_IBSS_RSN */
272
273 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
274 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
275
276 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
277 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
278 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
279 else
280 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
281
282 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
283 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
284 eapol_conf.accept_802_1x_keys = 1;
285 eapol_conf.required_keys = 0;
286 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
287 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
288 }
289 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
290 eapol_conf.required_keys |=
291 EAPOL_REQUIRE_KEY_BROADCAST;
292 }
293
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700294 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700295 eapol_conf.required_keys = 0;
296 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700297 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298 eapol_conf.workaround = ssid->eap_workaround;
299 eapol_conf.eap_disabled =
300 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
301 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
302 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700303 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800304
305#ifdef CONFIG_WPS
306 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
307 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
308 if (wpa_s->current_bss) {
309 struct wpabuf *ie;
310 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
311 WPS_IE_VENDOR_TYPE);
312 if (ie) {
313 if (wps_is_20(ie))
314 eapol_conf.wps |=
315 EAPOL_PEER_IS_WPS20_AP;
316 wpabuf_free(ie);
317 }
318 }
319 }
320#endif /* CONFIG_WPS */
321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700323
324 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800325#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326}
327
328
329/**
330 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
331 * @wpa_s: Pointer to wpa_supplicant data
332 * @ssid: Configuration data for the network
333 *
334 * This function is used to configure WPA state machine and related parameters
335 * to a mode where WPA is not enabled. This is called as part of the
336 * authentication configuration when the selected network does not use WPA.
337 */
338void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
339 struct wpa_ssid *ssid)
340{
341 int i;
342
343 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
344 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
345 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
346 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
347 else
348 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
349 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
350 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
351 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
352 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
353 wpa_s->group_cipher = WPA_CIPHER_NONE;
354 wpa_s->mgmt_group_cipher = 0;
355
356 for (i = 0; i < NUM_WEP_KEYS; i++) {
357 if (ssid->wep_key_len[i] > 5) {
358 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
359 wpa_s->group_cipher = WPA_CIPHER_WEP104;
360 break;
361 } else if (ssid->wep_key_len[i] > 0) {
362 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
363 wpa_s->group_cipher = WPA_CIPHER_WEP40;
364 break;
365 }
366 }
367
368 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
369 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
370 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
371 wpa_s->pairwise_cipher);
372 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
373#ifdef CONFIG_IEEE80211W
374 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
375 wpa_s->mgmt_group_cipher);
376#endif /* CONFIG_IEEE80211W */
377
378 pmksa_cache_clear_current(wpa_s->wpa);
379}
380
381
Dmitry Shmidt04949592012-07-19 12:16:46 -0700382void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800383{
384 int i;
385 if (wpa_s->hw.modes == NULL)
386 return;
387
388 for (i = 0; i < wpa_s->hw.num_modes; i++) {
389 os_free(wpa_s->hw.modes[i].channels);
390 os_free(wpa_s->hw.modes[i].rates);
391 }
392
393 os_free(wpa_s->hw.modes);
394 wpa_s->hw.modes = NULL;
395}
396
397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700398static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
399{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700400 int i;
401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700403 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 scard_deinit(wpa_s->scard);
405 wpa_s->scard = NULL;
406 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
407 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
408 l2_packet_deinit(wpa_s->l2);
409 wpa_s->l2 = NULL;
410 if (wpa_s->l2_br) {
411 l2_packet_deinit(wpa_s->l2_br);
412 wpa_s->l2_br = NULL;
413 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800414#ifdef CONFIG_TESTING_OPTIONS
415 l2_packet_deinit(wpa_s->l2_test);
416 wpa_s->l2_test = NULL;
417#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 if (wpa_s->conf != NULL) {
420 struct wpa_ssid *ssid;
421 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
422 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 }
424
425 os_free(wpa_s->confname);
426 wpa_s->confname = NULL;
427
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700428 os_free(wpa_s->confanother);
429 wpa_s->confanother = NULL;
430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431 wpa_sm_set_eapol(wpa_s->wpa, NULL);
432 eapol_sm_deinit(wpa_s->eapol);
433 wpa_s->eapol = NULL;
434
435 rsn_preauth_deinit(wpa_s->wpa);
436
437#ifdef CONFIG_TDLS
438 wpa_tdls_deinit(wpa_s->wpa);
439#endif /* CONFIG_TDLS */
440
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800441 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 pmksa_candidate_free(wpa_s->wpa);
443 wpa_sm_deinit(wpa_s->wpa);
444 wpa_s->wpa = NULL;
445 wpa_blacklist_clear(wpa_s);
446
447 wpa_bss_deinit(wpa_s);
448
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700449 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450 wpa_supplicant_cancel_scan(wpa_s);
451 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800452 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
453#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
454 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
455 wpa_s, NULL);
456#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457
458 wpas_wps_deinit(wpa_s);
459
460 wpabuf_free(wpa_s->pending_eapol_rx);
461 wpa_s->pending_eapol_rx = NULL;
462
463#ifdef CONFIG_IBSS_RSN
464 ibss_rsn_deinit(wpa_s->ibss_rsn);
465 wpa_s->ibss_rsn = NULL;
466#endif /* CONFIG_IBSS_RSN */
467
468 sme_deinit(wpa_s);
469
470#ifdef CONFIG_AP
471 wpa_supplicant_ap_deinit(wpa_s);
472#endif /* CONFIG_AP */
473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800476#ifdef CONFIG_OFFCHANNEL
477 offchannel_deinit(wpa_s);
478#endif /* CONFIG_OFFCHANNEL */
479
480 wpa_supplicant_cancel_sched_scan(wpa_s);
481
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482 os_free(wpa_s->next_scan_freqs);
483 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800484
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800485 os_free(wpa_s->manual_scan_freqs);
486 wpa_s->manual_scan_freqs = NULL;
487
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700488 os_free(wpa_s->manual_sched_scan_freqs);
489 wpa_s->manual_sched_scan_freqs = NULL;
490
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800491 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
492
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800493 gas_query_deinit(wpa_s->gas);
494 wpa_s->gas = NULL;
495
496 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700497
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700498 ieee802_1x_dealloc_kay_sm(wpa_s);
499
Dmitry Shmidt04949592012-07-19 12:16:46 -0700500 os_free(wpa_s->bssid_filter);
501 wpa_s->bssid_filter = NULL;
502
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800503 os_free(wpa_s->disallow_aps_bssid);
504 wpa_s->disallow_aps_bssid = NULL;
505 os_free(wpa_s->disallow_aps_ssid);
506 wpa_s->disallow_aps_ssid = NULL;
507
Dmitry Shmidt04949592012-07-19 12:16:46 -0700508 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700509#ifdef CONFIG_WNM
510 wnm_deallocate_memory(wpa_s);
511#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700512
513 ext_password_deinit(wpa_s->ext_pw);
514 wpa_s->ext_pw = NULL;
515
516 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800517 wpa_s->last_gas_resp = NULL;
518 wpabuf_free(wpa_s->prev_gas_resp);
519 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700520
521 os_free(wpa_s->last_scan_res);
522 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800523
524#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700525 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800526#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700527
528 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
529 wpabuf_free(wpa_s->vendor_elem[i]);
530 wpa_s->vendor_elem[i] = NULL;
531 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800532
533 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534}
535
536
537/**
538 * wpa_clear_keys - Clear keys configured for the driver
539 * @wpa_s: Pointer to wpa_supplicant data
540 * @addr: Previously used BSSID or %NULL if not available
541 *
542 * This function clears the encryption keys that has been previously configured
543 * for the driver.
544 */
545void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
546{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800547 int i, max;
548
549#ifdef CONFIG_IEEE80211W
550 max = 6;
551#else /* CONFIG_IEEE80211W */
552 max = 4;
553#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554
555 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800556 for (i = 0; i < max; i++) {
557 if (wpa_s->keys_cleared & BIT(i))
558 continue;
559 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
560 NULL, 0);
561 }
562 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
563 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
565 0);
566 /* MLME-SETPROTECTION.request(None) */
567 wpa_drv_mlme_setprotection(
568 wpa_s, addr,
569 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
570 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
571 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800572 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573}
574
575
576/**
577 * wpa_supplicant_state_txt - Get the connection state name as a text string
578 * @state: State (wpa_state; WPA_*)
579 * Returns: The state name as a printable text string
580 */
581const char * wpa_supplicant_state_txt(enum wpa_states state)
582{
583 switch (state) {
584 case WPA_DISCONNECTED:
585 return "DISCONNECTED";
586 case WPA_INACTIVE:
587 return "INACTIVE";
588 case WPA_INTERFACE_DISABLED:
589 return "INTERFACE_DISABLED";
590 case WPA_SCANNING:
591 return "SCANNING";
592 case WPA_AUTHENTICATING:
593 return "AUTHENTICATING";
594 case WPA_ASSOCIATING:
595 return "ASSOCIATING";
596 case WPA_ASSOCIATED:
597 return "ASSOCIATED";
598 case WPA_4WAY_HANDSHAKE:
599 return "4WAY_HANDSHAKE";
600 case WPA_GROUP_HANDSHAKE:
601 return "GROUP_HANDSHAKE";
602 case WPA_COMPLETED:
603 return "COMPLETED";
604 default:
605 return "UNKNOWN";
606 }
607}
608
609
610#ifdef CONFIG_BGSCAN
611
612static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
613{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800614 const char *name;
615
616 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
617 name = wpa_s->current_ssid->bgscan;
618 else
619 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800620 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800621 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800622 if (wpas_driver_bss_selection(wpa_s))
623 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
625 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800626#ifdef CONFIG_P2P
627 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
628 return;
629#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700630
631 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800632 if (wpa_s->current_ssid) {
633 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700634 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
635 "bgscan");
636 /*
637 * Live without bgscan; it is only used as a roaming
638 * optimization, so the initial connection is not
639 * affected.
640 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700641 } else {
642 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700644 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
645 0);
646 if (scan_res) {
647 bgscan_notify_scan(wpa_s, scan_res);
648 wpa_scan_results_free(scan_res);
649 }
650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651 } else
652 wpa_s->bgscan_ssid = NULL;
653}
654
655
656static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
657{
658 if (wpa_s->bgscan_ssid != NULL) {
659 bgscan_deinit(wpa_s);
660 wpa_s->bgscan_ssid = NULL;
661 }
662}
663
664#endif /* CONFIG_BGSCAN */
665
666
Dmitry Shmidt04949592012-07-19 12:16:46 -0700667static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
668{
669 if (autoscan_init(wpa_s, 0))
670 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
671}
672
673
674static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
675{
676 autoscan_deinit(wpa_s);
677}
678
679
680void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
681{
682 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
683 wpa_s->wpa_state == WPA_SCANNING) {
684 autoscan_deinit(wpa_s);
685 wpa_supplicant_start_autoscan(wpa_s);
686 }
687}
688
689
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690/**
691 * wpa_supplicant_set_state - Set current connection state
692 * @wpa_s: Pointer to wpa_supplicant data
693 * @state: The new connection state
694 *
695 * This function is called whenever the connection state changes, e.g.,
696 * association is completed for WPA/WPA2 4-Way Handshake is started.
697 */
698void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
699 enum wpa_states state)
700{
701 enum wpa_states old_state = wpa_s->wpa_state;
702
703 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
704 wpa_supplicant_state_txt(wpa_s->wpa_state),
705 wpa_supplicant_state_txt(state));
706
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800707 if (state == WPA_INTERFACE_DISABLED) {
708 /* Assure normal scan when interface is restored */
709 wpa_s->normal_scans = 0;
710 }
711
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700712 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800713 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700714 /* Reinitialize normal_scan counter */
715 wpa_s->normal_scans = 0;
716 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800717
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718 if (state != WPA_SCANNING)
719 wpa_supplicant_notify_scanning(wpa_s, 0);
720
721 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700723#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800725 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800726 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727 ssid ? ssid->id : -1,
728 ssid && ssid->id_str ? ssid->id_str : "");
729#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700730 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800731 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700732 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733 wpa_drv_set_operstate(wpa_s, 1);
734#ifndef IEEE8021X_EAPOL
735 wpa_drv_set_supp_port(wpa_s, 1);
736#endif /* IEEE8021X_EAPOL */
737 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700738 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700740
741 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
743 state == WPA_ASSOCIATED) {
744 wpa_s->new_connection = 1;
745 wpa_drv_set_operstate(wpa_s, 0);
746#ifndef IEEE8021X_EAPOL
747 wpa_drv_set_supp_port(wpa_s, 0);
748#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700749 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 }
751 wpa_s->wpa_state = state;
752
753#ifdef CONFIG_BGSCAN
754 if (state == WPA_COMPLETED)
755 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800756 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 wpa_supplicant_stop_bgscan(wpa_s);
758#endif /* CONFIG_BGSCAN */
759
Dmitry Shmidt04949592012-07-19 12:16:46 -0700760 if (state == WPA_AUTHENTICATING)
761 wpa_supplicant_stop_autoscan(wpa_s);
762
763 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
764 wpa_supplicant_start_autoscan(wpa_s);
765
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800766 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
767 wmm_ac_notify_disassoc(wpa_s);
768
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769 if (wpa_s->wpa_state != old_state) {
770 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
771
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700772 /*
773 * Notify the P2P Device interface about a state change in one
774 * of the interfaces.
775 */
776 wpas_p2p_indicate_state_change(wpa_s);
777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778 if (wpa_s->wpa_state == WPA_COMPLETED ||
779 old_state == WPA_COMPLETED)
780 wpas_notify_auth_changed(wpa_s);
781 }
782}
783
784
785void wpa_supplicant_terminate_proc(struct wpa_global *global)
786{
787 int pending = 0;
788#ifdef CONFIG_WPS
789 struct wpa_supplicant *wpa_s = global->ifaces;
790 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800791 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700792 if (wpas_wps_terminate_pending(wpa_s) == 1)
793 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700794#ifdef CONFIG_P2P
795 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
796 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
797 wpas_p2p_disconnect(wpa_s);
798#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800799 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800 }
801#endif /* CONFIG_WPS */
802 if (pending)
803 return;
804 eloop_terminate();
805}
806
807
808static void wpa_supplicant_terminate(int sig, void *signal_ctx)
809{
810 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 wpa_supplicant_terminate_proc(global);
812}
813
814
815void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
816{
817 enum wpa_states old_state = wpa_s->wpa_state;
818
819 wpa_s->pairwise_cipher = 0;
820 wpa_s->group_cipher = 0;
821 wpa_s->mgmt_group_cipher = 0;
822 wpa_s->key_mgmt = 0;
823 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700824 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825
826 if (wpa_s->wpa_state != old_state)
827 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
828}
829
830
831/**
832 * wpa_supplicant_reload_configuration - Reload configuration data
833 * @wpa_s: Pointer to wpa_supplicant data
834 * Returns: 0 on success or -1 if configuration parsing failed
835 *
836 * This function can be used to request that the configuration data is reloaded
837 * (e.g., after configuration file change). This function is reloading
838 * configuration only for one interface, so this may need to be called multiple
839 * times if %wpa_supplicant is controlling multiple interfaces and all
840 * interfaces need reconfiguration.
841 */
842int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
843{
844 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700845 int reconf_ctrl;
846 int old_ap_scan;
847
848 if (wpa_s->confname == NULL)
849 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700850 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851 if (conf == NULL) {
852 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
853 "file '%s' - exiting", wpa_s->confname);
854 return -1;
855 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700856 wpa_config_read(wpa_s->confanother, conf);
857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 conf->changed_parameters = (unsigned int) -1;
859
860 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
861 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
862 os_strcmp(conf->ctrl_interface,
863 wpa_s->conf->ctrl_interface) != 0);
864
865 if (reconf_ctrl && wpa_s->ctrl_iface) {
866 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
867 wpa_s->ctrl_iface = NULL;
868 }
869
870 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800871 if (wpa_s->current_ssid) {
872 wpa_supplicant_deauthenticate(wpa_s,
873 WLAN_REASON_DEAUTH_LEAVING);
874 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875
876 /*
877 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800878 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 */
880 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
881 /*
882 * Clear forced success to clear EAP state for next
883 * authentication.
884 */
885 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
886 }
887 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
888 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800889 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
891 rsn_preauth_deinit(wpa_s->wpa);
892
893 old_ap_scan = wpa_s->conf->ap_scan;
894 wpa_config_free(wpa_s->conf);
895 wpa_s->conf = conf;
896 if (old_ap_scan != wpa_s->conf->ap_scan)
897 wpas_notify_ap_scan_changed(wpa_s);
898
899 if (reconf_ctrl)
900 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
901
902 wpa_supplicant_update_config(wpa_s);
903
904 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700905 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906 wpa_s->reassociate = 1;
907 wpa_supplicant_req_scan(wpa_s, 0, 0);
908 }
909 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
910 return 0;
911}
912
913
914static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
915{
916 struct wpa_global *global = signal_ctx;
917 struct wpa_supplicant *wpa_s;
918 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
919 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
920 sig);
921 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
922 wpa_supplicant_terminate_proc(global);
923 }
924 }
925}
926
927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
929 struct wpa_ssid *ssid,
930 struct wpa_ie_data *ie)
931{
932 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
933 if (ret) {
934 if (ret == -2) {
935 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
936 "from association info");
937 }
938 return -1;
939 }
940
941 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
942 "cipher suites");
943 if (!(ie->group_cipher & ssid->group_cipher)) {
944 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
945 "cipher 0x%x (mask 0x%x) - reject",
946 ie->group_cipher, ssid->group_cipher);
947 return -1;
948 }
949 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
950 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
951 "cipher 0x%x (mask 0x%x) - reject",
952 ie->pairwise_cipher, ssid->pairwise_cipher);
953 return -1;
954 }
955 if (!(ie->key_mgmt & ssid->key_mgmt)) {
956 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
957 "management 0x%x (mask 0x%x) - reject",
958 ie->key_mgmt, ssid->key_mgmt);
959 return -1;
960 }
961
962#ifdef CONFIG_IEEE80211W
963 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800964 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
965 wpa_s->conf->pmf : ssid->ieee80211w) ==
966 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
968 "that does not support management frame protection - "
969 "reject");
970 return -1;
971 }
972#endif /* CONFIG_IEEE80211W */
973
974 return 0;
975}
976
977
978/**
979 * wpa_supplicant_set_suites - Set authentication and encryption parameters
980 * @wpa_s: Pointer to wpa_supplicant data
981 * @bss: Scan results for the selected BSS, or %NULL if not available
982 * @ssid: Configuration data for the selected network
983 * @wpa_ie: Buffer for the WPA/RSN IE
984 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
985 * used buffer length in case the functions returns success.
986 * Returns: 0 on success or -1 on failure
987 *
988 * This function is used to configure authentication and encryption parameters
989 * based on the network configuration and scan result for the selected BSS (if
990 * available).
991 */
992int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
993 struct wpa_bss *bss, struct wpa_ssid *ssid,
994 u8 *wpa_ie, size_t *wpa_ie_len)
995{
996 struct wpa_ie_data ie;
997 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800998 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999
1000 if (bss) {
1001 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1002 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001003 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001005 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006
1007 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1008 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1009 (ie.group_cipher & ssid->group_cipher) &&
1010 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1011 (ie.key_mgmt & ssid->key_mgmt)) {
1012 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1013 proto = WPA_PROTO_RSN;
1014 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001015 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 (ie.group_cipher & ssid->group_cipher) &&
1017 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1018 (ie.key_mgmt & ssid->key_mgmt)) {
1019 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1020 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001021#ifdef CONFIG_HS20
1022 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1023 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1024 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001025 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001026 ie.group_cipher = WPA_CIPHER_CCMP;
1027 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1028 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1029 proto = WPA_PROTO_OSEN;
1030#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 } else if (bss) {
1032 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001033 wpa_dbg(wpa_s, MSG_DEBUG,
1034 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1035 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1036 ssid->key_mgmt);
1037 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1038 MAC2STR(bss->bssid),
1039 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1040 bss_wpa ? " WPA" : "",
1041 bss_rsn ? " RSN" : "",
1042 bss_osen ? " OSEN" : "");
1043 if (bss_rsn) {
1044 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1045 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1046 wpa_dbg(wpa_s, MSG_DEBUG,
1047 "Could not parse RSN element");
1048 } else {
1049 wpa_dbg(wpa_s, MSG_DEBUG,
1050 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1051 ie.pairwise_cipher, ie.group_cipher,
1052 ie.key_mgmt);
1053 }
1054 }
1055 if (bss_wpa) {
1056 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1057 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1058 wpa_dbg(wpa_s, MSG_DEBUG,
1059 "Could not parse WPA element");
1060 } else {
1061 wpa_dbg(wpa_s, MSG_DEBUG,
1062 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1063 ie.pairwise_cipher, ie.group_cipher,
1064 ie.key_mgmt);
1065 }
1066 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067 return -1;
1068 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001069 if (ssid->proto & WPA_PROTO_OSEN)
1070 proto = WPA_PROTO_OSEN;
1071 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001072 proto = WPA_PROTO_RSN;
1073 else
1074 proto = WPA_PROTO_WPA;
1075 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1076 os_memset(&ie, 0, sizeof(ie));
1077 ie.group_cipher = ssid->group_cipher;
1078 ie.pairwise_cipher = ssid->pairwise_cipher;
1079 ie.key_mgmt = ssid->key_mgmt;
1080#ifdef CONFIG_IEEE80211W
1081 ie.mgmt_group_cipher =
1082 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1083 WPA_CIPHER_AES_128_CMAC : 0;
1084#endif /* CONFIG_IEEE80211W */
1085 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1086 "based on configuration");
1087 } else
1088 proto = ie.proto;
1089 }
1090
1091 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1092 "pairwise %d key_mgmt %d proto %d",
1093 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1094#ifdef CONFIG_IEEE80211W
1095 if (ssid->ieee80211w) {
1096 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1097 ie.mgmt_group_cipher);
1098 }
1099#endif /* CONFIG_IEEE80211W */
1100
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001101 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1103 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001104 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105
1106 if (bss || !wpa_s->ap_ies_from_associnfo) {
1107 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1108 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1109 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1110 bss_rsn ? 2 + bss_rsn[1] : 0))
1111 return -1;
1112 }
1113
1114 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001115 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1116 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1118 "cipher");
1119 return -1;
1120 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001121 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1122 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123
1124 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001125 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1126 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1128 "cipher");
1129 return -1;
1130 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001131 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1132 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133
1134 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001135#ifdef CONFIG_SAE
1136 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1137 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1138#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 if (0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001140 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1141 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1142 wpa_dbg(wpa_s, MSG_DEBUG,
1143 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144#ifdef CONFIG_IEEE80211R
1145 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1146 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1147 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1148 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1149 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1150 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1151#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001152#ifdef CONFIG_SAE
1153 } else if (sel & WPA_KEY_MGMT_SAE) {
1154 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1155 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1156 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1157 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1158 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1159#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160#ifdef CONFIG_IEEE80211W
1161 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1162 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1163 wpa_dbg(wpa_s, MSG_DEBUG,
1164 "WPA: using KEY_MGMT 802.1X with SHA256");
1165 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1166 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1167 wpa_dbg(wpa_s, MSG_DEBUG,
1168 "WPA: using KEY_MGMT PSK with SHA256");
1169#endif /* CONFIG_IEEE80211W */
1170 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1171 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1172 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1173 } else if (sel & WPA_KEY_MGMT_PSK) {
1174 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1176 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1177 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1178 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001179#ifdef CONFIG_HS20
1180 } else if (sel & WPA_KEY_MGMT_OSEN) {
1181 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1182 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1183#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 } else {
1185 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1186 "authenticated key management type");
1187 return -1;
1188 }
1189
1190 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1191 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1192 wpa_s->pairwise_cipher);
1193 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1194
1195#ifdef CONFIG_IEEE80211W
1196 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001197 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1198 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1200 sel = 0;
1201 if (sel & WPA_CIPHER_AES_128_CMAC) {
1202 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1203 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1204 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001205 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1206 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1207 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1208 "BIP-GMAC-128");
1209 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1210 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1211 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1212 "BIP-GMAC-256");
1213 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1214 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1215 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1216 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217 } else {
1218 wpa_s->mgmt_group_cipher = 0;
1219 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1220 }
1221 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1222 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001223 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1224 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1225 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226#endif /* CONFIG_IEEE80211W */
1227
1228 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1229 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1230 return -1;
1231 }
1232
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001233 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001234 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001235#ifndef CONFIG_NO_PBKDF2
1236 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1237 ssid->passphrase) {
1238 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001239 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1240 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001241 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1242 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001243 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1244 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001245 }
1246#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001247#ifdef CONFIG_EXT_PASSWORD
1248 if (ssid->ext_psk) {
1249 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1250 ssid->ext_psk);
1251 char pw_str[64 + 1];
1252 u8 psk[PMK_LEN];
1253
1254 if (pw == NULL) {
1255 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1256 "found from external storage");
1257 return -1;
1258 }
1259
1260 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1261 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1262 "PSK length %d in external storage",
1263 (int) wpabuf_len(pw));
1264 ext_password_free(pw);
1265 return -1;
1266 }
1267
1268 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1269 pw_str[wpabuf_len(pw)] = '\0';
1270
1271#ifndef CONFIG_NO_PBKDF2
1272 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1273 {
1274 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1275 4096, psk, PMK_LEN);
1276 os_memset(pw_str, 0, sizeof(pw_str));
1277 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1278 "external passphrase)",
1279 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001280 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1281 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001282 } else
1283#endif /* CONFIG_NO_PBKDF2 */
1284 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1285 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1286 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1287 "Invalid PSK hex string");
1288 os_memset(pw_str, 0, sizeof(pw_str));
1289 ext_password_free(pw);
1290 return -1;
1291 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001292 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1293 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001294 } else {
1295 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1296 "PSK available");
1297 os_memset(pw_str, 0, sizeof(pw_str));
1298 ext_password_free(pw);
1299 return -1;
1300 }
1301
1302 os_memset(pw_str, 0, sizeof(pw_str));
1303 ext_password_free(pw);
1304 }
1305#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001306 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1308
1309 return 0;
1310}
1311
1312
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001313static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1314{
1315 *pos = 0x00;
1316
1317 switch (idx) {
1318 case 0: /* Bits 0-7 */
1319 break;
1320 case 1: /* Bits 8-15 */
1321 break;
1322 case 2: /* Bits 16-23 */
1323#ifdef CONFIG_WNM
1324 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1325 *pos |= 0x08; /* Bit 19 - BSS Transition */
1326#endif /* CONFIG_WNM */
1327 break;
1328 case 3: /* Bits 24-31 */
1329#ifdef CONFIG_WNM
1330 *pos |= 0x02; /* Bit 25 - SSID List */
1331#endif /* CONFIG_WNM */
1332#ifdef CONFIG_INTERWORKING
1333 if (wpa_s->conf->interworking)
1334 *pos |= 0x80; /* Bit 31 - Interworking */
1335#endif /* CONFIG_INTERWORKING */
1336 break;
1337 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001338#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001339 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1340 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001341#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001342 break;
1343 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001344#ifdef CONFIG_HS20
1345 if (wpa_s->conf->hs20)
1346 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1347#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001348 break;
1349 case 6: /* Bits 48-55 */
1350 break;
1351 }
1352}
1353
1354
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001355int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001356{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001357 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001358 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001359
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001360 if (len < wpa_s->extended_capa_len)
1361 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001362 if (buflen < (size_t) len + 2) {
1363 wpa_printf(MSG_INFO,
1364 "Not enough room for building extended capabilities element");
1365 return -1;
1366 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001367
1368 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001369 *pos++ = len;
1370 for (i = 0; i < len; i++, pos++) {
1371 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001372
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001373 if (i < wpa_s->extended_capa_len) {
1374 *pos &= ~wpa_s->extended_capa_mask[i];
1375 *pos |= wpa_s->extended_capa[i];
1376 }
1377 }
1378
1379 while (len > 0 && buf[1 + len] == 0) {
1380 len--;
1381 buf[1] = len;
1382 }
1383 if (len == 0)
1384 return 0;
1385
1386 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001387}
1388
1389
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001390static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1391 struct wpa_bss *test_bss)
1392{
1393 struct wpa_bss *bss;
1394
1395 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1396 if (bss == test_bss)
1397 return 1;
1398 }
1399
1400 return 0;
1401}
1402
1403
1404static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1405 struct wpa_ssid *test_ssid)
1406{
1407 struct wpa_ssid *ssid;
1408
1409 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1410 if (ssid == test_ssid)
1411 return 1;
1412 }
1413
1414 return 0;
1415}
1416
1417
1418int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1419 struct wpa_ssid *test_ssid)
1420{
1421 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1422 return 0;
1423
1424 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1425}
1426
1427
1428void wpas_connect_work_free(struct wpa_connect_work *cwork)
1429{
1430 if (cwork == NULL)
1431 return;
1432 os_free(cwork);
1433}
1434
1435
1436void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1437{
1438 struct wpa_connect_work *cwork;
1439 struct wpa_radio_work *work = wpa_s->connect_work;
1440
1441 if (!work)
1442 return;
1443
1444 wpa_s->connect_work = NULL;
1445 cwork = work->ctx;
1446 work->ctx = NULL;
1447 wpas_connect_work_free(cwork);
1448 radio_work_done(work);
1449}
1450
1451
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001452int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1453{
1454 struct os_reltime now;
1455 u8 addr[ETH_ALEN];
1456
1457 os_get_reltime(&now);
1458 if (wpa_s->last_mac_addr_style == style &&
1459 wpa_s->last_mac_addr_change.sec != 0 &&
1460 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1461 wpa_s->conf->rand_addr_lifetime)) {
1462 wpa_msg(wpa_s, MSG_DEBUG,
1463 "Previously selected random MAC address has not yet expired");
1464 return 0;
1465 }
1466
1467 switch (style) {
1468 case 1:
1469 if (random_mac_addr(addr) < 0)
1470 return -1;
1471 break;
1472 case 2:
1473 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1474 if (random_mac_addr_keep_oui(addr) < 0)
1475 return -1;
1476 break;
1477 default:
1478 return -1;
1479 }
1480
1481 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1482 wpa_msg(wpa_s, MSG_INFO,
1483 "Failed to set random MAC address");
1484 return -1;
1485 }
1486
1487 os_get_reltime(&wpa_s->last_mac_addr_change);
1488 wpa_s->mac_addr_changed = 1;
1489 wpa_s->last_mac_addr_style = style;
1490
1491 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1492 wpa_msg(wpa_s, MSG_INFO,
1493 "Could not update MAC address information");
1494 return -1;
1495 }
1496
1497 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1498 MAC2STR(addr));
1499
1500 return 0;
1501}
1502
1503
1504int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1505{
1506 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1507 !wpa_s->conf->preassoc_mac_addr)
1508 return 0;
1509
1510 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1511}
1512
1513
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001514static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516/**
1517 * wpa_supplicant_associate - Request association
1518 * @wpa_s: Pointer to wpa_supplicant data
1519 * @bss: Scan results for the selected BSS, or %NULL if not available
1520 * @ssid: Configuration data for the selected network
1521 *
1522 * This function is used to request %wpa_supplicant to associate with a BSS.
1523 */
1524void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1525 struct wpa_bss *bss, struct wpa_ssid *ssid)
1526{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001527 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001528 int rand_style;
1529
1530 if (ssid->mac_addr == -1)
1531 rand_style = wpa_s->conf->mac_addr;
1532 else
1533 rand_style = ssid->mac_addr;
1534
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001535 wmm_ac_clear_saved_tspecs(wpa_s);
1536 wpa_s->reassoc_same_bss = 0;
1537
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001538 if (wpa_s->last_ssid == ssid) {
1539 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001540 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1541 wmm_ac_save_tspecs(wpa_s);
1542 wpa_s->reassoc_same_bss = 1;
1543 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001544 } else if (rand_style > 0) {
1545 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1546 return;
1547 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1548 } else if (wpa_s->mac_addr_changed) {
1549 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1550 wpa_msg(wpa_s, MSG_INFO,
1551 "Could not restore permanent MAC address");
1552 return;
1553 }
1554 wpa_s->mac_addr_changed = 0;
1555 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1556 wpa_msg(wpa_s, MSG_INFO,
1557 "Could not update MAC address information");
1558 return;
1559 }
1560 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1561 }
1562 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001563
1564#ifdef CONFIG_IBSS_RSN
1565 ibss_rsn_deinit(wpa_s->ibss_rsn);
1566 wpa_s->ibss_rsn = NULL;
1567#endif /* CONFIG_IBSS_RSN */
1568
1569 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1570 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1571#ifdef CONFIG_AP
1572 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1573 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1574 "mode");
1575 return;
1576 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001577 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1578 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001579 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1580 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001581 return;
1582 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001583 wpa_s->current_bss = bss;
1584#else /* CONFIG_AP */
1585 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1586 "the build");
1587#endif /* CONFIG_AP */
1588 return;
1589 }
1590
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001591 if (ssid->mode == WPAS_MODE_MESH) {
1592#ifdef CONFIG_MESH
1593 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1594 wpa_msg(wpa_s, MSG_INFO,
1595 "Driver does not support mesh mode");
1596 return;
1597 }
1598 if (bss)
1599 ssid->frequency = bss->freq;
1600 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1601 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1602 return;
1603 }
1604 wpa_s->current_bss = bss;
1605 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1606 "ssid=\"%s\" id=%d",
1607 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1608 ssid->id);
1609#else /* CONFIG_MESH */
1610 wpa_msg(wpa_s, MSG_ERROR,
1611 "mesh mode support not included in the build");
1612#endif /* CONFIG_MESH */
1613 return;
1614 }
1615
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001616#ifdef CONFIG_TDLS
1617 if (bss)
1618 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1619 bss->ie_len);
1620#endif /* CONFIG_TDLS */
1621
1622 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1623 ssid->mode == IEEE80211_MODE_INFRA) {
1624 sme_authenticate(wpa_s, bss, ssid);
1625 return;
1626 }
1627
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001628 if (wpa_s->connect_work) {
1629 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1630 return;
1631 }
1632
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001633 if (radio_work_pending(wpa_s, "connect")) {
1634 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1635 return;
1636 }
1637
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001638 cwork = os_zalloc(sizeof(*cwork));
1639 if (cwork == NULL)
1640 return;
1641
1642 cwork->bss = bss;
1643 cwork->ssid = ssid;
1644
1645 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1646 wpas_start_assoc_cb, cwork) < 0) {
1647 os_free(cwork);
1648 }
1649}
1650
1651
1652static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1653{
1654 struct wpa_connect_work *cwork = work->ctx;
1655 struct wpa_bss *bss = cwork->bss;
1656 struct wpa_ssid *ssid = cwork->ssid;
1657 struct wpa_supplicant *wpa_s = work->wpa_s;
1658 u8 wpa_ie[200];
1659 size_t wpa_ie_len;
1660 int use_crypt, ret, i, bssid_changed;
1661 int algs = WPA_AUTH_ALG_OPEN;
1662 unsigned int cipher_pairwise, cipher_group;
1663 struct wpa_driver_associate_params params;
1664 int wep_keys_set = 0;
1665 int assoc_failed = 0;
1666 struct wpa_ssid *old_ssid;
1667#ifdef CONFIG_HT_OVERRIDES
1668 struct ieee80211_ht_capabilities htcaps;
1669 struct ieee80211_ht_capabilities htcaps_mask;
1670#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001671#ifdef CONFIG_VHT_OVERRIDES
1672 struct ieee80211_vht_capabilities vhtcaps;
1673 struct ieee80211_vht_capabilities vhtcaps_mask;
1674#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001675
1676 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001677 if (work->started) {
1678 wpa_s->connect_work = NULL;
1679
1680 /* cancel possible auth. timeout */
1681 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1682 NULL);
1683 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001684 wpas_connect_work_free(cwork);
1685 return;
1686 }
1687
1688 wpa_s->connect_work = work;
1689
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001690 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001691 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1692 wpas_connect_work_done(wpa_s);
1693 return;
1694 }
1695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 os_memset(&params, 0, sizeof(params));
1697 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001698 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001699 if (bss &&
1700 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001701#ifdef CONFIG_IEEE80211R
1702 const u8 *ie, *md = NULL;
1703#endif /* CONFIG_IEEE80211R */
1704 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1705 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1706 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1707 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1708 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1709 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1710 if (bssid_changed)
1711 wpas_notify_bssid_changed(wpa_s);
1712#ifdef CONFIG_IEEE80211R
1713 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1714 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1715 md = ie + 2;
1716 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1717 if (md) {
1718 /* Prepare for the next transition */
1719 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1720 }
1721#endif /* CONFIG_IEEE80211R */
1722#ifdef CONFIG_WPS
1723 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1724 wpa_s->conf->ap_scan == 2 &&
1725 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1726 /* Use ap_scan==1 style network selection to find the network
1727 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001728 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001729 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730 wpa_s->reassociate = 1;
1731 wpa_supplicant_req_scan(wpa_s, 0, 0);
1732 return;
1733#endif /* CONFIG_WPS */
1734 } else {
1735 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1736 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1737 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1738 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001739 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001740 wpa_supplicant_cancel_scan(wpa_s);
1741
1742 /* Starting new association, so clear the possibly used WPA IE from the
1743 * previous association. */
1744 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1745
1746#ifdef IEEE8021X_EAPOL
1747 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1748 if (ssid->leap) {
1749 if (ssid->non_leap == 0)
1750 algs = WPA_AUTH_ALG_LEAP;
1751 else
1752 algs |= WPA_AUTH_ALG_LEAP;
1753 }
1754 }
1755#endif /* IEEE8021X_EAPOL */
1756 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1757 if (ssid->auth_alg) {
1758 algs = ssid->auth_alg;
1759 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1760 "0x%x", algs);
1761 }
1762
1763 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1764 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001765 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001767 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1768 wpa_s->conf->okc :
1769 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 (ssid->proto & WPA_PROTO_RSN);
1771 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001772 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1774 wpa_ie_len = sizeof(wpa_ie);
1775 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1776 wpa_ie, &wpa_ie_len)) {
1777 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1778 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001779 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 return;
1781 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001782 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1783 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1784 /*
1785 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1786 * use non-WPA since the scan results did not indicate that the
1787 * AP is using WPA or WPA2.
1788 */
1789 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1790 wpa_ie_len = 0;
1791 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001792 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001793 wpa_ie_len = sizeof(wpa_ie);
1794 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1795 wpa_ie, &wpa_ie_len)) {
1796 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1797 "key management and encryption suites (no "
1798 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001799 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800 return;
1801 }
1802#ifdef CONFIG_WPS
1803 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1804 struct wpabuf *wps_ie;
1805 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1806 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1807 wpa_ie_len = wpabuf_len(wps_ie);
1808 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1809 } else
1810 wpa_ie_len = 0;
1811 wpabuf_free(wps_ie);
1812 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1813 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1814 params.wps = WPS_MODE_PRIVACY;
1815 else
1816 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001817 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001818#endif /* CONFIG_WPS */
1819 } else {
1820 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1821 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001822 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823 }
1824
1825#ifdef CONFIG_P2P
1826 if (wpa_s->global->p2p) {
1827 u8 *pos;
1828 size_t len;
1829 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830 pos = wpa_ie + wpa_ie_len;
1831 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001832 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1833 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 if (res >= 0)
1835 wpa_ie_len += res;
1836 }
1837
1838 wpa_s->cross_connect_disallowed = 0;
1839 if (bss) {
1840 struct wpabuf *p2p;
1841 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1842 if (p2p) {
1843 wpa_s->cross_connect_disallowed =
1844 p2p_get_cross_connect_disallowed(p2p);
1845 wpabuf_free(p2p);
1846 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1847 "connection",
1848 wpa_s->cross_connect_disallowed ?
1849 "disallows" : "allows");
1850 }
1851 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001852
1853 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854#endif /* CONFIG_P2P */
1855
Dmitry Shmidt04949592012-07-19 12:16:46 -07001856#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001857 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001858 struct wpabuf *hs20;
1859 hs20 = wpabuf_alloc(20);
1860 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001861 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001862 size_t len;
1863
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001864 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001865 len = sizeof(wpa_ie) - wpa_ie_len;
1866 if (wpabuf_len(hs20) <= len) {
1867 os_memcpy(wpa_ie + wpa_ie_len,
1868 wpabuf_head(hs20), wpabuf_len(hs20));
1869 wpa_ie_len += wpabuf_len(hs20);
1870 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001871 wpabuf_free(hs20);
1872 }
1873 }
1874#endif /* CONFIG_HS20 */
1875
Dmitry Shmidt56052862013-10-04 10:23:25 -07001876 /*
1877 * Workaround: Add Extended Capabilities element only if the AP
1878 * included this element in Beacon/Probe Response frames. Some older
1879 * APs seem to have interoperability issues if this element is
1880 * included, so while the standard may require us to include the
1881 * element in all cases, it is justifiable to skip it to avoid
1882 * interoperability issues.
1883 */
1884 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001885 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001886 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001887 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1888 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001889 if (ext_capab_len > 0) {
1890 u8 *pos = wpa_ie;
1891 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1892 pos += 2 + pos[1];
1893 os_memmove(pos + ext_capab_len, pos,
1894 wpa_ie_len - (pos - wpa_ie));
1895 wpa_ie_len += ext_capab_len;
1896 os_memcpy(pos, ext_capab, ext_capab_len);
1897 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001898 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1901 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001902 cipher_pairwise = wpa_s->pairwise_cipher;
1903 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1905 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1906 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1907 use_crypt = 0;
1908 if (wpa_set_wep_keys(wpa_s, ssid)) {
1909 use_crypt = 1;
1910 wep_keys_set = 1;
1911 }
1912 }
1913 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1914 use_crypt = 0;
1915
1916#ifdef IEEE8021X_EAPOL
1917 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1918 if ((ssid->eapol_flags &
1919 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1920 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1921 !wep_keys_set) {
1922 use_crypt = 0;
1923 } else {
1924 /* Assume that dynamic WEP-104 keys will be used and
1925 * set cipher suites in order for drivers to expect
1926 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001927 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928 }
1929 }
1930#endif /* IEEE8021X_EAPOL */
1931
1932 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1933 /* Set the key before (and later after) association */
1934 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1935 }
1936
1937 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1938 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 params.ssid = bss->ssid;
1940 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001941 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1942 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1943 MACSTR " freq=%u MHz based on scan results "
1944 "(bssid_set=%d)",
1945 MAC2STR(bss->bssid), bss->freq,
1946 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001947 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001948 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001949 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001950 params.bssid_hint = bss->bssid;
1951 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001952 } else {
1953 params.ssid = ssid->ssid;
1954 params.ssid_len = ssid->ssid_len;
1955 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001956
1957 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1958 wpa_s->conf->ap_scan == 2) {
1959 params.bssid = ssid->bssid;
1960 params.fixed_bssid = 1;
1961 }
1962
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001963 /* Initial frequency for IBSS/mesh */
1964 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
1965 ssid->frequency > 0 && params.freq.freq == 0) {
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001966 enum hostapd_hw_mode hw_mode;
1967 u8 channel;
1968
1969 params.freq.freq = ssid->frequency;
1970
1971 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1972 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1973 if (wpa_s->hw.modes[i].mode == hw_mode) {
1974 struct hostapd_hw_modes *mode;
1975
1976 mode = &wpa_s->hw.modes[i];
1977 params.freq.ht_enabled = ht_supported(mode);
1978 break;
1979 }
1980 }
1981 }
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001982
1983 if (ssid->mode == WPAS_MODE_IBSS) {
1984 if (ssid->beacon_int)
1985 params.beacon_int = ssid->beacon_int;
1986 else
1987 params.beacon_int = wpa_s->conf->beacon_int;
1988 }
1989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990 params.wpa_ie = wpa_ie;
1991 params.wpa_ie_len = wpa_ie_len;
1992 params.pairwise_suite = cipher_pairwise;
1993 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001994 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001995 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996 params.auth_alg = algs;
1997 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001998 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999 for (i = 0; i < NUM_WEP_KEYS; i++) {
2000 if (ssid->wep_key_len[i])
2001 params.wep_key[i] = ssid->wep_key[i];
2002 params.wep_key_len[i] = ssid->wep_key_len[i];
2003 }
2004 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2005
2006 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002007 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2008 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 params.passphrase = ssid->passphrase;
2010 if (ssid->psk_set)
2011 params.psk = ssid->psk;
2012 }
2013
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002014 if (wpa_s->conf->key_mgmt_offload) {
2015 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2016 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
2017 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B)
2018 params.req_key_mgmt_offload =
2019 ssid->proactive_key_caching < 0 ?
2020 wpa_s->conf->okc : ssid->proactive_key_caching;
2021 else
2022 params.req_key_mgmt_offload = 1;
2023
2024 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2025 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2026 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2027 ssid->psk_set)
2028 params.psk = ssid->psk;
2029 }
2030
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031 params.drop_unencrypted = use_crypt;
2032
2033#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002034 params.mgmt_frame_protection =
2035 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
2036 wpa_s->conf->pmf : ssid->ieee80211w;
2037 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2039 struct wpa_ie_data ie;
2040 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2041 ie.capabilities &
2042 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2043 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2044 "MFP: require MFP");
2045 params.mgmt_frame_protection =
2046 MGMT_FRAME_PROTECTION_REQUIRED;
2047 }
2048 }
2049#endif /* CONFIG_IEEE80211W */
2050
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002051 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052
2053 if (wpa_s->parent->set_sta_uapsd)
2054 params.uapsd = wpa_s->parent->sta_uapsd;
2055 else
2056 params.uapsd = -1;
2057
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002058#ifdef CONFIG_HT_OVERRIDES
2059 os_memset(&htcaps, 0, sizeof(htcaps));
2060 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2061 params.htcaps = (u8 *) &htcaps;
2062 params.htcaps_mask = (u8 *) &htcaps_mask;
2063 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2064#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002065#ifdef CONFIG_VHT_OVERRIDES
2066 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2067 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2068 params.vhtcaps = &vhtcaps;
2069 params.vhtcaps_mask = &vhtcaps_mask;
2070 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
2071#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002072
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002073#ifdef CONFIG_P2P
2074 /*
2075 * If multi-channel concurrency is not supported, check for any
2076 * frequency conflict. In case of any frequency conflict, remove the
2077 * least prioritized connection.
2078 */
2079 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002080 int freq, num;
2081 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002082 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002083 wpa_printf(MSG_DEBUG,
2084 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002085 freq, params.freq.freq);
2086 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002087 wpa_s, params.freq.freq, ssid) < 0) {
2088 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002089 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002090 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002091 }
2092 }
2093#endif /* CONFIG_P2P */
2094
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002095 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002096 if (ret < 0) {
2097 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2098 "failed");
2099 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2100 /*
2101 * The driver is known to mean what is saying, so we
2102 * can stop right here; the association will not
2103 * succeed.
2104 */
2105 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002106 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2108 return;
2109 }
2110 /* try to continue anyway; new association will be tried again
2111 * after timeout */
2112 assoc_failed = 1;
2113 }
2114
2115 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2116 /* Set the key after the association just in case association
2117 * cleared the previously configured key. */
2118 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2119 /* No need to timeout authentication since there is no key
2120 * management. */
2121 wpa_supplicant_cancel_auth_timeout(wpa_s);
2122 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2123#ifdef CONFIG_IBSS_RSN
2124 } else if (ssid->mode == WPAS_MODE_IBSS &&
2125 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2126 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2127 /*
2128 * RSN IBSS authentication is per-STA and we can disable the
2129 * per-BSSID authentication.
2130 */
2131 wpa_supplicant_cancel_auth_timeout(wpa_s);
2132#endif /* CONFIG_IBSS_RSN */
2133 } else {
2134 /* Timeout for IEEE 802.11 authentication and association */
2135 int timeout = 60;
2136
2137 if (assoc_failed) {
2138 /* give IBSS a bit more time */
2139 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2140 } else if (wpa_s->conf->ap_scan == 1) {
2141 /* give IBSS a bit more time */
2142 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2143 }
2144 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2145 }
2146
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002147 if (wep_keys_set &&
2148 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149 /* Set static WEP keys again */
2150 wpa_set_wep_keys(wpa_s, ssid);
2151 }
2152
2153 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2154 /*
2155 * Do not allow EAP session resumption between different
2156 * network configurations.
2157 */
2158 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2159 }
2160 old_ssid = wpa_s->current_ssid;
2161 wpa_s->current_ssid = ssid;
2162 wpa_s->current_bss = bss;
2163 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2164 wpa_supplicant_initiate_eapol(wpa_s);
2165 if (old_ssid != wpa_s->current_ssid)
2166 wpas_notify_network_changed(wpa_s);
2167}
2168
2169
2170static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2171 const u8 *addr)
2172{
2173 struct wpa_ssid *old_ssid;
2174
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002175 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002177 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002178 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179 wpa_sm_set_config(wpa_s->wpa, NULL);
2180 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2181 if (old_ssid != wpa_s->current_ssid)
2182 wpas_notify_network_changed(wpa_s);
2183 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2184}
2185
2186
2187/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002188 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2189 * @wpa_s: Pointer to wpa_supplicant data
2190 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2191 *
2192 * This function is used to request %wpa_supplicant to deauthenticate from the
2193 * current AP.
2194 */
2195void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2196 int reason_code)
2197{
2198 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002199 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002200 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002201
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002202 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2203 " pending_bssid=" MACSTR " reason=%d state=%s",
2204 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2205 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2206
2207 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002208 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002209 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2210 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2211 wpa_s->wpa_state == WPA_ASSOCIATING))
2212 addr = wpa_s->pending_bssid;
2213 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2214 /*
2215 * When using driver-based BSS selection, we may not know the
2216 * BSSID with which we are currently trying to associate. We
2217 * need to notify the driver of this disconnection even in such
2218 * a case, so use the all zeros address here.
2219 */
2220 addr = wpa_s->bssid;
2221 zero_addr = 1;
2222 }
2223
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002224#ifdef CONFIG_TDLS
2225 wpa_tdls_teardown_peers(wpa_s->wpa);
2226#endif /* CONFIG_TDLS */
2227
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002228#ifdef CONFIG_MESH
2229 if (wpa_s->ifmsh) {
2230 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2231 wpa_s->ifname);
2232 wpa_supplicant_leave_mesh(wpa_s);
2233 }
2234#endif /* CONFIG_MESH */
2235
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002236 if (addr) {
2237 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002238 os_memset(&event, 0, sizeof(event));
2239 event.deauth_info.reason_code = (u16) reason_code;
2240 event.deauth_info.locally_generated = 1;
2241 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002242 if (zero_addr)
2243 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244 }
2245
2246 wpa_supplicant_clear_connection(wpa_s, addr);
2247}
2248
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002249static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2250 struct wpa_ssid *ssid)
2251{
2252 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2253 return;
2254
2255 ssid->disabled = 0;
2256 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2257 wpas_notify_network_enabled_changed(wpa_s, ssid);
2258
2259 /*
2260 * Try to reassociate since there is no current configuration and a new
2261 * network was made available.
2262 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002263 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002264 wpa_s->reassociate = 1;
2265}
2266
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002267
2268/**
2269 * wpa_supplicant_enable_network - Mark a configured network as enabled
2270 * @wpa_s: wpa_supplicant structure for a network interface
2271 * @ssid: wpa_ssid structure for a configured network or %NULL
2272 *
2273 * Enables the specified network or all networks if no network specified.
2274 */
2275void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2276 struct wpa_ssid *ssid)
2277{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002279 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2280 wpa_supplicant_enable_one_network(wpa_s, ssid);
2281 } else
2282 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002283
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002284 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002285 if (wpa_s->sched_scanning) {
2286 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2287 "new network to scan filters");
2288 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002289 }
2290
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002291 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2292 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293 }
2294}
2295
2296
2297/**
2298 * wpa_supplicant_disable_network - Mark a configured network as disabled
2299 * @wpa_s: wpa_supplicant structure for a network interface
2300 * @ssid: wpa_ssid structure for a configured network or %NULL
2301 *
2302 * Disables the specified network or all networks if no network specified.
2303 */
2304void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2305 struct wpa_ssid *ssid)
2306{
2307 struct wpa_ssid *other_ssid;
2308 int was_disabled;
2309
2310 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002311 if (wpa_s->sched_scanning)
2312 wpa_supplicant_cancel_sched_scan(wpa_s);
2313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2315 other_ssid = other_ssid->next) {
2316 was_disabled = other_ssid->disabled;
2317 if (was_disabled == 2)
2318 continue; /* do not change persistent P2P group
2319 * data */
2320
2321 other_ssid->disabled = 1;
2322
2323 if (was_disabled != other_ssid->disabled)
2324 wpas_notify_network_enabled_changed(
2325 wpa_s, other_ssid);
2326 }
2327 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002328 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002329 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2330 } else if (ssid->disabled != 2) {
2331 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002332 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2334
2335 was_disabled = ssid->disabled;
2336
2337 ssid->disabled = 1;
2338
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002339 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002341 if (wpa_s->sched_scanning) {
2342 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2343 "to remove network from filters");
2344 wpa_supplicant_cancel_sched_scan(wpa_s);
2345 wpa_supplicant_req_scan(wpa_s, 0, 0);
2346 }
2347 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 }
2349}
2350
2351
2352/**
2353 * wpa_supplicant_select_network - Attempt association with a network
2354 * @wpa_s: wpa_supplicant structure for a network interface
2355 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2356 */
2357void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2358 struct wpa_ssid *ssid)
2359{
2360
2361 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002362 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002363
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002364 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002365 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002367 disconnected = 1;
2368 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002369
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 if (ssid)
2371 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 /*
2374 * Mark all other networks disabled or mark all networks enabled if no
2375 * network specified.
2376 */
2377 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2378 other_ssid = other_ssid->next) {
2379 int was_disabled = other_ssid->disabled;
2380 if (was_disabled == 2)
2381 continue; /* do not change persistent P2P group data */
2382
2383 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002384 if (was_disabled && !other_ssid->disabled)
2385 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386
2387 if (was_disabled != other_ssid->disabled)
2388 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2389 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002390
2391 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2392 /* We are already associated with the selected network */
2393 wpa_printf(MSG_DEBUG, "Already associated with the "
2394 "selected network - do nothing");
2395 return;
2396 }
2397
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002398 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002399 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002400 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002401 wpa_s->connect_without_scan =
2402 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
2403 } else {
2404 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002405 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 wpa_s->disconnected = 0;
2408 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002409
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002410 if (wpa_s->connect_without_scan ||
2411 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002412 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413
2414 if (ssid)
2415 wpas_notify_network_selected(wpa_s, ssid);
2416}
2417
2418
2419/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002420 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2421 * @wpa_s: wpa_supplicant structure for a network interface
2422 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2423 * @pkcs11_module_path: PKCS #11 module path or NULL
2424 * Returns: 0 on success; -1 on failure
2425 *
2426 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2427 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2428 * module path fails the paths will be reset to the default value (NULL).
2429 */
2430int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2431 const char *pkcs11_engine_path,
2432 const char *pkcs11_module_path)
2433{
2434 char *pkcs11_engine_path_copy = NULL;
2435 char *pkcs11_module_path_copy = NULL;
2436
2437 if (pkcs11_engine_path != NULL) {
2438 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2439 if (pkcs11_engine_path_copy == NULL)
2440 return -1;
2441 }
2442 if (pkcs11_module_path != NULL) {
2443 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002444 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002445 os_free(pkcs11_engine_path_copy);
2446 return -1;
2447 }
2448 }
2449
2450 os_free(wpa_s->conf->pkcs11_engine_path);
2451 os_free(wpa_s->conf->pkcs11_module_path);
2452 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2453 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2454
2455 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2456 eapol_sm_deinit(wpa_s->eapol);
2457 wpa_s->eapol = NULL;
2458 if (wpa_supplicant_init_eapol(wpa_s)) {
2459 /* Error -> Reset paths to the default value (NULL) once. */
2460 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2461 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2462 NULL);
2463
2464 return -1;
2465 }
2466 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2467
2468 return 0;
2469}
2470
2471
2472/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2474 * @wpa_s: wpa_supplicant structure for a network interface
2475 * @ap_scan: AP scan mode
2476 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2477 *
2478 */
2479int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2480{
2481
2482 int old_ap_scan;
2483
2484 if (ap_scan < 0 || ap_scan > 2)
2485 return -1;
2486
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002487#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002488 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2489 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2490 wpa_s->wpa_state < WPA_COMPLETED) {
2491 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2492 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002493 return 0;
2494 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002495#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 old_ap_scan = wpa_s->conf->ap_scan;
2498 wpa_s->conf->ap_scan = ap_scan;
2499
2500 if (old_ap_scan != wpa_s->conf->ap_scan)
2501 wpas_notify_ap_scan_changed(wpa_s);
2502
2503 return 0;
2504}
2505
2506
2507/**
2508 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2509 * @wpa_s: wpa_supplicant structure for a network interface
2510 * @expire_age: Expiration age in seconds
2511 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2512 *
2513 */
2514int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2515 unsigned int bss_expire_age)
2516{
2517 if (bss_expire_age < 10) {
2518 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2519 bss_expire_age);
2520 return -1;
2521 }
2522 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2523 bss_expire_age);
2524 wpa_s->conf->bss_expiration_age = bss_expire_age;
2525
2526 return 0;
2527}
2528
2529
2530/**
2531 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2532 * @wpa_s: wpa_supplicant structure for a network interface
2533 * @expire_count: number of scans after which an unseen BSS is reclaimed
2534 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2535 *
2536 */
2537int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2538 unsigned int bss_expire_count)
2539{
2540 if (bss_expire_count < 1) {
2541 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2542 bss_expire_count);
2543 return -1;
2544 }
2545 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2546 bss_expire_count);
2547 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2548
2549 return 0;
2550}
2551
2552
2553/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002554 * wpa_supplicant_set_scan_interval - Set scan interval
2555 * @wpa_s: wpa_supplicant structure for a network interface
2556 * @scan_interval: scan interval in seconds
2557 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2558 *
2559 */
2560int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2561 int scan_interval)
2562{
2563 if (scan_interval < 0) {
2564 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2565 scan_interval);
2566 return -1;
2567 }
2568 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2569 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002570 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002571
2572 return 0;
2573}
2574
2575
2576/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 * wpa_supplicant_set_debug_params - Set global debug params
2578 * @global: wpa_global structure
2579 * @debug_level: debug level
2580 * @debug_timestamp: determines if show timestamp in debug data
2581 * @debug_show_keys: determines if show keys in debug data
2582 * Returns: 0 if succeed or -1 if debug_level has wrong value
2583 */
2584int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2585 int debug_timestamp, int debug_show_keys)
2586{
2587
2588 int old_level, old_timestamp, old_show_keys;
2589
2590 /* check for allowed debuglevels */
2591 if (debug_level != MSG_EXCESSIVE &&
2592 debug_level != MSG_MSGDUMP &&
2593 debug_level != MSG_DEBUG &&
2594 debug_level != MSG_INFO &&
2595 debug_level != MSG_WARNING &&
2596 debug_level != MSG_ERROR)
2597 return -1;
2598
2599 old_level = wpa_debug_level;
2600 old_timestamp = wpa_debug_timestamp;
2601 old_show_keys = wpa_debug_show_keys;
2602
2603 wpa_debug_level = debug_level;
2604 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2605 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2606
2607 if (wpa_debug_level != old_level)
2608 wpas_notify_debug_level_changed(global);
2609 if (wpa_debug_timestamp != old_timestamp)
2610 wpas_notify_debug_timestamp_changed(global);
2611 if (wpa_debug_show_keys != old_show_keys)
2612 wpas_notify_debug_show_keys_changed(global);
2613
2614 return 0;
2615}
2616
2617
2618/**
2619 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2620 * @wpa_s: Pointer to wpa_supplicant data
2621 * Returns: A pointer to the current network structure or %NULL on failure
2622 */
2623struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2624{
2625 struct wpa_ssid *entry;
2626 u8 ssid[MAX_SSID_LEN];
2627 int res;
2628 size_t ssid_len;
2629 u8 bssid[ETH_ALEN];
2630 int wired;
2631
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002632 res = wpa_drv_get_ssid(wpa_s, ssid);
2633 if (res < 0) {
2634 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2635 "driver");
2636 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002638 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002640 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2642 "driver");
2643 return NULL;
2644 }
2645
2646 wired = wpa_s->conf->ap_scan == 0 &&
2647 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2648
2649 entry = wpa_s->conf->ssid;
2650 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002651 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 ((ssid_len == entry->ssid_len &&
2653 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2654 (!entry->bssid_set ||
2655 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2656 return entry;
2657#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002658 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2660 (entry->ssid == NULL || entry->ssid_len == 0) &&
2661 (!entry->bssid_set ||
2662 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2663 return entry;
2664#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002665
Dmitry Shmidt04949592012-07-19 12:16:46 -07002666 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002667 entry->ssid_len == 0 &&
2668 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2669 return entry;
2670
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002671 entry = entry->next;
2672 }
2673
2674 return NULL;
2675}
2676
2677
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002678static int select_driver(struct wpa_supplicant *wpa_s, int i)
2679{
2680 struct wpa_global *global = wpa_s->global;
2681
2682 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2683 global->drv_priv[i] = wpa_drivers[i]->global_init();
2684 if (global->drv_priv[i] == NULL) {
2685 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2686 "'%s'", wpa_drivers[i]->name);
2687 return -1;
2688 }
2689 }
2690
2691 wpa_s->driver = wpa_drivers[i];
2692 wpa_s->global_drv_priv = global->drv_priv[i];
2693
2694 return 0;
2695}
2696
2697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2699 const char *name)
2700{
2701 int i;
2702 size_t len;
2703 const char *pos, *driver = name;
2704
2705 if (wpa_s == NULL)
2706 return -1;
2707
2708 if (wpa_drivers[0] == NULL) {
2709 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2710 "wpa_supplicant");
2711 return -1;
2712 }
2713
2714 if (name == NULL) {
2715 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002716 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 }
2718
2719 do {
2720 pos = os_strchr(driver, ',');
2721 if (pos)
2722 len = pos - driver;
2723 else
2724 len = os_strlen(driver);
2725
2726 for (i = 0; wpa_drivers[i]; i++) {
2727 if (os_strlen(wpa_drivers[i]->name) == len &&
2728 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002729 0) {
2730 /* First driver that succeeds wins */
2731 if (select_driver(wpa_s, i) == 0)
2732 return 0;
2733 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 }
2735
2736 driver = pos + 1;
2737 } while (pos);
2738
2739 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2740 return -1;
2741}
2742
2743
2744/**
2745 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2746 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2747 * with struct wpa_driver_ops::init()
2748 * @src_addr: Source address of the EAPOL frame
2749 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2750 * @len: Length of the EAPOL data
2751 *
2752 * This function is called for each received EAPOL frame. Most driver
2753 * interfaces rely on more generic OS mechanism for receiving frames through
2754 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2755 * take care of received EAPOL frames and deliver them to the core supplicant
2756 * code by calling this function.
2757 */
2758void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2759 const u8 *buf, size_t len)
2760{
2761 struct wpa_supplicant *wpa_s = ctx;
2762
2763 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2764 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2765
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002766#ifdef CONFIG_PEERKEY
2767 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2768 wpa_s->current_ssid->peerkey &&
2769 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2770 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2771 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2772 return;
2773 }
2774#endif /* CONFIG_PEERKEY */
2775
Jouni Malinena05074c2012-12-21 21:35:35 +02002776 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2777 (wpa_s->last_eapol_matches_bssid &&
2778#ifdef CONFIG_AP
2779 !wpa_s->ap_iface &&
2780#endif /* CONFIG_AP */
2781 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 /*
2783 * There is possible race condition between receiving the
2784 * association event and the EAPOL frame since they are coming
2785 * through different paths from the driver. In order to avoid
2786 * issues in trying to process the EAPOL frame before receiving
2787 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002788 * the association event is received. This may also be needed in
2789 * driver-based roaming case, so also use src_addr != BSSID as a
2790 * trigger if we have previously confirmed that the
2791 * Authenticator uses BSSID as the src_addr (which is not the
2792 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 */
2794 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002795 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2796 wpa_supplicant_state_txt(wpa_s->wpa_state),
2797 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002798 wpabuf_free(wpa_s->pending_eapol_rx);
2799 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2800 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002801 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2803 ETH_ALEN);
2804 }
2805 return;
2806 }
2807
Jouni Malinena05074c2012-12-21 21:35:35 +02002808 wpa_s->last_eapol_matches_bssid =
2809 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811#ifdef CONFIG_AP
2812 if (wpa_s->ap_iface) {
2813 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2814 return;
2815 }
2816#endif /* CONFIG_AP */
2817
2818 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2819 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2820 "no key management is configured");
2821 return;
2822 }
2823
2824 if (wpa_s->eapol_received == 0 &&
2825 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2826 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2827 wpa_s->wpa_state != WPA_COMPLETED) &&
2828 (wpa_s->current_ssid == NULL ||
2829 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2830 /* Timeout for completing IEEE 802.1X and WPA authentication */
2831 wpa_supplicant_req_auth_timeout(
2832 wpa_s,
2833 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2834 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2835 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2836 70 : 10, 0);
2837 }
2838 wpa_s->eapol_received++;
2839
2840 if (wpa_s->countermeasures) {
2841 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2842 "EAPOL packet");
2843 return;
2844 }
2845
2846#ifdef CONFIG_IBSS_RSN
2847 if (wpa_s->current_ssid &&
2848 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2849 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2850 return;
2851 }
2852#endif /* CONFIG_IBSS_RSN */
2853
2854 /* Source address of the incoming EAPOL frame could be compared to the
2855 * current BSSID. However, it is possible that a centralized
2856 * Authenticator could be using another MAC address than the BSSID of
2857 * an AP, so just allow any address to be used for now. The replies are
2858 * still sent to the current BSSID (if available), though. */
2859
2860 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2861 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2862 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2863 return;
2864 wpa_drv_poll(wpa_s);
2865 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2866 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2867 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2868 /*
2869 * Set portValid = TRUE here since we are going to skip 4-way
2870 * handshake processing which would normally set portValid. We
2871 * need this to allow the EAPOL state machines to be completed
2872 * without going through EAPOL-Key handshake.
2873 */
2874 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2875 }
2876}
2877
2878
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002879int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002881 if ((!wpa_s->p2p_mgmt ||
2882 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2883 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002884 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2886 wpa_drv_get_mac_addr(wpa_s),
2887 ETH_P_EAPOL,
2888 wpa_supplicant_rx_eapol, wpa_s, 0);
2889 if (wpa_s->l2 == NULL)
2890 return -1;
2891 } else {
2892 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2893 if (addr)
2894 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2895 }
2896
2897 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2898 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2899 return -1;
2900 }
2901
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002902 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002904 return 0;
2905}
2906
2907
Dmitry Shmidt04949592012-07-19 12:16:46 -07002908static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2909 const u8 *buf, size_t len)
2910{
2911 struct wpa_supplicant *wpa_s = ctx;
2912 const struct l2_ethhdr *eth;
2913
2914 if (len < sizeof(*eth))
2915 return;
2916 eth = (const struct l2_ethhdr *) buf;
2917
2918 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2919 !(eth->h_dest[0] & 0x01)) {
2920 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2921 " (bridge - not for this interface - ignore)",
2922 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2923 return;
2924 }
2925
2926 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2927 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2928 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2929 len - sizeof(*eth));
2930}
2931
2932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002933/**
2934 * wpa_supplicant_driver_init - Initialize driver interface parameters
2935 * @wpa_s: Pointer to wpa_supplicant data
2936 * Returns: 0 on success, -1 on failure
2937 *
2938 * This function is called to initialize driver interface parameters.
2939 * wpa_drv_init() must have been called before this function to initialize the
2940 * driver interface.
2941 */
2942int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2943{
2944 static int interface_count = 0;
2945
2946 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2947 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002948
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002949 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2950 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002951 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002952 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002954 if (wpa_s->bridge_ifname[0]) {
2955 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2956 "interface '%s'", wpa_s->bridge_ifname);
2957 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2958 wpa_s->own_addr,
2959 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002960 wpa_supplicant_rx_eapol_bridge,
2961 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962 if (wpa_s->l2_br == NULL) {
2963 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2964 "connection for the bridge interface '%s'",
2965 wpa_s->bridge_ifname);
2966 return -1;
2967 }
2968 }
2969
2970 wpa_clear_keys(wpa_s, NULL);
2971
2972 /* Make sure that TKIP countermeasures are not left enabled (could
2973 * happen if wpa_supplicant is killed during countermeasures. */
2974 wpa_drv_set_countermeasures(wpa_s, 0);
2975
2976 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2977 wpa_drv_flush_pmkid(wpa_s);
2978
2979 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002980 wpa_s->prev_scan_wildcard = 0;
2981
Dmitry Shmidt04949592012-07-19 12:16:46 -07002982 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002983 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2984 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2985 interface_count = 0;
2986 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002987#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002988 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002989 wpa_supplicant_delayed_sched_scan(wpa_s,
2990 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002991 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002992 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002993 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002994#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 interface_count++;
2996 } else
2997 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2998
2999 return 0;
3000}
3001
3002
3003static int wpa_supplicant_daemon(const char *pid_file)
3004{
3005 wpa_printf(MSG_DEBUG, "Daemonize..");
3006 return os_daemonize(pid_file);
3007}
3008
3009
3010static struct wpa_supplicant * wpa_supplicant_alloc(void)
3011{
3012 struct wpa_supplicant *wpa_s;
3013
3014 wpa_s = os_zalloc(sizeof(*wpa_s));
3015 if (wpa_s == NULL)
3016 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003017 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003018 wpa_s->scan_interval = 5;
3019 wpa_s->new_connection = 1;
3020 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003021 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003022
3023 return wpa_s;
3024}
3025
3026
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003027#ifdef CONFIG_HT_OVERRIDES
3028
3029static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3030 struct ieee80211_ht_capabilities *htcaps,
3031 struct ieee80211_ht_capabilities *htcaps_mask,
3032 const char *ht_mcs)
3033{
3034 /* parse ht_mcs into hex array */
3035 int i;
3036 const char *tmp = ht_mcs;
3037 char *end = NULL;
3038
3039 /* If ht_mcs is null, do not set anything */
3040 if (!ht_mcs)
3041 return 0;
3042
3043 /* This is what we are setting in the kernel */
3044 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3045
3046 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3047
3048 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3049 errno = 0;
3050 long v = strtol(tmp, &end, 16);
3051 if (errno == 0) {
3052 wpa_msg(wpa_s, MSG_DEBUG,
3053 "htcap value[%i]: %ld end: %p tmp: %p",
3054 i, v, end, tmp);
3055 if (end == tmp)
3056 break;
3057
3058 htcaps->supported_mcs_set[i] = v;
3059 tmp = end;
3060 } else {
3061 wpa_msg(wpa_s, MSG_ERROR,
3062 "Failed to parse ht-mcs: %s, error: %s\n",
3063 ht_mcs, strerror(errno));
3064 return -1;
3065 }
3066 }
3067
3068 /*
3069 * If we were able to parse any values, then set mask for the MCS set.
3070 */
3071 if (i) {
3072 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3073 IEEE80211_HT_MCS_MASK_LEN - 1);
3074 /* skip the 3 reserved bits */
3075 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3076 0x1f;
3077 }
3078
3079 return 0;
3080}
3081
3082
3083static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3084 struct ieee80211_ht_capabilities *htcaps,
3085 struct ieee80211_ht_capabilities *htcaps_mask,
3086 int disabled)
3087{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003088 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003089
3090 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3091
3092 if (disabled == -1)
3093 return 0;
3094
3095 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3096 htcaps_mask->ht_capabilities_info |= msk;
3097 if (disabled)
3098 htcaps->ht_capabilities_info &= msk;
3099 else
3100 htcaps->ht_capabilities_info |= msk;
3101
3102 return 0;
3103}
3104
3105
3106static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3107 struct ieee80211_ht_capabilities *htcaps,
3108 struct ieee80211_ht_capabilities *htcaps_mask,
3109 int factor)
3110{
3111 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3112
3113 if (factor == -1)
3114 return 0;
3115
3116 if (factor < 0 || factor > 3) {
3117 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3118 "Must be 0-3 or -1", factor);
3119 return -EINVAL;
3120 }
3121
3122 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3123 htcaps->a_mpdu_params &= ~0x3;
3124 htcaps->a_mpdu_params |= factor & 0x3;
3125
3126 return 0;
3127}
3128
3129
3130static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3131 struct ieee80211_ht_capabilities *htcaps,
3132 struct ieee80211_ht_capabilities *htcaps_mask,
3133 int density)
3134{
3135 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3136
3137 if (density == -1)
3138 return 0;
3139
3140 if (density < 0 || density > 7) {
3141 wpa_msg(wpa_s, MSG_ERROR,
3142 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3143 density);
3144 return -EINVAL;
3145 }
3146
3147 htcaps_mask->a_mpdu_params |= 0x1C;
3148 htcaps->a_mpdu_params &= ~(0x1C);
3149 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3150
3151 return 0;
3152}
3153
3154
3155static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3156 struct ieee80211_ht_capabilities *htcaps,
3157 struct ieee80211_ht_capabilities *htcaps_mask,
3158 int disabled)
3159{
3160 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003161 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3162 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003163
3164 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3165
3166 if (disabled)
3167 htcaps->ht_capabilities_info &= ~msk;
3168 else
3169 htcaps->ht_capabilities_info |= msk;
3170
3171 htcaps_mask->ht_capabilities_info |= msk;
3172
3173 return 0;
3174}
3175
3176
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003177static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3178 struct ieee80211_ht_capabilities *htcaps,
3179 struct ieee80211_ht_capabilities *htcaps_mask,
3180 int disabled)
3181{
3182 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003183 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3184 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003185
3186 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3187
3188 if (disabled)
3189 htcaps->ht_capabilities_info &= ~msk;
3190 else
3191 htcaps->ht_capabilities_info |= msk;
3192
3193 htcaps_mask->ht_capabilities_info |= msk;
3194
3195 return 0;
3196}
3197
3198
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003199static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3200 struct ieee80211_ht_capabilities *htcaps,
3201 struct ieee80211_ht_capabilities *htcaps_mask,
3202 int disabled)
3203{
3204 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003205 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003206
3207 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3208
3209 if (disabled)
3210 htcaps->ht_capabilities_info &= ~msk;
3211 else
3212 htcaps->ht_capabilities_info |= msk;
3213
3214 htcaps_mask->ht_capabilities_info |= msk;
3215
3216 return 0;
3217}
3218
3219
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003220void wpa_supplicant_apply_ht_overrides(
3221 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3222 struct wpa_driver_associate_params *params)
3223{
3224 struct ieee80211_ht_capabilities *htcaps;
3225 struct ieee80211_ht_capabilities *htcaps_mask;
3226
3227 if (!ssid)
3228 return;
3229
3230 params->disable_ht = ssid->disable_ht;
3231 if (!params->htcaps || !params->htcaps_mask)
3232 return;
3233
3234 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3235 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3236 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3237 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3238 ssid->disable_max_amsdu);
3239 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3240 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3241 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003242 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003243 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003244
3245 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003246 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003247 htcaps->ht_capabilities_info |= bit;
3248 htcaps_mask->ht_capabilities_info |= bit;
3249 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003250}
3251
3252#endif /* CONFIG_HT_OVERRIDES */
3253
3254
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003255#ifdef CONFIG_VHT_OVERRIDES
3256void wpa_supplicant_apply_vht_overrides(
3257 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3258 struct wpa_driver_associate_params *params)
3259{
3260 struct ieee80211_vht_capabilities *vhtcaps;
3261 struct ieee80211_vht_capabilities *vhtcaps_mask;
3262
3263 if (!ssid)
3264 return;
3265
3266 params->disable_vht = ssid->disable_vht;
3267
3268 vhtcaps = (void *) params->vhtcaps;
3269 vhtcaps_mask = (void *) params->vhtcaps_mask;
3270
3271 if (!vhtcaps || !vhtcaps_mask)
3272 return;
3273
3274 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3275 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3276
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003277#ifdef CONFIG_HT_OVERRIDES
3278 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003279 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3280 int max_ampdu;
3281
3282 max_ampdu = (ssid->vht_capa &
3283 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3284 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003285
3286 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3287 wpa_set_ampdu_factor(wpa_s,
3288 (void *) params->htcaps,
3289 (void *) params->htcaps_mask,
3290 max_ampdu);
3291 }
3292#endif /* CONFIG_HT_OVERRIDES */
3293
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003294#define OVERRIDE_MCS(i) \
3295 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3296 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3297 3 << 2 * (i - 1); \
3298 vhtcaps->vht_supported_mcs_set.tx_map |= \
3299 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3300 } \
3301 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3302 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3303 3 << 2 * (i - 1); \
3304 vhtcaps->vht_supported_mcs_set.rx_map |= \
3305 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3306 }
3307
3308 OVERRIDE_MCS(1);
3309 OVERRIDE_MCS(2);
3310 OVERRIDE_MCS(3);
3311 OVERRIDE_MCS(4);
3312 OVERRIDE_MCS(5);
3313 OVERRIDE_MCS(6);
3314 OVERRIDE_MCS(7);
3315 OVERRIDE_MCS(8);
3316}
3317#endif /* CONFIG_VHT_OVERRIDES */
3318
3319
Dmitry Shmidt04949592012-07-19 12:16:46 -07003320static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3321{
3322#ifdef PCSC_FUNCS
3323 size_t len;
3324
3325 if (!wpa_s->conf->pcsc_reader)
3326 return 0;
3327
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003328 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003329 if (!wpa_s->scard)
3330 return 1;
3331
3332 if (wpa_s->conf->pcsc_pin &&
3333 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3334 scard_deinit(wpa_s->scard);
3335 wpa_s->scard = NULL;
3336 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3337 return -1;
3338 }
3339
3340 len = sizeof(wpa_s->imsi) - 1;
3341 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3342 scard_deinit(wpa_s->scard);
3343 wpa_s->scard = NULL;
3344 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3345 return -1;
3346 }
3347 wpa_s->imsi[len] = '\0';
3348
3349 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3350
3351 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3352 wpa_s->imsi, wpa_s->mnc_len);
3353
3354 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3355 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3356#endif /* PCSC_FUNCS */
3357
3358 return 0;
3359}
3360
3361
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003362int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3363{
3364 char *val, *pos;
3365
3366 ext_password_deinit(wpa_s->ext_pw);
3367 wpa_s->ext_pw = NULL;
3368 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3369
3370 if (!wpa_s->conf->ext_password_backend)
3371 return 0;
3372
3373 val = os_strdup(wpa_s->conf->ext_password_backend);
3374 if (val == NULL)
3375 return -1;
3376 pos = os_strchr(val, ':');
3377 if (pos)
3378 *pos++ = '\0';
3379
3380 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3381
3382 wpa_s->ext_pw = ext_password_init(val, pos);
3383 os_free(val);
3384 if (wpa_s->ext_pw == NULL) {
3385 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3386 return -1;
3387 }
3388 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3389
3390 return 0;
3391}
3392
3393
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003394static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003395 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003396{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003397 struct wowlan_triggers *triggers;
3398 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003399
3400 if (!wpa_s->conf->wowlan_triggers)
3401 return 0;
3402
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003403 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3404 if (triggers) {
3405 ret = wpa_drv_wowlan(wpa_s, triggers);
3406 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003407 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003408 return ret;
3409}
3410
3411
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003412static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3413 const char *rn)
3414{
3415 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3416 struct wpa_radio *radio;
3417
3418 while (rn && iface) {
3419 radio = iface->radio;
3420 if (radio && os_strcmp(rn, radio->name) == 0) {
3421 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3422 wpa_s->ifname, rn);
3423 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3424 return radio;
3425 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003426
3427 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003428 }
3429
3430 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3431 wpa_s->ifname, rn ? rn : "N/A");
3432 radio = os_zalloc(sizeof(*radio));
3433 if (radio == NULL)
3434 return NULL;
3435
3436 if (rn)
3437 os_strlcpy(radio->name, rn, sizeof(radio->name));
3438 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003439 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003440 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3441
3442 return radio;
3443}
3444
3445
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003446static void radio_work_free(struct wpa_radio_work *work)
3447{
3448 if (work->wpa_s->scan_work == work) {
3449 /* This should not really happen. */
3450 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3451 work->type, work, work->started);
3452 work->wpa_s->scan_work = NULL;
3453 }
3454
3455#ifdef CONFIG_P2P
3456 if (work->wpa_s->p2p_scan_work == work) {
3457 /* This should not really happen. */
3458 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3459 work->type, work, work->started);
3460 work->wpa_s->p2p_scan_work = NULL;
3461 }
3462#endif /* CONFIG_P2P */
3463
3464 dl_list_del(&work->list);
3465 os_free(work);
3466}
3467
3468
3469static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3470{
3471 struct wpa_radio *radio = eloop_ctx;
3472 struct wpa_radio_work *work;
3473 struct os_reltime now, diff;
3474 struct wpa_supplicant *wpa_s;
3475
3476 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3477 if (work == NULL)
3478 return;
3479
3480 if (work->started)
3481 return; /* already started and still in progress */
3482
3483 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3484 radio_list);
3485 if (wpa_s && wpa_s->external_scan_running) {
3486 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3487 return;
3488 }
3489
3490 os_get_reltime(&now);
3491 os_reltime_sub(&now, &work->time, &diff);
3492 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3493 work->type, work, diff.sec, diff.usec);
3494 work->started = 1;
3495 work->time = now;
3496 work->cb(work, 0);
3497}
3498
3499
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003500/*
3501 * This function removes both started and pending radio works running on
3502 * the provided interface's radio.
3503 * Prior to the removal of the radio work, its callback (cb) is called with
3504 * deinit set to be 1. Each work's callback is responsible for clearing its
3505 * internal data and restoring to a correct state.
3506 * @wpa_s: wpa_supplicant data
3507 * @type: type of works to be removed
3508 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3509 * this interface's works.
3510 */
3511void radio_remove_works(struct wpa_supplicant *wpa_s,
3512 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003513{
3514 struct wpa_radio_work *work, *tmp;
3515 struct wpa_radio *radio = wpa_s->radio;
3516
3517 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3518 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003519 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003520 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003521
3522 /* skip other ifaces' works */
3523 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003524 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003525
3526 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3527 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003528 work->cb(work, 1);
3529 radio_work_free(work);
3530 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003531
3532 /* in case we removed the started work */
3533 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003534}
3535
3536
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003537static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3538{
3539 struct wpa_radio *radio = wpa_s->radio;
3540
3541 if (!radio)
3542 return;
3543
3544 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3545 wpa_s->ifname, radio->name);
3546 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003547 radio_remove_works(wpa_s, NULL, 0);
3548 wpa_s->radio = NULL;
3549 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003550 return; /* Interfaces remain for this radio */
3551
3552 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003553 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003554 os_free(radio);
3555}
3556
3557
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003558void radio_work_check_next(struct wpa_supplicant *wpa_s)
3559{
3560 struct wpa_radio *radio = wpa_s->radio;
3561
3562 if (dl_list_empty(&radio->work))
3563 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003564 if (wpa_s->ext_work_in_progress) {
3565 wpa_printf(MSG_DEBUG,
3566 "External radio work in progress - delay start of pending item");
3567 return;
3568 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003569 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3570 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3571}
3572
3573
3574/**
3575 * radio_add_work - Add a radio work item
3576 * @wpa_s: Pointer to wpa_supplicant data
3577 * @freq: Frequency of the offchannel operation in MHz or 0
3578 * @type: Unique identifier for each type of work
3579 * @next: Force as the next work to be executed
3580 * @cb: Callback function for indicating when radio is available
3581 * @ctx: Context pointer for the work (work->ctx in cb())
3582 * Returns: 0 on success, -1 on failure
3583 *
3584 * This function is used to request time for an operation that requires
3585 * exclusive radio control. Once the radio is available, the registered callback
3586 * function will be called. radio_work_done() must be called once the exclusive
3587 * radio operation has been completed, so that the radio is freed for other
3588 * operations. The special case of deinit=1 is used to free the context data
3589 * during interface removal. That does not allow the callback function to start
3590 * the radio operation, i.e., it must free any resources allocated for the radio
3591 * work and return.
3592 *
3593 * The @freq parameter can be used to indicate a single channel on which the
3594 * offchannel operation will occur. This may allow multiple radio work
3595 * operations to be performed in parallel if they apply for the same channel.
3596 * Setting this to 0 indicates that the work item may use multiple channels or
3597 * requires exclusive control of the radio.
3598 */
3599int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3600 const char *type, int next,
3601 void (*cb)(struct wpa_radio_work *work, int deinit),
3602 void *ctx)
3603{
3604 struct wpa_radio_work *work;
3605 int was_empty;
3606
3607 work = os_zalloc(sizeof(*work));
3608 if (work == NULL)
3609 return -1;
3610 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3611 os_get_reltime(&work->time);
3612 work->freq = freq;
3613 work->type = type;
3614 work->wpa_s = wpa_s;
3615 work->cb = cb;
3616 work->ctx = ctx;
3617
3618 was_empty = dl_list_empty(&wpa_s->radio->work);
3619 if (next)
3620 dl_list_add(&wpa_s->radio->work, &work->list);
3621 else
3622 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3623 if (was_empty) {
3624 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3625 radio_work_check_next(wpa_s);
3626 }
3627
3628 return 0;
3629}
3630
3631
3632/**
3633 * radio_work_done - Indicate that a radio work item has been completed
3634 * @work: Completed work
3635 *
3636 * This function is called once the callback function registered with
3637 * radio_add_work() has completed its work.
3638 */
3639void radio_work_done(struct wpa_radio_work *work)
3640{
3641 struct wpa_supplicant *wpa_s = work->wpa_s;
3642 struct os_reltime now, diff;
3643 unsigned int started = work->started;
3644
3645 os_get_reltime(&now);
3646 os_reltime_sub(&now, &work->time, &diff);
3647 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3648 work->type, work, started ? "done" : "canceled",
3649 diff.sec, diff.usec);
3650 radio_work_free(work);
3651 if (started)
3652 radio_work_check_next(wpa_s);
3653}
3654
3655
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003656struct wpa_radio_work *
3657radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003658{
3659 struct wpa_radio_work *work;
3660 struct wpa_radio *radio = wpa_s->radio;
3661
3662 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3663 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003664 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003665 }
3666
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003667 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003668}
3669
3670
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003671static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3672 struct wpa_interface *iface)
3673{
3674 const char *ifname, *driver, *rn;
3675
3676 driver = iface->driver;
3677next_driver:
3678 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3679 return -1;
3680
3681 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3682 if (wpa_s->drv_priv == NULL) {
3683 const char *pos;
3684 pos = driver ? os_strchr(driver, ',') : NULL;
3685 if (pos) {
3686 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3687 "driver interface - try next driver wrapper");
3688 driver = pos + 1;
3689 goto next_driver;
3690 }
3691 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3692 "interface");
3693 return -1;
3694 }
3695 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3696 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3697 "driver_param '%s'", wpa_s->conf->driver_param);
3698 return -1;
3699 }
3700
3701 ifname = wpa_drv_get_ifname(wpa_s);
3702 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3703 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3704 "interface name with '%s'", ifname);
3705 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3706 }
3707
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003708 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003709 if (rn && rn[0] == '\0')
3710 rn = NULL;
3711
3712 wpa_s->radio = radio_add_interface(wpa_s, rn);
3713 if (wpa_s->radio == NULL)
3714 return -1;
3715
3716 return 0;
3717}
3718
3719
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003720static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3721 struct wpa_interface *iface)
3722{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003723 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003724 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725
3726 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3727 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3728 iface->confname ? iface->confname : "N/A",
3729 iface->driver ? iface->driver : "default",
3730 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3731 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3732
3733 if (iface->confname) {
3734#ifdef CONFIG_BACKEND_FILE
3735 wpa_s->confname = os_rel2abs_path(iface->confname);
3736 if (wpa_s->confname == NULL) {
3737 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3738 "for configuration file '%s'.",
3739 iface->confname);
3740 return -1;
3741 }
3742 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3743 iface->confname, wpa_s->confname);
3744#else /* CONFIG_BACKEND_FILE */
3745 wpa_s->confname = os_strdup(iface->confname);
3746#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003747 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003748 if (wpa_s->conf == NULL) {
3749 wpa_printf(MSG_ERROR, "Failed to read or parse "
3750 "configuration '%s'.", wpa_s->confname);
3751 return -1;
3752 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003753 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3754 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755
3756 /*
3757 * Override ctrl_interface and driver_param if set on command
3758 * line.
3759 */
3760 if (iface->ctrl_interface) {
3761 os_free(wpa_s->conf->ctrl_interface);
3762 wpa_s->conf->ctrl_interface =
3763 os_strdup(iface->ctrl_interface);
3764 }
3765
3766 if (iface->driver_param) {
3767 os_free(wpa_s->conf->driver_param);
3768 wpa_s->conf->driver_param =
3769 os_strdup(iface->driver_param);
3770 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003771
3772 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3773 os_free(wpa_s->conf->ctrl_interface);
3774 wpa_s->conf->ctrl_interface = NULL;
3775 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 } else
3777 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3778 iface->driver_param);
3779
3780 if (wpa_s->conf == NULL) {
3781 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3782 return -1;
3783 }
3784
3785 if (iface->ifname == NULL) {
3786 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3787 return -1;
3788 }
3789 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3790 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3791 iface->ifname);
3792 return -1;
3793 }
3794 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3795
3796 if (iface->bridge_ifname) {
3797 if (os_strlen(iface->bridge_ifname) >=
3798 sizeof(wpa_s->bridge_ifname)) {
3799 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3800 "name '%s'.", iface->bridge_ifname);
3801 return -1;
3802 }
3803 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3804 sizeof(wpa_s->bridge_ifname));
3805 }
3806
3807 /* RSNA Supplicant Key Management - INITIALIZE */
3808 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3809 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3810
3811 /* Initialize driver interface and register driver event handler before
3812 * L2 receive handler so that association events are processed before
3813 * EAPOL-Key packets if both become available for the same select()
3814 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003815 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003816 return -1;
3817
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3819 return -1;
3820
3821 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3822 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3823 NULL);
3824 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3825
3826 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3827 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3828 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3829 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3830 "dot11RSNAConfigPMKLifetime");
3831 return -1;
3832 }
3833
3834 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3835 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3836 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3837 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3838 "dot11RSNAConfigPMKReauthThreshold");
3839 return -1;
3840 }
3841
3842 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3843 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3844 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3845 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3846 "dot11RSNAConfigSATimeout");
3847 return -1;
3848 }
3849
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003850 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3851 &wpa_s->hw.num_modes,
3852 &wpa_s->hw.flags);
3853
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003854 capa_res = wpa_drv_get_capa(wpa_s, &capa);
3855 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003856 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003857 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003858 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003859 wpa_s->drv_smps_modes = capa.smps_modes;
3860 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003861 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003862 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003863 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3864 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3865 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3867 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003868 wpa_s->extended_capa = capa.extended_capa;
3869 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3870 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003871 wpa_s->num_multichan_concurrent =
3872 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003873 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
3874
3875 if (capa.mac_addr_rand_scan_supported)
3876 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
3877 if (wpa_s->sched_scan_supported &&
3878 capa.mac_addr_rand_sched_scan_supported)
3879 wpa_s->mac_addr_rand_supported |=
3880 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003881 }
3882 if (wpa_s->max_remain_on_chan == 0)
3883 wpa_s->max_remain_on_chan = 1000;
3884
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003885 /*
3886 * Only take p2p_mgmt parameters when P2P Device is supported.
3887 * Doing it here as it determines whether l2_packet_init() will be done
3888 * during wpa_supplicant_driver_init().
3889 */
3890 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3891 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3892 else
3893 iface->p2p_mgmt = 1;
3894
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003895 if (wpa_s->num_multichan_concurrent == 0)
3896 wpa_s->num_multichan_concurrent = 1;
3897
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003898 if (wpa_supplicant_driver_init(wpa_s) < 0)
3899 return -1;
3900
3901#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003902 if ((!iface->p2p_mgmt ||
3903 !(wpa_s->drv_flags &
3904 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3905 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003906 return -1;
3907#endif /* CONFIG_TDLS */
3908
3909 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3910 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3911 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3912 return -1;
3913 }
3914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003915 if (wpas_wps_init(wpa_s))
3916 return -1;
3917
3918 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3919 return -1;
3920 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3921
3922 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3923 if (wpa_s->ctrl_iface == NULL) {
3924 wpa_printf(MSG_ERROR,
3925 "Failed to initialize control interface '%s'.\n"
3926 "You may have another wpa_supplicant process "
3927 "already running or the file was\n"
3928 "left by an unclean termination of wpa_supplicant "
3929 "in which case you will need\n"
3930 "to manually remove this file before starting "
3931 "wpa_supplicant again.\n",
3932 wpa_s->conf->ctrl_interface);
3933 return -1;
3934 }
3935
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003936 wpa_s->gas = gas_query_init(wpa_s);
3937 if (wpa_s->gas == NULL) {
3938 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3939 return -1;
3940 }
3941
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003942 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3944 return -1;
3945 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946
3947 if (wpa_bss_init(wpa_s) < 0)
3948 return -1;
3949
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003950 /*
3951 * Set Wake-on-WLAN triggers, if configured.
3952 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3953 * have effect anyway when the interface is down).
3954 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003955 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003956 return -1;
3957
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003958#ifdef CONFIG_EAP_PROXY
3959{
3960 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003961 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3962 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003963 if (wpa_s->mnc_len > 0) {
3964 wpa_s->imsi[len] = '\0';
3965 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3966 wpa_s->imsi, wpa_s->mnc_len);
3967 } else {
3968 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3969 }
3970}
3971#endif /* CONFIG_EAP_PROXY */
3972
Dmitry Shmidt04949592012-07-19 12:16:46 -07003973 if (pcsc_reader_init(wpa_s) < 0)
3974 return -1;
3975
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003976 if (wpas_init_ext_pw(wpa_s) < 0)
3977 return -1;
3978
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003979 wpas_rrm_reset(wpa_s);
3980
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003981 return 0;
3982}
3983
3984
3985static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003986 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003987{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003988 struct wpa_global *global = wpa_s->global;
3989 struct wpa_supplicant *iface, *prev;
3990
3991 if (wpa_s == wpa_s->parent)
3992 wpas_p2p_group_remove(wpa_s, "*");
3993
3994 iface = global->ifaces;
3995 while (iface) {
3996 if (iface == wpa_s || iface->parent != wpa_s) {
3997 iface = iface->next;
3998 continue;
3999 }
4000 wpa_printf(MSG_DEBUG,
4001 "Remove remaining child interface %s from parent %s",
4002 iface->ifname, wpa_s->ifname);
4003 prev = iface;
4004 iface = iface->next;
4005 wpa_supplicant_remove_iface(global, prev, terminate);
4006 }
4007
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004008 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004009 if (wpa_s->drv_priv) {
4010 wpa_supplicant_deauthenticate(wpa_s,
4011 WLAN_REASON_DEAUTH_LEAVING);
4012
4013 wpa_drv_set_countermeasures(wpa_s, 0);
4014 wpa_clear_keys(wpa_s, NULL);
4015 }
4016
4017 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004018 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004019
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004020 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004021 radio_remove_interface(wpa_s);
4022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 if (wpa_s->drv_priv)
4024 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004025
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004026 if (notify)
4027 wpas_notify_iface_removed(wpa_s);
4028
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004029 if (terminate)
4030 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004031
4032 if (wpa_s->ctrl_iface) {
4033 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4034 wpa_s->ctrl_iface = NULL;
4035 }
4036
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004037#ifdef CONFIG_MESH
4038 if (wpa_s->ifmsh) {
4039 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4040 wpa_s->ifmsh = NULL;
4041 }
4042#endif /* CONFIG_MESH */
4043
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004044 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004045 wpa_config_free(wpa_s->conf);
4046 wpa_s->conf = NULL;
4047 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004048
4049 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050}
4051
4052
4053/**
4054 * wpa_supplicant_add_iface - Add a new network interface
4055 * @global: Pointer to global data from wpa_supplicant_init()
4056 * @iface: Interface configuration options
4057 * Returns: Pointer to the created interface or %NULL on failure
4058 *
4059 * This function is used to add new network interfaces for %wpa_supplicant.
4060 * This can be called before wpa_supplicant_run() to add interfaces before the
4061 * main event loop has been started. In addition, new interfaces can be added
4062 * dynamically while %wpa_supplicant is already running. This could happen,
4063 * e.g., when a hotplug network adapter is inserted.
4064 */
4065struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
4066 struct wpa_interface *iface)
4067{
4068 struct wpa_supplicant *wpa_s;
4069 struct wpa_interface t_iface;
4070 struct wpa_ssid *ssid;
4071
4072 if (global == NULL || iface == NULL)
4073 return NULL;
4074
4075 wpa_s = wpa_supplicant_alloc();
4076 if (wpa_s == NULL)
4077 return NULL;
4078
4079 wpa_s->global = global;
4080
4081 t_iface = *iface;
4082 if (global->params.override_driver) {
4083 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4084 "('%s' -> '%s')",
4085 iface->driver, global->params.override_driver);
4086 t_iface.driver = global->params.override_driver;
4087 }
4088 if (global->params.override_ctrl_interface) {
4089 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4090 "ctrl_interface ('%s' -> '%s')",
4091 iface->ctrl_interface,
4092 global->params.override_ctrl_interface);
4093 t_iface.ctrl_interface =
4094 global->params.override_ctrl_interface;
4095 }
4096 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4097 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4098 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004099 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004100 return NULL;
4101 }
4102
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004103 if (iface->p2p_mgmt == 0) {
4104 /* Notify the control interfaces about new iface */
4105 if (wpas_notify_iface_added(wpa_s)) {
4106 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4107 return NULL;
4108 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004110 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4111 wpas_notify_network_added(wpa_s, ssid);
4112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113
4114 wpa_s->next = global->ifaces;
4115 global->ifaces = wpa_s;
4116
4117 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004118 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004120#ifdef CONFIG_P2P
4121 if (wpa_s->global->p2p == NULL &&
4122 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4123 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4124 wpa_printf(MSG_INFO,
4125 "P2P: Failed to enable P2P Device interface");
4126 /* Try to continue without. P2P will be disabled. */
4127 }
4128#endif /* CONFIG_P2P */
4129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004130 return wpa_s;
4131}
4132
4133
4134/**
4135 * wpa_supplicant_remove_iface - Remove a network interface
4136 * @global: Pointer to global data from wpa_supplicant_init()
4137 * @wpa_s: Pointer to the network interface to be removed
4138 * Returns: 0 if interface was removed, -1 if interface was not found
4139 *
4140 * This function can be used to dynamically remove network interfaces from
4141 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4142 * addition, this function is used to remove all remaining interfaces when
4143 * %wpa_supplicant is terminated.
4144 */
4145int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004146 struct wpa_supplicant *wpa_s,
4147 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148{
4149 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004150#ifdef CONFIG_MESH
4151 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4152 char *ifname = NULL;
4153#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004154
4155 /* Remove interface from the global list of interfaces */
4156 prev = global->ifaces;
4157 if (prev == wpa_s) {
4158 global->ifaces = wpa_s->next;
4159 } else {
4160 while (prev && prev->next != wpa_s)
4161 prev = prev->next;
4162 if (prev == NULL)
4163 return -1;
4164 prev->next = wpa_s->next;
4165 }
4166
4167 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4168
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004169#ifdef CONFIG_MESH
4170 if (mesh_if_created) {
4171 ifname = os_strdup(wpa_s->ifname);
4172 if (ifname == NULL) {
4173 wpa_dbg(wpa_s, MSG_ERROR,
4174 "mesh: Failed to malloc ifname");
4175 return -1;
4176 }
4177 }
4178#endif /* CONFIG_MESH */
4179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004180 if (global->p2p_group_formation == wpa_s)
4181 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004182 if (global->p2p_invite_group == wpa_s)
4183 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004184 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004185
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004186#ifdef CONFIG_MESH
4187 if (mesh_if_created) {
4188 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4189 os_free(ifname);
4190 }
4191#endif /* CONFIG_MESH */
4192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004193 return 0;
4194}
4195
4196
4197/**
4198 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4199 * @wpa_s: Pointer to the network interface
4200 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4201 */
4202const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4203{
4204 const char *eapol_method;
4205
4206 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4207 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4208 return "NO-EAP";
4209 }
4210
4211 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4212 if (eapol_method == NULL)
4213 return "UNKNOWN-EAP";
4214
4215 return eapol_method;
4216}
4217
4218
4219/**
4220 * wpa_supplicant_get_iface - Get a new network interface
4221 * @global: Pointer to global data from wpa_supplicant_init()
4222 * @ifname: Interface name
4223 * Returns: Pointer to the interface or %NULL if not found
4224 */
4225struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4226 const char *ifname)
4227{
4228 struct wpa_supplicant *wpa_s;
4229
4230 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4231 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4232 return wpa_s;
4233 }
4234 return NULL;
4235}
4236
4237
4238#ifndef CONFIG_NO_WPA_MSG
4239static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4240{
4241 struct wpa_supplicant *wpa_s = ctx;
4242 if (wpa_s == NULL)
4243 return NULL;
4244 return wpa_s->ifname;
4245}
4246#endif /* CONFIG_NO_WPA_MSG */
4247
4248
4249/**
4250 * wpa_supplicant_init - Initialize %wpa_supplicant
4251 * @params: Parameters for %wpa_supplicant
4252 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4253 *
4254 * This function is used to initialize %wpa_supplicant. After successful
4255 * initialization, the returned data pointer can be used to add and remove
4256 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4257 */
4258struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4259{
4260 struct wpa_global *global;
4261 int ret, i;
4262
4263 if (params == NULL)
4264 return NULL;
4265
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004266#ifdef CONFIG_DRIVER_NDIS
4267 {
4268 void driver_ndis_init_ops(void);
4269 driver_ndis_init_ops();
4270 }
4271#endif /* CONFIG_DRIVER_NDIS */
4272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273#ifndef CONFIG_NO_WPA_MSG
4274 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4275#endif /* CONFIG_NO_WPA_MSG */
4276
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004277 if (params->wpa_debug_file_path)
4278 wpa_debug_open_file(params->wpa_debug_file_path);
4279 else
4280 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004281 if (params->wpa_debug_syslog)
4282 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004283 if (params->wpa_debug_tracing) {
4284 ret = wpa_debug_open_linux_tracing();
4285 if (ret) {
4286 wpa_printf(MSG_ERROR,
4287 "Failed to enable trace logging");
4288 return NULL;
4289 }
4290 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291
4292 ret = eap_register_methods();
4293 if (ret) {
4294 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4295 if (ret == -2)
4296 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4297 "the same EAP type.");
4298 return NULL;
4299 }
4300
4301 global = os_zalloc(sizeof(*global));
4302 if (global == NULL)
4303 return NULL;
4304 dl_list_init(&global->p2p_srv_bonjour);
4305 dl_list_init(&global->p2p_srv_upnp);
4306 global->params.daemonize = params->daemonize;
4307 global->params.wait_for_monitor = params->wait_for_monitor;
4308 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4309 if (params->pid_file)
4310 global->params.pid_file = os_strdup(params->pid_file);
4311 if (params->ctrl_interface)
4312 global->params.ctrl_interface =
4313 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004314 if (params->ctrl_interface_group)
4315 global->params.ctrl_interface_group =
4316 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317 if (params->override_driver)
4318 global->params.override_driver =
4319 os_strdup(params->override_driver);
4320 if (params->override_ctrl_interface)
4321 global->params.override_ctrl_interface =
4322 os_strdup(params->override_ctrl_interface);
4323 wpa_debug_level = global->params.wpa_debug_level =
4324 params->wpa_debug_level;
4325 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4326 params->wpa_debug_show_keys;
4327 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4328 params->wpa_debug_timestamp;
4329
4330 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4331
4332 if (eloop_init()) {
4333 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4334 wpa_supplicant_deinit(global);
4335 return NULL;
4336 }
4337
Jouni Malinen75ecf522011-06-27 15:19:46 -07004338 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339
4340 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4341 if (global->ctrl_iface == NULL) {
4342 wpa_supplicant_deinit(global);
4343 return NULL;
4344 }
4345
4346 if (wpas_notify_supplicant_initialized(global)) {
4347 wpa_supplicant_deinit(global);
4348 return NULL;
4349 }
4350
4351 for (i = 0; wpa_drivers[i]; i++)
4352 global->drv_count++;
4353 if (global->drv_count == 0) {
4354 wpa_printf(MSG_ERROR, "No drivers enabled");
4355 wpa_supplicant_deinit(global);
4356 return NULL;
4357 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004358 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 if (global->drv_priv == NULL) {
4360 wpa_supplicant_deinit(global);
4361 return NULL;
4362 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004364#ifdef CONFIG_WIFI_DISPLAY
4365 if (wifi_display_init(global) < 0) {
4366 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4367 wpa_supplicant_deinit(global);
4368 return NULL;
4369 }
4370#endif /* CONFIG_WIFI_DISPLAY */
4371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004372 return global;
4373}
4374
4375
4376/**
4377 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4378 * @global: Pointer to global data from wpa_supplicant_init()
4379 * Returns: 0 after successful event loop run, -1 on failure
4380 *
4381 * This function starts the main event loop and continues running as long as
4382 * there are any remaining events. In most cases, this function is running as
4383 * long as the %wpa_supplicant process in still in use.
4384 */
4385int wpa_supplicant_run(struct wpa_global *global)
4386{
4387 struct wpa_supplicant *wpa_s;
4388
4389 if (global->params.daemonize &&
4390 wpa_supplicant_daemon(global->params.pid_file))
4391 return -1;
4392
4393 if (global->params.wait_for_monitor) {
4394 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4395 if (wpa_s->ctrl_iface)
4396 wpa_supplicant_ctrl_iface_wait(
4397 wpa_s->ctrl_iface);
4398 }
4399
4400 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4401 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4402
4403 eloop_run();
4404
4405 return 0;
4406}
4407
4408
4409/**
4410 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4411 * @global: Pointer to global data from wpa_supplicant_init()
4412 *
4413 * This function is called to deinitialize %wpa_supplicant and to free all
4414 * allocated resources. Remaining network interfaces will also be removed.
4415 */
4416void wpa_supplicant_deinit(struct wpa_global *global)
4417{
4418 int i;
4419
4420 if (global == NULL)
4421 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004422
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004423#ifdef CONFIG_WIFI_DISPLAY
4424 wifi_display_deinit(global);
4425#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004426
4427 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004428 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004429
4430 if (global->ctrl_iface)
4431 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4432
4433 wpas_notify_supplicant_deinitialized(global);
4434
4435 eap_peer_unregister_methods();
4436#ifdef CONFIG_AP
4437 eap_server_unregister_methods();
4438#endif /* CONFIG_AP */
4439
4440 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4441 if (!global->drv_priv[i])
4442 continue;
4443 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4444 }
4445 os_free(global->drv_priv);
4446
4447 random_deinit();
4448
4449 eloop_destroy();
4450
4451 if (global->params.pid_file) {
4452 os_daemonize_terminate(global->params.pid_file);
4453 os_free(global->params.pid_file);
4454 }
4455 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004456 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457 os_free(global->params.override_driver);
4458 os_free(global->params.override_ctrl_interface);
4459
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004460 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004461 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004462 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 os_free(global);
4465 wpa_debug_close_syslog();
4466 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004467 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468}
4469
4470
4471void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4472{
4473 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4474 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4475 char country[3];
4476 country[0] = wpa_s->conf->country[0];
4477 country[1] = wpa_s->conf->country[1];
4478 country[2] = '\0';
4479 if (wpa_drv_set_country(wpa_s, country) < 0) {
4480 wpa_printf(MSG_ERROR, "Failed to set country code "
4481 "'%s'", country);
4482 }
4483 }
4484
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004485 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4486 wpas_init_ext_pw(wpa_s);
4487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004488#ifdef CONFIG_WPS
4489 wpas_wps_update_config(wpa_s);
4490#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004492 wpa_s->conf->changed_parameters = 0;
4493}
4494
4495
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004496void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004497{
4498 int i;
4499
4500 for (i = 0; i < *num_freqs; i++) {
4501 if (freqs[i] == freq)
4502 return;
4503 }
4504
4505 freqs[*num_freqs] = freq;
4506 (*num_freqs)++;
4507}
4508
4509
4510static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4511{
4512 struct wpa_bss *bss, *cbss;
4513 const int max_freqs = 10;
4514 int *freqs;
4515 int num_freqs = 0;
4516
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004517 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 if (freqs == NULL)
4519 return NULL;
4520
4521 cbss = wpa_s->current_bss;
4522
4523 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4524 if (bss == cbss)
4525 continue;
4526 if (bss->ssid_len == cbss->ssid_len &&
4527 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4528 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4529 add_freq(freqs, &num_freqs, bss->freq);
4530 if (num_freqs == max_freqs)
4531 break;
4532 }
4533 }
4534
4535 if (num_freqs == 0) {
4536 os_free(freqs);
4537 freqs = NULL;
4538 }
4539
4540 return freqs;
4541}
4542
4543
4544void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4545{
4546 int timeout;
4547 int count;
4548 int *freqs = NULL;
4549
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004550 wpas_connect_work_done(wpa_s);
4551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004553 * Remove possible authentication timeout since the connection failed.
4554 */
4555 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4556
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004557 if (wpa_s->disconnected) {
4558 /*
4559 * There is no point in blacklisting the AP if this event is
4560 * generated based on local request to disconnect.
4561 */
4562 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4563 "indication since interface has been put into "
4564 "disconnected state");
4565 return;
4566 }
4567
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004568 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004569 * Add the failed BSSID into the blacklist and speed up next scan
4570 * attempt if there could be other APs that could accept association.
4571 * The current blacklist count indicates how many times we have tried
4572 * connecting to this AP and multiple attempts mean that other APs are
4573 * either not available or has already been tried, so that we can start
4574 * increasing the delay here to avoid constant scanning.
4575 */
4576 count = wpa_blacklist_add(wpa_s, bssid);
4577 if (count == 1 && wpa_s->current_bss) {
4578 /*
4579 * This BSS was not in the blacklist before. If there is
4580 * another BSS available for the same ESS, we should try that
4581 * next. Otherwise, we may as well try this one once more
4582 * before allowing other, likely worse, ESSes to be considered.
4583 */
4584 freqs = get_bss_freqs_in_ess(wpa_s);
4585 if (freqs) {
4586 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4587 "has been seen; try it next");
4588 wpa_blacklist_add(wpa_s, bssid);
4589 /*
4590 * On the next scan, go through only the known channels
4591 * used in this ESS based on previous scans to speed up
4592 * common load balancing use case.
4593 */
4594 os_free(wpa_s->next_scan_freqs);
4595 wpa_s->next_scan_freqs = freqs;
4596 }
4597 }
4598
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004599 /*
4600 * Add previous failure count in case the temporary blacklist was
4601 * cleared due to no other BSSes being available.
4602 */
4603 count += wpa_s->extra_blacklist_count;
4604
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004605 if (count > 3 && wpa_s->current_ssid) {
4606 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4607 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004608 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004609 }
4610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611 switch (count) {
4612 case 1:
4613 timeout = 100;
4614 break;
4615 case 2:
4616 timeout = 500;
4617 break;
4618 case 3:
4619 timeout = 1000;
4620 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004621 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004622 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004623 break;
4624 default:
4625 timeout = 10000;
4626 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004627 }
4628
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004629 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4630 "ms", count, timeout);
4631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632 /*
4633 * TODO: if more than one possible AP is available in scan results,
4634 * could try the other ones before requesting a new scan.
4635 */
4636 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4637 1000 * (timeout % 1000));
4638}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004639
4640
4641int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4642{
4643 return wpa_s->conf->ap_scan == 2 ||
4644 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4645}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004646
Dmitry Shmidt04949592012-07-19 12:16:46 -07004647
4648#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4649int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4650 struct wpa_ssid *ssid,
4651 const char *field,
4652 const char *value)
4653{
4654#ifdef IEEE8021X_EAPOL
4655 struct eap_peer_config *eap = &ssid->eap;
4656
4657 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4658 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4659 (const u8 *) value, os_strlen(value));
4660
4661 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4662 case WPA_CTRL_REQ_EAP_IDENTITY:
4663 os_free(eap->identity);
4664 eap->identity = (u8 *) os_strdup(value);
4665 eap->identity_len = os_strlen(value);
4666 eap->pending_req_identity = 0;
4667 if (ssid == wpa_s->current_ssid)
4668 wpa_s->reassociate = 1;
4669 break;
4670 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004671 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004672 eap->password = (u8 *) os_strdup(value);
4673 eap->password_len = os_strlen(value);
4674 eap->pending_req_password = 0;
4675 if (ssid == wpa_s->current_ssid)
4676 wpa_s->reassociate = 1;
4677 break;
4678 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004679 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004680 eap->new_password = (u8 *) os_strdup(value);
4681 eap->new_password_len = os_strlen(value);
4682 eap->pending_req_new_password = 0;
4683 if (ssid == wpa_s->current_ssid)
4684 wpa_s->reassociate = 1;
4685 break;
4686 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004687 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004688 eap->pin = os_strdup(value);
4689 eap->pending_req_pin = 0;
4690 if (ssid == wpa_s->current_ssid)
4691 wpa_s->reassociate = 1;
4692 break;
4693 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004694 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004695 eap->otp = (u8 *) os_strdup(value);
4696 eap->otp_len = os_strlen(value);
4697 os_free(eap->pending_req_otp);
4698 eap->pending_req_otp = NULL;
4699 eap->pending_req_otp_len = 0;
4700 break;
4701 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004702 str_clear_free(eap->private_key_passwd);
4703 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004704 eap->pending_req_passphrase = 0;
4705 if (ssid == wpa_s->current_ssid)
4706 wpa_s->reassociate = 1;
4707 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004708 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004709 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004710 eap->external_sim_resp = os_strdup(value);
4711 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004712 default:
4713 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4714 return -1;
4715 }
4716
4717 return 0;
4718#else /* IEEE8021X_EAPOL */
4719 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4720 return -1;
4721#endif /* IEEE8021X_EAPOL */
4722}
4723#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4724
4725
4726int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4727{
4728 int i;
4729 unsigned int drv_enc;
4730
4731 if (ssid == NULL)
4732 return 1;
4733
4734 if (ssid->disabled)
4735 return 1;
4736
4737 if (wpa_s && wpa_s->drv_capa_known)
4738 drv_enc = wpa_s->drv_enc;
4739 else
4740 drv_enc = (unsigned int) -1;
4741
4742 for (i = 0; i < NUM_WEP_KEYS; i++) {
4743 size_t len = ssid->wep_key_len[i];
4744 if (len == 0)
4745 continue;
4746 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4747 continue;
4748 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4749 continue;
4750 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4751 continue;
4752 return 1; /* invalid WEP key */
4753 }
4754
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004755 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004756 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004757 return 1;
4758
Dmitry Shmidt04949592012-07-19 12:16:46 -07004759 return 0;
4760}
4761
4762
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004763int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004764{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004765 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004766 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004767 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004768 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004769 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004770}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004771
4772
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004773void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004774{
4775 struct wpa_ssid *ssid = wpa_s->current_ssid;
4776 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004777 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004778
4779 if (ssid == NULL) {
4780 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4781 "SSID block");
4782 return;
4783 }
4784
4785 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4786 return;
4787
4788 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004789
4790#ifdef CONFIG_P2P
4791 if (ssid->p2p_group &&
4792 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4793 /*
4794 * Skip the wait time since there is a short timeout on the
4795 * connection to a P2P group.
4796 */
4797 return;
4798 }
4799#endif /* CONFIG_P2P */
4800
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004801 if (ssid->auth_failures > 50)
4802 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004803 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004804 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004805 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004806 dur = 90;
4807 else if (ssid->auth_failures > 3)
4808 dur = 60;
4809 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004810 dur = 30;
4811 else if (ssid->auth_failures > 1)
4812 dur = 20;
4813 else
4814 dur = 10;
4815
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004816 if (ssid->auth_failures > 1 &&
4817 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4818 dur += os_random() % (ssid->auth_failures * 10);
4819
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004820 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004821 if (now.sec + dur <= ssid->disabled_until.sec)
4822 return;
4823
4824 ssid->disabled_until.sec = now.sec + dur;
4825
4826 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004827 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004828 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004829 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004830}
4831
4832
4833void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4834 struct wpa_ssid *ssid, int clear_failures)
4835{
4836 if (ssid == NULL)
4837 return;
4838
4839 if (ssid->disabled_until.sec) {
4840 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4841 "id=%d ssid=\"%s\"",
4842 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4843 }
4844 ssid->disabled_until.sec = 0;
4845 ssid->disabled_until.usec = 0;
4846 if (clear_failures)
4847 ssid->auth_failures = 0;
4848}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004849
4850
4851int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4852{
4853 size_t i;
4854
4855 if (wpa_s->disallow_aps_bssid == NULL)
4856 return 0;
4857
4858 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4859 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4860 bssid, ETH_ALEN) == 0)
4861 return 1;
4862 }
4863
4864 return 0;
4865}
4866
4867
4868int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4869 size_t ssid_len)
4870{
4871 size_t i;
4872
4873 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4874 return 0;
4875
4876 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4877 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4878 if (ssid_len == s->ssid_len &&
4879 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4880 return 1;
4881 }
4882
4883 return 0;
4884}
4885
4886
4887/**
4888 * wpas_request_connection - Request a new connection
4889 * @wpa_s: Pointer to the network interface
4890 *
4891 * This function is used to request a new connection to be found. It will mark
4892 * the interface to allow reassociation and request a new scan to find a
4893 * suitable network to connect to.
4894 */
4895void wpas_request_connection(struct wpa_supplicant *wpa_s)
4896{
4897 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004898 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004899 wpa_supplicant_reinit_autoscan(wpa_s);
4900 wpa_s->extra_blacklist_count = 0;
4901 wpa_s->disconnected = 0;
4902 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004903
4904 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4905 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004906}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004907
4908
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004909void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4910 struct wpa_used_freq_data *freqs_data,
4911 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004912{
4913 unsigned int i;
4914
4915 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4916 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004917 for (i = 0; i < len; i++) {
4918 struct wpa_used_freq_data *cur = &freqs_data[i];
4919 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4920 i, cur->freq, cur->flags);
4921 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004922}
4923
4924
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004925/*
4926 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004927 * are using the same radio as the current interface, and in addition, get
4928 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004929 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004930int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4931 struct wpa_used_freq_data *freqs_data,
4932 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004933{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004934 struct wpa_supplicant *ifs;
4935 u8 bssid[ETH_ALEN];
4936 int freq;
4937 unsigned int idx = 0, i;
4938
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004939 wpa_dbg(wpa_s, MSG_DEBUG,
4940 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004941 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004942
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004943 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4944 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004945 if (idx == len)
4946 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004947
4948 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4949 continue;
4950
4951 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4952 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4953 freq = ifs->current_ssid->frequency;
4954 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4955 freq = ifs->assoc_freq;
4956 else
4957 continue;
4958
4959 /* Hold only distinct freqs */
4960 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004961 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004962 break;
4963
4964 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004965 freqs_data[idx++].freq = freq;
4966
4967 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4968 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4969 WPA_FREQ_USED_BY_P2P_CLIENT :
4970 WPA_FREQ_USED_BY_INFRA_STATION;
4971 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004972 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004973
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004974 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004975 return idx;
4976}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004977
4978
4979/*
4980 * Find the operating frequencies of any of the virtual interfaces that
4981 * are using the same radio as the current interface.
4982 */
4983int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4984 int *freq_array, unsigned int len)
4985{
4986 struct wpa_used_freq_data *freqs_data;
4987 int num, i;
4988
4989 os_memset(freq_array, 0, sizeof(int) * len);
4990
4991 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4992 if (!freqs_data)
4993 return -1;
4994
4995 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4996 for (i = 0; i < num; i++)
4997 freq_array[i] = freqs_data[i].freq;
4998
4999 os_free(freqs_data);
5000
5001 return num;
5002}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005003
5004
5005static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5006{
5007 struct rrm_data *rrm = data;
5008
5009 if (!rrm->notify_neighbor_rep) {
5010 wpa_printf(MSG_ERROR,
5011 "RRM: Unexpected neighbor report timeout");
5012 return;
5013 }
5014
5015 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5016 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5017
5018 rrm->notify_neighbor_rep = NULL;
5019 rrm->neighbor_rep_cb_ctx = NULL;
5020}
5021
5022
5023/*
5024 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5025 * @wpa_s: Pointer to wpa_supplicant
5026 */
5027void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5028{
5029 wpa_s->rrm.rrm_used = 0;
5030
5031 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5032 NULL);
5033 if (wpa_s->rrm.notify_neighbor_rep)
5034 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5035 wpa_s->rrm.next_neighbor_rep_token = 1;
5036}
5037
5038
5039/*
5040 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5041 * @wpa_s: Pointer to wpa_supplicant
5042 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5043 * @report_len: Length of neighbor report buffer
5044 */
5045void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5046 const u8 *report, size_t report_len)
5047{
5048 struct wpabuf *neighbor_rep;
5049
5050 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5051 if (report_len < 1)
5052 return;
5053
5054 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5055 wpa_printf(MSG_DEBUG,
5056 "RRM: Discarding neighbor report with token %d (expected %d)",
5057 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5058 return;
5059 }
5060
5061 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5062 NULL);
5063
5064 if (!wpa_s->rrm.notify_neighbor_rep) {
5065 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5066 return;
5067 }
5068
5069 /* skipping the first byte, which is only an id (dialog token) */
5070 neighbor_rep = wpabuf_alloc(report_len - 1);
5071 if (neighbor_rep == NULL)
5072 return;
5073 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5074 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5075 report[0]);
5076 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5077 neighbor_rep);
5078 wpa_s->rrm.notify_neighbor_rep = NULL;
5079 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5080}
5081
5082
5083/**
5084 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5085 * @wpa_s: Pointer to wpa_supplicant
5086 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5087 * is sent in the request.
5088 * @cb: Callback function to be called once the requested report arrives, or
5089 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5090 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5091 * the requester's responsibility to free it.
5092 * In the latter case NULL will be sent in 'neighbor_rep'.
5093 * @cb_ctx: Context value to send the callback function
5094 * Returns: 0 in case of success, negative error code otherwise
5095 *
5096 * In case there is a previous request which has not been answered yet, the
5097 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5098 * Request must contain a callback function.
5099 */
5100int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5101 const struct wpa_ssid *ssid,
5102 void (*cb)(void *ctx,
5103 struct wpabuf *neighbor_rep),
5104 void *cb_ctx)
5105{
5106 struct wpabuf *buf;
5107 const u8 *rrm_ie;
5108
5109 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5110 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5111 return -ENOTCONN;
5112 }
5113
5114 if (!wpa_s->rrm.rrm_used) {
5115 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5116 return -EOPNOTSUPP;
5117 }
5118
5119 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5120 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5121 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5122 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5123 wpa_printf(MSG_DEBUG,
5124 "RRM: No network support for Neighbor Report.");
5125 return -EOPNOTSUPP;
5126 }
5127
5128 if (!cb) {
5129 wpa_printf(MSG_DEBUG,
5130 "RRM: Neighbor Report request must provide a callback.");
5131 return -EINVAL;
5132 }
5133
5134 /* Refuse if there's a live request */
5135 if (wpa_s->rrm.notify_neighbor_rep) {
5136 wpa_printf(MSG_DEBUG,
5137 "RRM: Currently handling previous Neighbor Report.");
5138 return -EBUSY;
5139 }
5140
5141 /* 3 = action category + action code + dialog token */
5142 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5143 if (buf == NULL) {
5144 wpa_printf(MSG_DEBUG,
5145 "RRM: Failed to allocate Neighbor Report Request");
5146 return -ENOMEM;
5147 }
5148
5149 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5150 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5151 wpa_s->rrm.next_neighbor_rep_token);
5152
5153 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5154 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5155 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5156 if (ssid) {
5157 wpabuf_put_u8(buf, WLAN_EID_SSID);
5158 wpabuf_put_u8(buf, ssid->ssid_len);
5159 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5160 }
5161
5162 wpa_s->rrm.next_neighbor_rep_token++;
5163
5164 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5165 wpa_s->own_addr, wpa_s->bssid,
5166 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5167 wpa_printf(MSG_DEBUG,
5168 "RRM: Failed to send Neighbor Report Request");
5169 wpabuf_free(buf);
5170 return -ECANCELED;
5171 }
5172
5173 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5174 wpa_s->rrm.notify_neighbor_rep = cb;
5175 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5176 wpas_rrm_neighbor_rep_timeout_handler,
5177 &wpa_s->rrm, NULL);
5178
5179 wpabuf_free(buf);
5180 return 0;
5181}
5182
5183
5184void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5185 const u8 *src,
5186 const u8 *frame, size_t len,
5187 int rssi)
5188{
5189 struct wpabuf *buf;
5190 const struct rrm_link_measurement_request *req;
5191 struct rrm_link_measurement_report report;
5192
5193 if (wpa_s->wpa_state != WPA_COMPLETED) {
5194 wpa_printf(MSG_INFO,
5195 "RRM: Ignoring link measurement request. Not associated");
5196 return;
5197 }
5198
5199 if (!wpa_s->rrm.rrm_used) {
5200 wpa_printf(MSG_INFO,
5201 "RRM: Ignoring link measurement request. Not RRM network");
5202 return;
5203 }
5204
5205 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5206 wpa_printf(MSG_INFO,
5207 "RRM: Measurement report failed. TX power insertion not supported");
5208 return;
5209 }
5210
5211 req = (const struct rrm_link_measurement_request *) frame;
5212 if (len < sizeof(*req)) {
5213 wpa_printf(MSG_INFO,
5214 "RRM: Link measurement report failed. Request too short");
5215 return;
5216 }
5217
5218 os_memset(&report, 0, sizeof(report));
5219 report.tpc.eid = WLAN_EID_TPC_REPORT;
5220 report.tpc.len = 2;
5221 report.rsni = 255; /* 255 indicates that RSNI is not available */
5222 report.dialog_token = req->dialog_token;
5223
5224 /*
5225 * It's possible to estimate RCPI based on RSSI in dBm. This
5226 * calculation will not reflect the correct value for high rates,
5227 * but it's good enough for Action frames which are transmitted
5228 * with up to 24 Mbps rates.
5229 */
5230 if (!rssi)
5231 report.rcpi = 255; /* not available */
5232 else if (rssi < -110)
5233 report.rcpi = 0;
5234 else if (rssi > 0)
5235 report.rcpi = 220;
5236 else
5237 report.rcpi = (rssi + 110) * 2;
5238
5239 /* action_category + action_code */
5240 buf = wpabuf_alloc(2 + sizeof(report));
5241 if (buf == NULL) {
5242 wpa_printf(MSG_ERROR,
5243 "RRM: Link measurement report failed. Buffer allocation failed");
5244 return;
5245 }
5246
5247 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5248 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5249 wpabuf_put_data(buf, &report, sizeof(report));
5250 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5251 wpabuf_head(buf), wpabuf_len(buf));
5252
5253 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5254 wpa_s->own_addr, wpa_s->bssid,
5255 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5256 wpa_printf(MSG_ERROR,
5257 "RRM: Link measurement report failed. Send action failed");
5258 }
5259 wpabuf_free(buf);
5260}