blob: 07855764a257726e84afc2e8d39cdc546d55cc2e [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003 * Copyright (c) 2003-2016, 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"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080040#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080042#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "blacklist.h"
44#include "wpas_glue.h"
45#include "wps_supplicant.h"
46#include "ibss_rsn.h"
47#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080048#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "ap.h"
50#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070051#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "notify.h"
53#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "bss.h"
56#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080057#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070059#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070060#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080061#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070063const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtde47be72016-01-07 12:52:55 -080065"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070067const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080068"This software may be distributed under the terms of the BSD license.\n"
69"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070#ifdef EAP_TLS_OPENSSL
71"\nThis product includes software developed by the OpenSSL Project\n"
72"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
73#endif /* EAP_TLS_OPENSSL */
74;
75
76#ifndef CONFIG_NO_STDOUT_DEBUG
77/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070080const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080081"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082"\n"
83"Redistribution and use in source and binary forms, with or without\n"
84"modification, are permitted provided that the following conditions are\n"
85"met:\n"
86"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"1. Redistributions of source code must retain the above copyright\n"
89" notice, this list of conditions and the following disclaimer.\n"
90"\n"
91"2. Redistributions in binary form must reproduce the above copyright\n"
92" notice, this list of conditions and the following disclaimer in the\n"
93" documentation and/or other materials provided with the distribution.\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
97" names of its contributors may be used to endorse or promote products\n"
98" derived from this software without specific prior written permission.\n"
99"\n"
100"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
101"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
102"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
103"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
106"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
107"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
108"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
109"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
110"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
111"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
112"\n";
113#endif /* CONFIG_NO_STDOUT_DEBUG */
114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115/* Configure default/group WEP keys for static WEP */
116int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
117{
118 int i, set = 0;
119
120 for (i = 0; i < NUM_WEP_KEYS; i++) {
121 if (ssid->wep_key_len[i] == 0)
122 continue;
123
124 set = 1;
125 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
126 i, i == ssid->wep_tx_keyidx, NULL, 0,
127 ssid->wep_key[i], ssid->wep_key_len[i]);
128 }
129
130 return set;
131}
132
133
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700134int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
135 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136{
137 u8 key[32];
138 size_t keylen;
139 enum wpa_alg alg;
140 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800141 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700142
143 /* IBSS/WPA-None uses only one key (Group) for both receiving and
144 * sending unicast and multicast packets. */
145
146 if (ssid->mode != WPAS_MODE_IBSS) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
148 "IBSS/ad-hoc) for WPA-None", ssid->mode);
149 return -1;
150 }
151
152 if (!ssid->psk_set) {
153 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
154 "WPA-None");
155 return -1;
156 }
157
158 switch (wpa_s->group_cipher) {
159 case WPA_CIPHER_CCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_CCMP;
163 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700164 case WPA_CIPHER_GCMP:
165 os_memcpy(key, ssid->psk, 16);
166 keylen = 16;
167 alg = WPA_ALG_GCMP;
168 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169 case WPA_CIPHER_TKIP:
170 /* WPA-None uses the same Michael MIC key for both TX and RX */
171 os_memcpy(key, ssid->psk, 16 + 8);
172 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
173 keylen = 32;
174 alg = WPA_ALG_TKIP;
175 break;
176 default:
177 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
178 "WPA-None", wpa_s->group_cipher);
179 return -1;
180 }
181
182 /* TODO: should actually remember the previously used seq#, both for TX
183 * and RX from each STA.. */
184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800185 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
186 os_memset(key, 0, sizeof(key));
187 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700188}
189
190
191static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
192{
193 struct wpa_supplicant *wpa_s = eloop_ctx;
194 const u8 *bssid = wpa_s->bssid;
195 if (is_zero_ether_addr(bssid))
196 bssid = wpa_s->pending_bssid;
197 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
198 MAC2STR(bssid));
199 wpa_blacklist_add(wpa_s, bssid);
200 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800201 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700202 wpa_s->reassociate = 1;
203
204 /*
205 * If we timed out, the AP or the local radio may be busy.
206 * So, wait a second until scanning again.
207 */
208 wpa_supplicant_req_scan(wpa_s, 1, 0);
209}
210
211
212/**
213 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
214 * @wpa_s: Pointer to wpa_supplicant data
215 * @sec: Number of seconds after which to time out authentication
216 * @usec: Number of microseconds after which to time out authentication
217 *
218 * This function is used to schedule a timeout for the current authentication
219 * attempt.
220 */
221void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
222 int sec, int usec)
223{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700224 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
226 return;
227
228 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
229 "%d usec", sec, usec);
230 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
231 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
232}
233
234
235/**
236 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
237 * @wpa_s: Pointer to wpa_supplicant data
238 *
239 * This function is used to cancel authentication timeout scheduled with
240 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
241 * been completed.
242 */
243void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
244{
245 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
246 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
247 wpa_blacklist_del(wpa_s, wpa_s->bssid);
248}
249
250
251/**
252 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
253 * @wpa_s: Pointer to wpa_supplicant data
254 *
255 * This function is used to configure EAPOL state machine based on the selected
256 * authentication mode.
257 */
258void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
259{
260#ifdef IEEE8021X_EAPOL
261 struct eapol_config eapol_conf;
262 struct wpa_ssid *ssid = wpa_s->current_ssid;
263
264#ifdef CONFIG_IBSS_RSN
265 if (ssid->mode == WPAS_MODE_IBSS &&
266 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
267 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
268 /*
269 * RSN IBSS authentication is per-STA and we can disable the
270 * per-BSSID EAPOL authentication.
271 */
272 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
273 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
274 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
275 return;
276 }
277#endif /* CONFIG_IBSS_RSN */
278
279 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
280 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
281
282 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
283 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
284 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
285 else
286 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
287
288 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
289 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
290 eapol_conf.accept_802_1x_keys = 1;
291 eapol_conf.required_keys = 0;
292 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
293 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
294 }
295 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
296 eapol_conf.required_keys |=
297 EAPOL_REQUIRE_KEY_BROADCAST;
298 }
299
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700300 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700301 eapol_conf.required_keys = 0;
302 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700303 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 eapol_conf.workaround = ssid->eap_workaround;
305 eapol_conf.eap_disabled =
306 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
307 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
308 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700309 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800310
311#ifdef CONFIG_WPS
312 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
313 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
314 if (wpa_s->current_bss) {
315 struct wpabuf *ie;
316 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
317 WPS_IE_VENDOR_TYPE);
318 if (ie) {
319 if (wps_is_20(ie))
320 eapol_conf.wps |=
321 EAPOL_PEER_IS_WPS20_AP;
322 wpabuf_free(ie);
323 }
324 }
325 }
326#endif /* CONFIG_WPS */
327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700329
330 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800331#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332}
333
334
335/**
336 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
337 * @wpa_s: Pointer to wpa_supplicant data
338 * @ssid: Configuration data for the network
339 *
340 * This function is used to configure WPA state machine and related parameters
341 * to a mode where WPA is not enabled. This is called as part of the
342 * authentication configuration when the selected network does not use WPA.
343 */
344void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
345 struct wpa_ssid *ssid)
346{
347 int i;
348
349 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
350 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
351 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
352 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
353 else
354 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
355 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
356 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
357 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
358 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
359 wpa_s->group_cipher = WPA_CIPHER_NONE;
360 wpa_s->mgmt_group_cipher = 0;
361
362 for (i = 0; i < NUM_WEP_KEYS; i++) {
363 if (ssid->wep_key_len[i] > 5) {
364 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
365 wpa_s->group_cipher = WPA_CIPHER_WEP104;
366 break;
367 } else if (ssid->wep_key_len[i] > 0) {
368 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
369 wpa_s->group_cipher = WPA_CIPHER_WEP40;
370 break;
371 }
372 }
373
374 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
375 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
376 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
377 wpa_s->pairwise_cipher);
378 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
379#ifdef CONFIG_IEEE80211W
380 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
381 wpa_s->mgmt_group_cipher);
382#endif /* CONFIG_IEEE80211W */
383
384 pmksa_cache_clear_current(wpa_s->wpa);
385}
386
387
Dmitry Shmidt04949592012-07-19 12:16:46 -0700388void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800389{
390 int i;
391 if (wpa_s->hw.modes == NULL)
392 return;
393
394 for (i = 0; i < wpa_s->hw.num_modes; i++) {
395 os_free(wpa_s->hw.modes[i].channels);
396 os_free(wpa_s->hw.modes[i].rates);
397 }
398
399 os_free(wpa_s->hw.modes);
400 wpa_s->hw.modes = NULL;
401}
402
403
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800404static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
405{
406 struct wpa_bss_tmp_disallowed *bss, *prev;
407
408 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
409 struct wpa_bss_tmp_disallowed, list) {
410 dl_list_del(&bss->list);
411 os_free(bss);
412 }
413}
414
415
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
417{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700418 int i;
419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700421 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 scard_deinit(wpa_s->scard);
423 wpa_s->scard = NULL;
424 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
425 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
426 l2_packet_deinit(wpa_s->l2);
427 wpa_s->l2 = NULL;
428 if (wpa_s->l2_br) {
429 l2_packet_deinit(wpa_s->l2_br);
430 wpa_s->l2_br = NULL;
431 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800432#ifdef CONFIG_TESTING_OPTIONS
433 l2_packet_deinit(wpa_s->l2_test);
434 wpa_s->l2_test = NULL;
435#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437 if (wpa_s->conf != NULL) {
438 struct wpa_ssid *ssid;
439 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
440 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 }
442
443 os_free(wpa_s->confname);
444 wpa_s->confname = NULL;
445
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700446 os_free(wpa_s->confanother);
447 wpa_s->confanother = NULL;
448
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700449 wpa_sm_set_eapol(wpa_s->wpa, NULL);
450 eapol_sm_deinit(wpa_s->eapol);
451 wpa_s->eapol = NULL;
452
453 rsn_preauth_deinit(wpa_s->wpa);
454
455#ifdef CONFIG_TDLS
456 wpa_tdls_deinit(wpa_s->wpa);
457#endif /* CONFIG_TDLS */
458
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800459 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700460 pmksa_candidate_free(wpa_s->wpa);
461 wpa_sm_deinit(wpa_s->wpa);
462 wpa_s->wpa = NULL;
463 wpa_blacklist_clear(wpa_s);
464
465 wpa_bss_deinit(wpa_s);
466
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700467 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 wpa_supplicant_cancel_scan(wpa_s);
469 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800470 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
471#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
472 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
473 wpa_s, NULL);
474#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700476 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 wpas_wps_deinit(wpa_s);
479
480 wpabuf_free(wpa_s->pending_eapol_rx);
481 wpa_s->pending_eapol_rx = NULL;
482
483#ifdef CONFIG_IBSS_RSN
484 ibss_rsn_deinit(wpa_s->ibss_rsn);
485 wpa_s->ibss_rsn = NULL;
486#endif /* CONFIG_IBSS_RSN */
487
488 sme_deinit(wpa_s);
489
490#ifdef CONFIG_AP
491 wpa_supplicant_ap_deinit(wpa_s);
492#endif /* CONFIG_AP */
493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700494 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800496#ifdef CONFIG_OFFCHANNEL
497 offchannel_deinit(wpa_s);
498#endif /* CONFIG_OFFCHANNEL */
499
500 wpa_supplicant_cancel_sched_scan(wpa_s);
501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502 os_free(wpa_s->next_scan_freqs);
503 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800504
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800505 os_free(wpa_s->manual_scan_freqs);
506 wpa_s->manual_scan_freqs = NULL;
507
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700508 os_free(wpa_s->manual_sched_scan_freqs);
509 wpa_s->manual_sched_scan_freqs = NULL;
510
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800511 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
512
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700513 /*
514 * Need to remove any pending gas-query radio work before the
515 * gas_query_deinit() call because gas_query::work has not yet been set
516 * for works that have not been started. gas_query_free() will be unable
517 * to cancel such pending radio works and once the pending gas-query
518 * radio work eventually gets removed, the deinit notification call to
519 * gas_query_start_cb() would result in dereferencing freed memory.
520 */
521 if (wpa_s->radio)
522 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800523 gas_query_deinit(wpa_s->gas);
524 wpa_s->gas = NULL;
525
526 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700527
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700528 ieee802_1x_dealloc_kay_sm(wpa_s);
529
Dmitry Shmidt04949592012-07-19 12:16:46 -0700530 os_free(wpa_s->bssid_filter);
531 wpa_s->bssid_filter = NULL;
532
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800533 os_free(wpa_s->disallow_aps_bssid);
534 wpa_s->disallow_aps_bssid = NULL;
535 os_free(wpa_s->disallow_aps_ssid);
536 wpa_s->disallow_aps_ssid = NULL;
537
Dmitry Shmidt04949592012-07-19 12:16:46 -0700538 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700539#ifdef CONFIG_WNM
540 wnm_deallocate_memory(wpa_s);
541#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542
543 ext_password_deinit(wpa_s->ext_pw);
544 wpa_s->ext_pw = NULL;
545
546 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800547 wpa_s->last_gas_resp = NULL;
548 wpabuf_free(wpa_s->prev_gas_resp);
549 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700550
551 os_free(wpa_s->last_scan_res);
552 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800553
554#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700555 if (wpa_s->drv_priv)
556 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700557 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800558#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700559
560 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
561 wpabuf_free(wpa_s->vendor_elem[i]);
562 wpa_s->vendor_elem[i] = NULL;
563 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800564
565 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800566
567 wpa_s->sched_scan_plans_num = 0;
568 os_free(wpa_s->sched_scan_plans);
569 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800570
571#ifdef CONFIG_MBO
572 wpa_s->non_pref_chan_num = 0;
573 os_free(wpa_s->non_pref_chan);
574 wpa_s->non_pref_chan = NULL;
575#endif /* CONFIG_MBO */
576
577 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700578
579 wpabuf_free(wpa_s->lci);
580 wpa_s->lci = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700581}
582
583
584/**
585 * wpa_clear_keys - Clear keys configured for the driver
586 * @wpa_s: Pointer to wpa_supplicant data
587 * @addr: Previously used BSSID or %NULL if not available
588 *
589 * This function clears the encryption keys that has been previously configured
590 * for the driver.
591 */
592void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
593{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800594 int i, max;
595
596#ifdef CONFIG_IEEE80211W
597 max = 6;
598#else /* CONFIG_IEEE80211W */
599 max = 4;
600#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601
602 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800603 for (i = 0; i < max; i++) {
604 if (wpa_s->keys_cleared & BIT(i))
605 continue;
606 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
607 NULL, 0);
608 }
609 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
610 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
612 0);
613 /* MLME-SETPROTECTION.request(None) */
614 wpa_drv_mlme_setprotection(
615 wpa_s, addr,
616 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
617 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
618 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800619 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700620}
621
622
623/**
624 * wpa_supplicant_state_txt - Get the connection state name as a text string
625 * @state: State (wpa_state; WPA_*)
626 * Returns: The state name as a printable text string
627 */
628const char * wpa_supplicant_state_txt(enum wpa_states state)
629{
630 switch (state) {
631 case WPA_DISCONNECTED:
632 return "DISCONNECTED";
633 case WPA_INACTIVE:
634 return "INACTIVE";
635 case WPA_INTERFACE_DISABLED:
636 return "INTERFACE_DISABLED";
637 case WPA_SCANNING:
638 return "SCANNING";
639 case WPA_AUTHENTICATING:
640 return "AUTHENTICATING";
641 case WPA_ASSOCIATING:
642 return "ASSOCIATING";
643 case WPA_ASSOCIATED:
644 return "ASSOCIATED";
645 case WPA_4WAY_HANDSHAKE:
646 return "4WAY_HANDSHAKE";
647 case WPA_GROUP_HANDSHAKE:
648 return "GROUP_HANDSHAKE";
649 case WPA_COMPLETED:
650 return "COMPLETED";
651 default:
652 return "UNKNOWN";
653 }
654}
655
656
657#ifdef CONFIG_BGSCAN
658
659static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
660{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800661 const char *name;
662
663 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
664 name = wpa_s->current_ssid->bgscan;
665 else
666 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800667 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800668 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800669 if (wpas_driver_bss_selection(wpa_s))
670 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
672 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800673#ifdef CONFIG_P2P
674 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
675 return;
676#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677
678 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800679 if (wpa_s->current_ssid) {
680 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
682 "bgscan");
683 /*
684 * Live without bgscan; it is only used as a roaming
685 * optimization, so the initial connection is not
686 * affected.
687 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688 } else {
689 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700691 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
692 0);
693 if (scan_res) {
694 bgscan_notify_scan(wpa_s, scan_res);
695 wpa_scan_results_free(scan_res);
696 }
697 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698 } else
699 wpa_s->bgscan_ssid = NULL;
700}
701
702
703static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
704{
705 if (wpa_s->bgscan_ssid != NULL) {
706 bgscan_deinit(wpa_s);
707 wpa_s->bgscan_ssid = NULL;
708 }
709}
710
711#endif /* CONFIG_BGSCAN */
712
713
Dmitry Shmidt04949592012-07-19 12:16:46 -0700714static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
715{
716 if (autoscan_init(wpa_s, 0))
717 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
718}
719
720
721static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
722{
723 autoscan_deinit(wpa_s);
724}
725
726
727void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
728{
729 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
730 wpa_s->wpa_state == WPA_SCANNING) {
731 autoscan_deinit(wpa_s);
732 wpa_supplicant_start_autoscan(wpa_s);
733 }
734}
735
736
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737/**
738 * wpa_supplicant_set_state - Set current connection state
739 * @wpa_s: Pointer to wpa_supplicant data
740 * @state: The new connection state
741 *
742 * This function is called whenever the connection state changes, e.g.,
743 * association is completed for WPA/WPA2 4-Way Handshake is started.
744 */
745void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
746 enum wpa_states state)
747{
748 enum wpa_states old_state = wpa_s->wpa_state;
749
750 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
751 wpa_supplicant_state_txt(wpa_s->wpa_state),
752 wpa_supplicant_state_txt(state));
753
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800754 if (state == WPA_INTERFACE_DISABLED) {
755 /* Assure normal scan when interface is restored */
756 wpa_s->normal_scans = 0;
757 }
758
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700759 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800760 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700761 /* Reinitialize normal_scan counter */
762 wpa_s->normal_scans = 0;
763 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800764
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700765#ifdef CONFIG_P2P
766 /*
767 * P2PS client has to reply to Probe Request frames received on the
768 * group operating channel. Enable Probe Request frame reporting for
769 * P2P connected client in case p2p_cli_probe configuration property is
770 * set to 1.
771 */
772 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
773 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
774 wpa_s->current_ssid->p2p_group) {
775 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
776 wpa_dbg(wpa_s, MSG_DEBUG,
777 "P2P: Enable CLI Probe Request RX reporting");
778 wpa_s->p2p_cli_probe =
779 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
780 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
781 wpa_dbg(wpa_s, MSG_DEBUG,
782 "P2P: Disable CLI Probe Request RX reporting");
783 wpa_s->p2p_cli_probe = 0;
784 wpa_drv_probe_req_report(wpa_s, 0);
785 }
786 }
787#endif /* CONFIG_P2P */
788
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789 if (state != WPA_SCANNING)
790 wpa_supplicant_notify_scanning(wpa_s, 0);
791
792 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700794#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800796 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800797 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 ssid ? ssid->id : -1,
799 ssid && ssid->id_str ? ssid->id_str : "");
800#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700801 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700802 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800803 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805 wpa_drv_set_operstate(wpa_s, 1);
806#ifndef IEEE8021X_EAPOL
807 wpa_drv_set_supp_port(wpa_s, 1);
808#endif /* IEEE8021X_EAPOL */
809 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700810 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700812
813 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
815 state == WPA_ASSOCIATED) {
816 wpa_s->new_connection = 1;
817 wpa_drv_set_operstate(wpa_s, 0);
818#ifndef IEEE8021X_EAPOL
819 wpa_drv_set_supp_port(wpa_s, 0);
820#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700821 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822 }
823 wpa_s->wpa_state = state;
824
825#ifdef CONFIG_BGSCAN
826 if (state == WPA_COMPLETED)
827 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800828 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 wpa_supplicant_stop_bgscan(wpa_s);
830#endif /* CONFIG_BGSCAN */
831
Dmitry Shmidt04949592012-07-19 12:16:46 -0700832 if (state == WPA_AUTHENTICATING)
833 wpa_supplicant_stop_autoscan(wpa_s);
834
835 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
836 wpa_supplicant_start_autoscan(wpa_s);
837
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800838 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
839 wmm_ac_notify_disassoc(wpa_s);
840
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700841 if (wpa_s->wpa_state != old_state) {
842 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
843
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700844 /*
845 * Notify the P2P Device interface about a state change in one
846 * of the interfaces.
847 */
848 wpas_p2p_indicate_state_change(wpa_s);
849
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 if (wpa_s->wpa_state == WPA_COMPLETED ||
851 old_state == WPA_COMPLETED)
852 wpas_notify_auth_changed(wpa_s);
853 }
854}
855
856
857void wpa_supplicant_terminate_proc(struct wpa_global *global)
858{
859 int pending = 0;
860#ifdef CONFIG_WPS
861 struct wpa_supplicant *wpa_s = global->ifaces;
862 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800863 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700864 if (wpas_wps_terminate_pending(wpa_s) == 1)
865 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700866#ifdef CONFIG_P2P
867 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
868 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
869 wpas_p2p_disconnect(wpa_s);
870#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800871 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 }
873#endif /* CONFIG_WPS */
874 if (pending)
875 return;
876 eloop_terminate();
877}
878
879
880static void wpa_supplicant_terminate(int sig, void *signal_ctx)
881{
882 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700883 wpa_supplicant_terminate_proc(global);
884}
885
886
887void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
888{
889 enum wpa_states old_state = wpa_s->wpa_state;
890
891 wpa_s->pairwise_cipher = 0;
892 wpa_s->group_cipher = 0;
893 wpa_s->mgmt_group_cipher = 0;
894 wpa_s->key_mgmt = 0;
895 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700896 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700897
898 if (wpa_s->wpa_state != old_state)
899 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
900}
901
902
903/**
904 * wpa_supplicant_reload_configuration - Reload configuration data
905 * @wpa_s: Pointer to wpa_supplicant data
906 * Returns: 0 on success or -1 if configuration parsing failed
907 *
908 * This function can be used to request that the configuration data is reloaded
909 * (e.g., after configuration file change). This function is reloading
910 * configuration only for one interface, so this may need to be called multiple
911 * times if %wpa_supplicant is controlling multiple interfaces and all
912 * interfaces need reconfiguration.
913 */
914int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
915{
916 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917 int reconf_ctrl;
918 int old_ap_scan;
919
920 if (wpa_s->confname == NULL)
921 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700922 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700923 if (conf == NULL) {
924 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
925 "file '%s' - exiting", wpa_s->confname);
926 return -1;
927 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700928 wpa_config_read(wpa_s->confanother, conf);
929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 conf->changed_parameters = (unsigned int) -1;
931
932 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
933 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
934 os_strcmp(conf->ctrl_interface,
935 wpa_s->conf->ctrl_interface) != 0);
936
937 if (reconf_ctrl && wpa_s->ctrl_iface) {
938 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
939 wpa_s->ctrl_iface = NULL;
940 }
941
942 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800943 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700944 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
945 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800946 wpa_supplicant_deauthenticate(wpa_s,
947 WLAN_REASON_DEAUTH_LEAVING);
948 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700949
950 /*
951 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800952 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700953 */
954 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
955 /*
956 * Clear forced success to clear EAP state for next
957 * authentication.
958 */
959 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
960 }
961 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
962 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800963 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700964 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
965 rsn_preauth_deinit(wpa_s->wpa);
966
967 old_ap_scan = wpa_s->conf->ap_scan;
968 wpa_config_free(wpa_s->conf);
969 wpa_s->conf = conf;
970 if (old_ap_scan != wpa_s->conf->ap_scan)
971 wpas_notify_ap_scan_changed(wpa_s);
972
973 if (reconf_ctrl)
974 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
975
976 wpa_supplicant_update_config(wpa_s);
977
978 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700979 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980 wpa_s->reassociate = 1;
981 wpa_supplicant_req_scan(wpa_s, 0, 0);
982 }
983 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
984 return 0;
985}
986
987
988static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
989{
990 struct wpa_global *global = signal_ctx;
991 struct wpa_supplicant *wpa_s;
992 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
993 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
994 sig);
995 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
996 wpa_supplicant_terminate_proc(global);
997 }
998 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800999
1000 if (wpa_debug_reopen_file() < 0) {
1001 /* Ignore errors since we cannot really do much to fix this */
1002 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1003 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004}
1005
1006
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1008 struct wpa_ssid *ssid,
1009 struct wpa_ie_data *ie)
1010{
1011 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1012 if (ret) {
1013 if (ret == -2) {
1014 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1015 "from association info");
1016 }
1017 return -1;
1018 }
1019
1020 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1021 "cipher suites");
1022 if (!(ie->group_cipher & ssid->group_cipher)) {
1023 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1024 "cipher 0x%x (mask 0x%x) - reject",
1025 ie->group_cipher, ssid->group_cipher);
1026 return -1;
1027 }
1028 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1029 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1030 "cipher 0x%x (mask 0x%x) - reject",
1031 ie->pairwise_cipher, ssid->pairwise_cipher);
1032 return -1;
1033 }
1034 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1035 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1036 "management 0x%x (mask 0x%x) - reject",
1037 ie->key_mgmt, ssid->key_mgmt);
1038 return -1;
1039 }
1040
1041#ifdef CONFIG_IEEE80211W
1042 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001043 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1045 "that does not support management frame protection - "
1046 "reject");
1047 return -1;
1048 }
1049#endif /* CONFIG_IEEE80211W */
1050
1051 return 0;
1052}
1053
1054
1055/**
1056 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1057 * @wpa_s: Pointer to wpa_supplicant data
1058 * @bss: Scan results for the selected BSS, or %NULL if not available
1059 * @ssid: Configuration data for the selected network
1060 * @wpa_ie: Buffer for the WPA/RSN IE
1061 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1062 * used buffer length in case the functions returns success.
1063 * Returns: 0 on success or -1 on failure
1064 *
1065 * This function is used to configure authentication and encryption parameters
1066 * based on the network configuration and scan result for the selected BSS (if
1067 * available).
1068 */
1069int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1070 struct wpa_bss *bss, struct wpa_ssid *ssid,
1071 u8 *wpa_ie, size_t *wpa_ie_len)
1072{
1073 struct wpa_ie_data ie;
1074 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001075 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076
1077 if (bss) {
1078 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1079 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001080 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001082 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083
1084 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1085 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1086 (ie.group_cipher & ssid->group_cipher) &&
1087 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1088 (ie.key_mgmt & ssid->key_mgmt)) {
1089 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1090 proto = WPA_PROTO_RSN;
1091 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001092 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001093 (ie.group_cipher & ssid->group_cipher) &&
1094 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1095 (ie.key_mgmt & ssid->key_mgmt)) {
1096 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1097 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001098#ifdef CONFIG_HS20
1099 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1100 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1101 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001102 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001103 ie.group_cipher = WPA_CIPHER_CCMP;
1104 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1105 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1106 proto = WPA_PROTO_OSEN;
1107#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 } else if (bss) {
1109 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001110 wpa_dbg(wpa_s, MSG_DEBUG,
1111 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1112 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1113 ssid->key_mgmt);
1114 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1115 MAC2STR(bss->bssid),
1116 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1117 bss_wpa ? " WPA" : "",
1118 bss_rsn ? " RSN" : "",
1119 bss_osen ? " OSEN" : "");
1120 if (bss_rsn) {
1121 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1122 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1123 wpa_dbg(wpa_s, MSG_DEBUG,
1124 "Could not parse RSN element");
1125 } else {
1126 wpa_dbg(wpa_s, MSG_DEBUG,
1127 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1128 ie.pairwise_cipher, ie.group_cipher,
1129 ie.key_mgmt);
1130 }
1131 }
1132 if (bss_wpa) {
1133 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1134 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1135 wpa_dbg(wpa_s, MSG_DEBUG,
1136 "Could not parse WPA element");
1137 } else {
1138 wpa_dbg(wpa_s, MSG_DEBUG,
1139 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1140 ie.pairwise_cipher, ie.group_cipher,
1141 ie.key_mgmt);
1142 }
1143 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 return -1;
1145 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001146 if (ssid->proto & WPA_PROTO_OSEN)
1147 proto = WPA_PROTO_OSEN;
1148 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149 proto = WPA_PROTO_RSN;
1150 else
1151 proto = WPA_PROTO_WPA;
1152 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1153 os_memset(&ie, 0, sizeof(ie));
1154 ie.group_cipher = ssid->group_cipher;
1155 ie.pairwise_cipher = ssid->pairwise_cipher;
1156 ie.key_mgmt = ssid->key_mgmt;
1157#ifdef CONFIG_IEEE80211W
1158 ie.mgmt_group_cipher =
1159 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1160 WPA_CIPHER_AES_128_CMAC : 0;
1161#endif /* CONFIG_IEEE80211W */
1162 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1163 "based on configuration");
1164 } else
1165 proto = ie.proto;
1166 }
1167
1168 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1169 "pairwise %d key_mgmt %d proto %d",
1170 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1171#ifdef CONFIG_IEEE80211W
1172 if (ssid->ieee80211w) {
1173 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1174 ie.mgmt_group_cipher);
1175 }
1176#endif /* CONFIG_IEEE80211W */
1177
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001178 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001179 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1180 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001181 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001182
1183 if (bss || !wpa_s->ap_ies_from_associnfo) {
1184 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1185 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1186 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1187 bss_rsn ? 2 + bss_rsn[1] : 0))
1188 return -1;
1189 }
1190
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001191#ifdef CONFIG_NO_WPA
1192 wpa_s->group_cipher = WPA_CIPHER_NONE;
1193 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1194#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001196 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1197 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1199 "cipher");
1200 return -1;
1201 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001202 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1203 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204
1205 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001206 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1207 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001208 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1209 "cipher");
1210 return -1;
1211 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001212 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1213 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001214#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001215
1216 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001217#ifdef CONFIG_SAE
1218 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1219 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1220#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001221 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001222#ifdef CONFIG_SUITEB192
1223 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1224 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1225 wpa_dbg(wpa_s, MSG_DEBUG,
1226 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1227#endif /* CONFIG_SUITEB192 */
1228#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001229 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1230 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1231 wpa_dbg(wpa_s, MSG_DEBUG,
1232 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001233#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001234#ifdef CONFIG_IEEE80211R
1235 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1236 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1237 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1238 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1239 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1240 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1241#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001242#ifdef CONFIG_SAE
1243 } else if (sel & WPA_KEY_MGMT_SAE) {
1244 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1245 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1246 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1247 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1248 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1249#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250#ifdef CONFIG_IEEE80211W
1251 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1252 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1253 wpa_dbg(wpa_s, MSG_DEBUG,
1254 "WPA: using KEY_MGMT 802.1X with SHA256");
1255 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1256 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1257 wpa_dbg(wpa_s, MSG_DEBUG,
1258 "WPA: using KEY_MGMT PSK with SHA256");
1259#endif /* CONFIG_IEEE80211W */
1260 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1261 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1262 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1263 } else if (sel & WPA_KEY_MGMT_PSK) {
1264 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1265 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1266 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1267 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1268 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001269#ifdef CONFIG_HS20
1270 } else if (sel & WPA_KEY_MGMT_OSEN) {
1271 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1272 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1273#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 } else {
1275 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1276 "authenticated key management type");
1277 return -1;
1278 }
1279
1280 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1281 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1282 wpa_s->pairwise_cipher);
1283 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1284
1285#ifdef CONFIG_IEEE80211W
1286 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001287 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1289 sel = 0;
1290 if (sel & WPA_CIPHER_AES_128_CMAC) {
1291 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1292 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1293 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001294 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1295 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1296 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1297 "BIP-GMAC-128");
1298 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1299 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1300 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1301 "BIP-GMAC-256");
1302 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1303 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1304 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1305 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001306 } else {
1307 wpa_s->mgmt_group_cipher = 0;
1308 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1309 }
1310 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1311 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001312 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001313 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001314#endif /* CONFIG_IEEE80211W */
1315
1316 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1317 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1318 return -1;
1319 }
1320
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001321 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001322 int psk_set = 0;
1323
1324 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001325 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1326 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001327 psk_set = 1;
1328 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001329#ifndef CONFIG_NO_PBKDF2
1330 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1331 ssid->passphrase) {
1332 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001333 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1334 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001335 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1336 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001337 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001338 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001339 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001340 }
1341#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001342#ifdef CONFIG_EXT_PASSWORD
1343 if (ssid->ext_psk) {
1344 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1345 ssid->ext_psk);
1346 char pw_str[64 + 1];
1347 u8 psk[PMK_LEN];
1348
1349 if (pw == NULL) {
1350 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1351 "found from external storage");
1352 return -1;
1353 }
1354
1355 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1356 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1357 "PSK length %d in external storage",
1358 (int) wpabuf_len(pw));
1359 ext_password_free(pw);
1360 return -1;
1361 }
1362
1363 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1364 pw_str[wpabuf_len(pw)] = '\0';
1365
1366#ifndef CONFIG_NO_PBKDF2
1367 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1368 {
1369 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1370 4096, psk, PMK_LEN);
1371 os_memset(pw_str, 0, sizeof(pw_str));
1372 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1373 "external passphrase)",
1374 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001375 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1376 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001377 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001378 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001379 } else
1380#endif /* CONFIG_NO_PBKDF2 */
1381 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1382 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1383 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1384 "Invalid PSK hex string");
1385 os_memset(pw_str, 0, sizeof(pw_str));
1386 ext_password_free(pw);
1387 return -1;
1388 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001389 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1390 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001391 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001392 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001393 } else {
1394 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1395 "PSK available");
1396 os_memset(pw_str, 0, sizeof(pw_str));
1397 ext_password_free(pw);
1398 return -1;
1399 }
1400
1401 os_memset(pw_str, 0, sizeof(pw_str));
1402 ext_password_free(pw);
1403 }
1404#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001405
1406 if (!psk_set) {
1407 wpa_msg(wpa_s, MSG_INFO,
1408 "No PSK available for association");
1409 return -1;
1410 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001411 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1413
1414 return 0;
1415}
1416
1417
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001418static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1419{
1420 *pos = 0x00;
1421
1422 switch (idx) {
1423 case 0: /* Bits 0-7 */
1424 break;
1425 case 1: /* Bits 8-15 */
1426 break;
1427 case 2: /* Bits 16-23 */
1428#ifdef CONFIG_WNM
1429 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1430 *pos |= 0x08; /* Bit 19 - BSS Transition */
1431#endif /* CONFIG_WNM */
1432 break;
1433 case 3: /* Bits 24-31 */
1434#ifdef CONFIG_WNM
1435 *pos |= 0x02; /* Bit 25 - SSID List */
1436#endif /* CONFIG_WNM */
1437#ifdef CONFIG_INTERWORKING
1438 if (wpa_s->conf->interworking)
1439 *pos |= 0x80; /* Bit 31 - Interworking */
1440#endif /* CONFIG_INTERWORKING */
1441 break;
1442 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001443#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001444 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1445 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001446#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001447 break;
1448 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001449#ifdef CONFIG_HS20
1450 if (wpa_s->conf->hs20)
1451 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1452#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001453#ifdef CONFIG_MBO
1454 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1455#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001456 break;
1457 case 6: /* Bits 48-55 */
1458 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001459 case 7: /* Bits 56-63 */
1460 break;
1461 case 8: /* Bits 64-71 */
1462 if (wpa_s->conf->ftm_responder)
1463 *pos |= 0x40; /* Bit 70 - FTM responder */
1464 if (wpa_s->conf->ftm_initiator)
1465 *pos |= 0x80; /* Bit 71 - FTM initiator */
1466 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001467 }
1468}
1469
1470
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001471int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001472{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001473 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001474 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001475
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001476 if (len < 9 &&
1477 (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
1478 len = 9;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001479 if (len < wpa_s->extended_capa_len)
1480 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001481 if (buflen < (size_t) len + 2) {
1482 wpa_printf(MSG_INFO,
1483 "Not enough room for building extended capabilities element");
1484 return -1;
1485 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001486
1487 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001488 *pos++ = len;
1489 for (i = 0; i < len; i++, pos++) {
1490 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001491
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001492 if (i < wpa_s->extended_capa_len) {
1493 *pos &= ~wpa_s->extended_capa_mask[i];
1494 *pos |= wpa_s->extended_capa[i];
1495 }
1496 }
1497
1498 while (len > 0 && buf[1 + len] == 0) {
1499 len--;
1500 buf[1] = len;
1501 }
1502 if (len == 0)
1503 return 0;
1504
1505 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001506}
1507
1508
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001509static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1510 struct wpa_bss *test_bss)
1511{
1512 struct wpa_bss *bss;
1513
1514 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1515 if (bss == test_bss)
1516 return 1;
1517 }
1518
1519 return 0;
1520}
1521
1522
1523static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1524 struct wpa_ssid *test_ssid)
1525{
1526 struct wpa_ssid *ssid;
1527
1528 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1529 if (ssid == test_ssid)
1530 return 1;
1531 }
1532
1533 return 0;
1534}
1535
1536
1537int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1538 struct wpa_ssid *test_ssid)
1539{
1540 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1541 return 0;
1542
1543 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1544}
1545
1546
1547void wpas_connect_work_free(struct wpa_connect_work *cwork)
1548{
1549 if (cwork == NULL)
1550 return;
1551 os_free(cwork);
1552}
1553
1554
1555void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1556{
1557 struct wpa_connect_work *cwork;
1558 struct wpa_radio_work *work = wpa_s->connect_work;
1559
1560 if (!work)
1561 return;
1562
1563 wpa_s->connect_work = NULL;
1564 cwork = work->ctx;
1565 work->ctx = NULL;
1566 wpas_connect_work_free(cwork);
1567 radio_work_done(work);
1568}
1569
1570
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001571int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1572{
1573 struct os_reltime now;
1574 u8 addr[ETH_ALEN];
1575
1576 os_get_reltime(&now);
1577 if (wpa_s->last_mac_addr_style == style &&
1578 wpa_s->last_mac_addr_change.sec != 0 &&
1579 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1580 wpa_s->conf->rand_addr_lifetime)) {
1581 wpa_msg(wpa_s, MSG_DEBUG,
1582 "Previously selected random MAC address has not yet expired");
1583 return 0;
1584 }
1585
1586 switch (style) {
1587 case 1:
1588 if (random_mac_addr(addr) < 0)
1589 return -1;
1590 break;
1591 case 2:
1592 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1593 if (random_mac_addr_keep_oui(addr) < 0)
1594 return -1;
1595 break;
1596 default:
1597 return -1;
1598 }
1599
1600 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1601 wpa_msg(wpa_s, MSG_INFO,
1602 "Failed to set random MAC address");
1603 return -1;
1604 }
1605
1606 os_get_reltime(&wpa_s->last_mac_addr_change);
1607 wpa_s->mac_addr_changed = 1;
1608 wpa_s->last_mac_addr_style = style;
1609
1610 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1611 wpa_msg(wpa_s, MSG_INFO,
1612 "Could not update MAC address information");
1613 return -1;
1614 }
1615
1616 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1617 MAC2STR(addr));
1618
1619 return 0;
1620}
1621
1622
1623int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1624{
1625 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1626 !wpa_s->conf->preassoc_mac_addr)
1627 return 0;
1628
1629 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1630}
1631
1632
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001633static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635/**
1636 * wpa_supplicant_associate - Request association
1637 * @wpa_s: Pointer to wpa_supplicant data
1638 * @bss: Scan results for the selected BSS, or %NULL if not available
1639 * @ssid: Configuration data for the selected network
1640 *
1641 * This function is used to request %wpa_supplicant to associate with a BSS.
1642 */
1643void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1644 struct wpa_bss *bss, struct wpa_ssid *ssid)
1645{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001646 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001647 int rand_style;
1648
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001649 wpa_s->own_disconnect_req = 0;
1650
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001651 /*
1652 * If we are starting a new connection, any previously pending EAPOL
1653 * RX cannot be valid anymore.
1654 */
1655 wpabuf_free(wpa_s->pending_eapol_rx);
1656 wpa_s->pending_eapol_rx = NULL;
1657
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001658 if (ssid->mac_addr == -1)
1659 rand_style = wpa_s->conf->mac_addr;
1660 else
1661 rand_style = ssid->mac_addr;
1662
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001663 wmm_ac_clear_saved_tspecs(wpa_s);
1664 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001665 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001666
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001667 if (wpa_s->last_ssid == ssid) {
1668 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001669 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001670 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1671 wmm_ac_save_tspecs(wpa_s);
1672 wpa_s->reassoc_same_bss = 1;
1673 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001674 } else if (rand_style > 0) {
1675 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1676 return;
1677 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1678 } else if (wpa_s->mac_addr_changed) {
1679 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1680 wpa_msg(wpa_s, MSG_INFO,
1681 "Could not restore permanent MAC address");
1682 return;
1683 }
1684 wpa_s->mac_addr_changed = 0;
1685 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1686 wpa_msg(wpa_s, MSG_INFO,
1687 "Could not update MAC address information");
1688 return;
1689 }
1690 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1691 }
1692 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693
1694#ifdef CONFIG_IBSS_RSN
1695 ibss_rsn_deinit(wpa_s->ibss_rsn);
1696 wpa_s->ibss_rsn = NULL;
1697#endif /* CONFIG_IBSS_RSN */
1698
1699 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1700 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1701#ifdef CONFIG_AP
1702 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1703 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1704 "mode");
1705 return;
1706 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001707 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1708 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001709 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1710 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001711 return;
1712 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001713 wpa_s->current_bss = bss;
1714#else /* CONFIG_AP */
1715 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1716 "the build");
1717#endif /* CONFIG_AP */
1718 return;
1719 }
1720
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001721 if (ssid->mode == WPAS_MODE_MESH) {
1722#ifdef CONFIG_MESH
1723 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1724 wpa_msg(wpa_s, MSG_INFO,
1725 "Driver does not support mesh mode");
1726 return;
1727 }
1728 if (bss)
1729 ssid->frequency = bss->freq;
1730 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1731 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1732 return;
1733 }
1734 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001735 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1736 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1737 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001738#else /* CONFIG_MESH */
1739 wpa_msg(wpa_s, MSG_ERROR,
1740 "mesh mode support not included in the build");
1741#endif /* CONFIG_MESH */
1742 return;
1743 }
1744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745#ifdef CONFIG_TDLS
1746 if (bss)
1747 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1748 bss->ie_len);
1749#endif /* CONFIG_TDLS */
1750
1751 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1752 ssid->mode == IEEE80211_MODE_INFRA) {
1753 sme_authenticate(wpa_s, bss, ssid);
1754 return;
1755 }
1756
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001757 if (wpa_s->connect_work) {
1758 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1759 return;
1760 }
1761
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001762 if (radio_work_pending(wpa_s, "connect")) {
1763 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1764 return;
1765 }
1766
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001767 wpas_abort_ongoing_scan(wpa_s);
1768
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001769 cwork = os_zalloc(sizeof(*cwork));
1770 if (cwork == NULL)
1771 return;
1772
1773 cwork->bss = bss;
1774 cwork->ssid = ssid;
1775
1776 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1777 wpas_start_assoc_cb, cwork) < 0) {
1778 os_free(cwork);
1779 }
1780}
1781
1782
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001783static int bss_is_ibss(struct wpa_bss *bss)
1784{
1785 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1786 IEEE80211_CAP_IBSS;
1787}
1788
1789
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001790static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1791 const struct wpa_ssid *ssid)
1792{
1793 enum hostapd_hw_mode hw_mode;
1794 struct hostapd_hw_modes *mode = NULL;
1795 u8 channel;
1796 int i;
1797
1798#ifdef CONFIG_HT_OVERRIDES
1799 if (ssid->disable_ht)
1800 return 0;
1801#endif /* CONFIG_HT_OVERRIDES */
1802
1803 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1804 if (hw_mode == NUM_HOSTAPD_MODES)
1805 return 0;
1806 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1807 if (wpa_s->hw.modes[i].mode == hw_mode) {
1808 mode = &wpa_s->hw.modes[i];
1809 break;
1810 }
1811 }
1812
1813 if (!mode)
1814 return 0;
1815
1816 return mode->vht_capab != 0;
1817}
1818
1819
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001820void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1821 const struct wpa_ssid *ssid,
1822 struct hostapd_freq_params *freq)
1823{
1824 enum hostapd_hw_mode hw_mode;
1825 struct hostapd_hw_modes *mode = NULL;
1826 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1827 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001828 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001829 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1830 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001831 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001832 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001833 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001834 int chwidth, seg0, seg1;
1835 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001836
1837 freq->freq = ssid->frequency;
1838
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001839 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1840 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1841
1842 if (ssid->mode != WPAS_MODE_IBSS)
1843 break;
1844
1845 /* Don't adjust control freq in case of fixed_freq */
1846 if (ssid->fixed_freq)
1847 break;
1848
1849 if (!bss_is_ibss(bss))
1850 continue;
1851
1852 if (ssid->ssid_len == bss->ssid_len &&
1853 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1854 wpa_printf(MSG_DEBUG,
1855 "IBSS already found in scan results, adjust control freq: %d",
1856 bss->freq);
1857 freq->freq = bss->freq;
1858 obss_scan = 0;
1859 break;
1860 }
1861 }
1862
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001863 /* For IBSS check HT_IBSS flag */
1864 if (ssid->mode == WPAS_MODE_IBSS &&
1865 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1866 return;
1867
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001868 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1869 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1870 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1871 wpa_printf(MSG_DEBUG,
1872 "IBSS: WEP/TKIP detected, do not try to enable HT");
1873 return;
1874 }
1875
1876 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001877 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1878 if (wpa_s->hw.modes[i].mode == hw_mode) {
1879 mode = &wpa_s->hw.modes[i];
1880 break;
1881 }
1882 }
1883
1884 if (!mode)
1885 return;
1886
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001887#ifdef CONFIG_HT_OVERRIDES
1888 if (ssid->disable_ht) {
1889 freq->ht_enabled = 0;
1890 return;
1891 }
1892#endif /* CONFIG_HT_OVERRIDES */
1893
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001894 freq->ht_enabled = ht_supported(mode);
1895 if (!freq->ht_enabled)
1896 return;
1897
1898 /* Setup higher BW only for 5 GHz */
1899 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1900 return;
1901
1902 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1903 pri_chan = &mode->channels[chan_idx];
1904 if (pri_chan->chan == channel)
1905 break;
1906 pri_chan = NULL;
1907 }
1908 if (!pri_chan)
1909 return;
1910
1911 /* Check primary channel flags */
1912 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1913 return;
1914
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001915#ifdef CONFIG_HT_OVERRIDES
1916 if (ssid->disable_ht40)
1917 return;
1918#endif /* CONFIG_HT_OVERRIDES */
1919
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001920 /* Check/setup HT40+/HT40- */
1921 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1922 if (ht40plus[j] == channel) {
1923 ht40 = 1;
1924 break;
1925 }
1926 }
1927
1928 /* Find secondary channel */
1929 for (i = 0; i < mode->num_channels; i++) {
1930 sec_chan = &mode->channels[i];
1931 if (sec_chan->chan == channel + ht40 * 4)
1932 break;
1933 sec_chan = NULL;
1934 }
1935 if (!sec_chan)
1936 return;
1937
1938 /* Check secondary channel flags */
1939 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1940 return;
1941
1942 freq->channel = pri_chan->chan;
1943
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001944 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001945 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1946 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001947 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001948 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1949 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001950 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001951 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001952
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001953 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001954 struct wpa_scan_results *scan_res;
1955
1956 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1957 if (scan_res == NULL) {
1958 /* Back to HT20 */
1959 freq->sec_channel_offset = 0;
1960 return;
1961 }
1962
1963 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1964 sec_chan->chan);
1965 switch (res) {
1966 case 0:
1967 /* Back to HT20 */
1968 freq->sec_channel_offset = 0;
1969 break;
1970 case 1:
1971 /* Configuration allowed */
1972 break;
1973 case 2:
1974 /* Switch pri/sec channels */
1975 freq->freq = hw_get_freq(mode, sec_chan->chan);
1976 freq->sec_channel_offset = -freq->sec_channel_offset;
1977 freq->channel = sec_chan->chan;
1978 break;
1979 default:
1980 freq->sec_channel_offset = 0;
1981 break;
1982 }
1983
1984 wpa_scan_results_free(scan_res);
1985 }
1986
1987 wpa_printf(MSG_DEBUG,
1988 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1989 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001990
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001991 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001992 return;
1993
1994 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001995 if (ssid->mode == WPAS_MODE_IBSS &&
1996 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001997 return;
1998
1999 vht_freq = *freq;
2000
2001 vht_freq.vht_enabled = vht_supported(mode);
2002 if (!vht_freq.vht_enabled)
2003 return;
2004
2005 /* setup center_freq1, bandwidth */
2006 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2007 if (freq->channel >= vht80[j] &&
2008 freq->channel < vht80[j] + 16)
2009 break;
2010 }
2011
2012 if (j == ARRAY_SIZE(vht80))
2013 return;
2014
2015 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2016 struct hostapd_channel_data *chan;
2017
2018 chan = hw_get_channel_chan(mode, i, NULL);
2019 if (!chan)
2020 return;
2021
2022 /* Back to HT configuration if channel not usable */
2023 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2024 return;
2025 }
2026
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002027 chwidth = VHT_CHANWIDTH_80MHZ;
2028 seg0 = vht80[j] + 6;
2029 seg1 = 0;
2030
2031 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2032 /* setup center_freq2, bandwidth */
2033 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2034 /* Only accept 80 MHz segments separated by a gap */
2035 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2036 continue;
2037 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2038 struct hostapd_channel_data *chan;
2039
2040 chan = hw_get_channel_chan(mode, i, NULL);
2041 if (!chan)
2042 continue;
2043
2044 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2045 HOSTAPD_CHAN_NO_IR |
2046 HOSTAPD_CHAN_RADAR))
2047 continue;
2048
2049 /* Found a suitable second segment for 80+80 */
2050 chwidth = VHT_CHANWIDTH_80P80MHZ;
2051 vht_caps |=
2052 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2053 seg1 = vht80[k] + 6;
2054 }
2055
2056 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2057 break;
2058 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002059 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2060 if (freq->freq == 5180) {
2061 chwidth = VHT_CHANWIDTH_160MHZ;
2062 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2063 seg0 = 50;
2064 } else if (freq->freq == 5520) {
2065 chwidth = VHT_CHANWIDTH_160MHZ;
2066 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2067 seg0 = 114;
2068 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002069 }
2070
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002071 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2072 freq->channel, freq->ht_enabled,
2073 vht_freq.vht_enabled,
2074 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002075 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002076 return;
2077
2078 *freq = vht_freq;
2079
2080 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2081 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002082}
2083
2084
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002085static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2086{
2087 struct wpa_connect_work *cwork = work->ctx;
2088 struct wpa_bss *bss = cwork->bss;
2089 struct wpa_ssid *ssid = cwork->ssid;
2090 struct wpa_supplicant *wpa_s = work->wpa_s;
2091 u8 wpa_ie[200];
2092 size_t wpa_ie_len;
2093 int use_crypt, ret, i, bssid_changed;
2094 int algs = WPA_AUTH_ALG_OPEN;
2095 unsigned int cipher_pairwise, cipher_group;
2096 struct wpa_driver_associate_params params;
2097 int wep_keys_set = 0;
2098 int assoc_failed = 0;
2099 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002100 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002101#ifdef CONFIG_HT_OVERRIDES
2102 struct ieee80211_ht_capabilities htcaps;
2103 struct ieee80211_ht_capabilities htcaps_mask;
2104#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002105#ifdef CONFIG_VHT_OVERRIDES
2106 struct ieee80211_vht_capabilities vhtcaps;
2107 struct ieee80211_vht_capabilities vhtcaps_mask;
2108#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002109#ifdef CONFIG_MBO
2110 const u8 *mbo = NULL;
2111#endif /* CONFIG_MBO */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002112
2113 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002114 if (work->started) {
2115 wpa_s->connect_work = NULL;
2116
2117 /* cancel possible auth. timeout */
2118 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2119 NULL);
2120 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002121 wpas_connect_work_free(cwork);
2122 return;
2123 }
2124
2125 wpa_s->connect_work = work;
2126
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002127 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2128 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002129 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2130 wpas_connect_work_done(wpa_s);
2131 return;
2132 }
2133
Dmitry Shmidte4663042016-04-04 10:07:49 -07002134 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 os_memset(&params, 0, sizeof(params));
2136 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002137 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002138 if (bss &&
2139 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002140#ifdef CONFIG_IEEE80211R
2141 const u8 *ie, *md = NULL;
2142#endif /* CONFIG_IEEE80211R */
2143 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2144 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2145 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2146 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2147 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2148 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2149 if (bssid_changed)
2150 wpas_notify_bssid_changed(wpa_s);
2151#ifdef CONFIG_IEEE80211R
2152 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2153 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2154 md = ie + 2;
2155 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2156 if (md) {
2157 /* Prepare for the next transition */
2158 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2159 }
2160#endif /* CONFIG_IEEE80211R */
2161#ifdef CONFIG_WPS
2162 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2163 wpa_s->conf->ap_scan == 2 &&
2164 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2165 /* Use ap_scan==1 style network selection to find the network
2166 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002167 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002168 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 wpa_s->reassociate = 1;
2170 wpa_supplicant_req_scan(wpa_s, 0, 0);
2171 return;
2172#endif /* CONFIG_WPS */
2173 } else {
2174 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2175 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2176 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2177 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002178 if (!wpa_s->pno)
2179 wpa_supplicant_cancel_sched_scan(wpa_s);
2180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002181 wpa_supplicant_cancel_scan(wpa_s);
2182
2183 /* Starting new association, so clear the possibly used WPA IE from the
2184 * previous association. */
2185 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2186
2187#ifdef IEEE8021X_EAPOL
2188 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2189 if (ssid->leap) {
2190 if (ssid->non_leap == 0)
2191 algs = WPA_AUTH_ALG_LEAP;
2192 else
2193 algs |= WPA_AUTH_ALG_LEAP;
2194 }
2195 }
2196#endif /* IEEE8021X_EAPOL */
2197 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2198 if (ssid->auth_alg) {
2199 algs = ssid->auth_alg;
2200 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2201 "0x%x", algs);
2202 }
2203
2204 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2205 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002206 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002208 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2209 wpa_s->conf->okc :
2210 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 (ssid->proto & WPA_PROTO_RSN);
2212 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002213 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002214 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002215 wpa_ie_len = sizeof(wpa_ie);
2216 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2217 wpa_ie, &wpa_ie_len)) {
2218 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2219 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002220 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 return;
2222 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002223 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2224 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2225 /*
2226 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2227 * use non-WPA since the scan results did not indicate that the
2228 * AP is using WPA or WPA2.
2229 */
2230 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2231 wpa_ie_len = 0;
2232 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002233 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234 wpa_ie_len = sizeof(wpa_ie);
2235 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2236 wpa_ie, &wpa_ie_len)) {
2237 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2238 "key management and encryption suites (no "
2239 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002240 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 return;
2242 }
2243#ifdef CONFIG_WPS
2244 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2245 struct wpabuf *wps_ie;
2246 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2247 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2248 wpa_ie_len = wpabuf_len(wps_ie);
2249 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2250 } else
2251 wpa_ie_len = 0;
2252 wpabuf_free(wps_ie);
2253 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2254 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2255 params.wps = WPS_MODE_PRIVACY;
2256 else
2257 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002258 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259#endif /* CONFIG_WPS */
2260 } else {
2261 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2262 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002263 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 }
2265
2266#ifdef CONFIG_P2P
2267 if (wpa_s->global->p2p) {
2268 u8 *pos;
2269 size_t len;
2270 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 pos = wpa_ie + wpa_ie_len;
2272 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002273 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2274 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002275 if (res >= 0)
2276 wpa_ie_len += res;
2277 }
2278
2279 wpa_s->cross_connect_disallowed = 0;
2280 if (bss) {
2281 struct wpabuf *p2p;
2282 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2283 if (p2p) {
2284 wpa_s->cross_connect_disallowed =
2285 p2p_get_cross_connect_disallowed(p2p);
2286 wpabuf_free(p2p);
2287 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2288 "connection",
2289 wpa_s->cross_connect_disallowed ?
2290 "disallows" : "allows");
2291 }
2292 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002293
2294 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002295#endif /* CONFIG_P2P */
2296
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002297#ifdef CONFIG_MBO
2298 if (bss) {
2299 mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2300 if (mbo) {
2301 int len;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002302
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002303 len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
2304 wpa_ie + wpa_ie_len,
2305 sizeof(wpa_ie) -
2306 wpa_ie_len);
2307 if (len > 0)
2308 wpa_ie_len += len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002309 }
2310 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002311#endif /* CONFIG_MBO */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002312
Dmitry Shmidt56052862013-10-04 10:23:25 -07002313 /*
2314 * Workaround: Add Extended Capabilities element only if the AP
2315 * included this element in Beacon/Probe Response frames. Some older
2316 * APs seem to have interoperability issues if this element is
2317 * included, so while the standard may require us to include the
2318 * element in all cases, it is justifiable to skip it to avoid
2319 * interoperability issues.
2320 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002321 if (ssid->p2p_group)
2322 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2323 else
2324 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2325
Dmitry Shmidt56052862013-10-04 10:23:25 -07002326 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002327 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002328 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002329 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2330 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002331 if (ext_capab_len > 0) {
2332 u8 *pos = wpa_ie;
2333 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2334 pos += 2 + pos[1];
2335 os_memmove(pos + ext_capab_len, pos,
2336 wpa_ie_len - (pos - wpa_ie));
2337 wpa_ie_len += ext_capab_len;
2338 os_memcpy(pos, ext_capab, ext_capab_len);
2339 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002340 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002341
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002342#ifdef CONFIG_HS20
2343 if (is_hs20_network(wpa_s, ssid, bss)) {
2344 struct wpabuf *hs20;
2345
2346 hs20 = wpabuf_alloc(20);
2347 if (hs20) {
2348 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2349 size_t len;
2350
2351 wpas_hs20_add_indication(hs20, pps_mo_id);
2352 len = sizeof(wpa_ie) - wpa_ie_len;
2353 if (wpabuf_len(hs20) <= len) {
2354 os_memcpy(wpa_ie + wpa_ie_len,
2355 wpabuf_head(hs20), wpabuf_len(hs20));
2356 wpa_ie_len += wpabuf_len(hs20);
2357 }
2358 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002359
2360 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002361 }
2362 }
2363#endif /* CONFIG_HS20 */
2364
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002365 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2366 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2367 size_t len;
2368
2369 len = sizeof(wpa_ie) - wpa_ie_len;
2370 if (wpabuf_len(buf) <= len) {
2371 os_memcpy(wpa_ie + wpa_ie_len,
2372 wpabuf_head(buf), wpabuf_len(buf));
2373 wpa_ie_len += wpabuf_len(buf);
2374 }
2375 }
2376
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002377#ifdef CONFIG_FST
2378 if (wpa_s->fst_ies) {
2379 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2380
2381 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2382 os_memcpy(wpa_ie + wpa_ie_len,
2383 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2384 wpa_ie_len += fst_ies_len;
2385 }
2386 }
2387#endif /* CONFIG_FST */
2388
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002389#ifdef CONFIG_MBO
2390 if (mbo) {
2391 int len;
2392
2393 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2394 sizeof(wpa_ie) - wpa_ie_len);
2395 if (len >= 0)
2396 wpa_ie_len += len;
2397 }
2398#endif /* CONFIG_MBO */
2399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2401 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002402 cipher_pairwise = wpa_s->pairwise_cipher;
2403 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2405 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2406 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2407 use_crypt = 0;
2408 if (wpa_set_wep_keys(wpa_s, ssid)) {
2409 use_crypt = 1;
2410 wep_keys_set = 1;
2411 }
2412 }
2413 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2414 use_crypt = 0;
2415
2416#ifdef IEEE8021X_EAPOL
2417 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2418 if ((ssid->eapol_flags &
2419 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2420 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2421 !wep_keys_set) {
2422 use_crypt = 0;
2423 } else {
2424 /* Assume that dynamic WEP-104 keys will be used and
2425 * set cipher suites in order for drivers to expect
2426 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002427 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 }
2429 }
2430#endif /* IEEE8021X_EAPOL */
2431
2432 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2433 /* Set the key before (and later after) association */
2434 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2435 }
2436
2437 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2438 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 params.ssid = bss->ssid;
2440 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002441 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2442 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2443 MACSTR " freq=%u MHz based on scan results "
2444 "(bssid_set=%d)",
2445 MAC2STR(bss->bssid), bss->freq,
2446 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002447 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002448 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002449 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002450 params.bssid_hint = bss->bssid;
2451 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002452 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 } else {
2454 params.ssid = ssid->ssid;
2455 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002456 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002458
2459 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2460 wpa_s->conf->ap_scan == 2) {
2461 params.bssid = ssid->bssid;
2462 params.fixed_bssid = 1;
2463 }
2464
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002465 /* Initial frequency for IBSS/mesh */
2466 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002467 ssid->frequency > 0 && params.freq.freq == 0)
2468 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002469
2470 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002471 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002472 if (ssid->beacon_int)
2473 params.beacon_int = ssid->beacon_int;
2474 else
2475 params.beacon_int = wpa_s->conf->beacon_int;
2476 }
2477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 params.wpa_ie = wpa_ie;
2479 params.wpa_ie_len = wpa_ie_len;
2480 params.pairwise_suite = cipher_pairwise;
2481 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002482 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002483 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 params.auth_alg = algs;
2485 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002486 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 for (i = 0; i < NUM_WEP_KEYS; i++) {
2488 if (ssid->wep_key_len[i])
2489 params.wep_key[i] = ssid->wep_key[i];
2490 params.wep_key_len[i] = ssid->wep_key_len[i];
2491 }
2492 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2493
2494 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002495 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2496 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 params.passphrase = ssid->passphrase;
2498 if (ssid->psk_set)
2499 params.psk = ssid->psk;
2500 }
2501
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002502 if (wpa_s->conf->key_mgmt_offload) {
2503 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2504 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002505 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2506 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002507 params.req_key_mgmt_offload =
2508 ssid->proactive_key_caching < 0 ?
2509 wpa_s->conf->okc : ssid->proactive_key_caching;
2510 else
2511 params.req_key_mgmt_offload = 1;
2512
2513 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2514 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2515 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2516 ssid->psk_set)
2517 params.psk = ssid->psk;
2518 }
2519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 params.drop_unencrypted = use_crypt;
2521
2522#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002523 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002524 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2526 struct wpa_ie_data ie;
2527 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2528 ie.capabilities &
2529 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2530 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2531 "MFP: require MFP");
2532 params.mgmt_frame_protection =
2533 MGMT_FRAME_PROTECTION_REQUIRED;
2534 }
2535 }
2536#endif /* CONFIG_IEEE80211W */
2537
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002538 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002540 if (wpa_s->p2pdev->set_sta_uapsd)
2541 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 else
2543 params.uapsd = -1;
2544
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002545#ifdef CONFIG_HT_OVERRIDES
2546 os_memset(&htcaps, 0, sizeof(htcaps));
2547 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2548 params.htcaps = (u8 *) &htcaps;
2549 params.htcaps_mask = (u8 *) &htcaps_mask;
2550 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2551#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002552#ifdef CONFIG_VHT_OVERRIDES
2553 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2554 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2555 params.vhtcaps = &vhtcaps;
2556 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002557 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002558#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002559
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002560#ifdef CONFIG_P2P
2561 /*
2562 * If multi-channel concurrency is not supported, check for any
2563 * frequency conflict. In case of any frequency conflict, remove the
2564 * least prioritized connection.
2565 */
2566 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002567 int freq, num;
2568 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002569 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002570 wpa_printf(MSG_DEBUG,
2571 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002572 freq, params.freq.freq);
2573 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002574 wpa_s, params.freq.freq, ssid) < 0) {
2575 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002576 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002577 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002578 }
2579 }
2580#endif /* CONFIG_P2P */
2581
Dmitry Shmidte4663042016-04-04 10:07:49 -07002582 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2583 wpa_s->current_ssid)
2584 params.prev_bssid = prev_bssid;
2585
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002586 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 if (ret < 0) {
2588 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2589 "failed");
2590 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2591 /*
2592 * The driver is known to mean what is saying, so we
2593 * can stop right here; the association will not
2594 * succeed.
2595 */
2596 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002597 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2599 return;
2600 }
2601 /* try to continue anyway; new association will be tried again
2602 * after timeout */
2603 assoc_failed = 1;
2604 }
2605
2606 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2607 /* Set the key after the association just in case association
2608 * cleared the previously configured key. */
2609 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2610 /* No need to timeout authentication since there is no key
2611 * management. */
2612 wpa_supplicant_cancel_auth_timeout(wpa_s);
2613 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2614#ifdef CONFIG_IBSS_RSN
2615 } else if (ssid->mode == WPAS_MODE_IBSS &&
2616 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2617 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2618 /*
2619 * RSN IBSS authentication is per-STA and we can disable the
2620 * per-BSSID authentication.
2621 */
2622 wpa_supplicant_cancel_auth_timeout(wpa_s);
2623#endif /* CONFIG_IBSS_RSN */
2624 } else {
2625 /* Timeout for IEEE 802.11 authentication and association */
2626 int timeout = 60;
2627
2628 if (assoc_failed) {
2629 /* give IBSS a bit more time */
2630 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2631 } else if (wpa_s->conf->ap_scan == 1) {
2632 /* give IBSS a bit more time */
2633 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2634 }
2635 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2636 }
2637
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002638 if (wep_keys_set &&
2639 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 /* Set static WEP keys again */
2641 wpa_set_wep_keys(wpa_s, ssid);
2642 }
2643
2644 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2645 /*
2646 * Do not allow EAP session resumption between different
2647 * network configurations.
2648 */
2649 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2650 }
2651 old_ssid = wpa_s->current_ssid;
2652 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002653
2654 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002655 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002656#ifdef CONFIG_HS20
2657 hs20_configure_frame_filters(wpa_s);
2658#endif /* CONFIG_HS20 */
2659 }
2660
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2662 wpa_supplicant_initiate_eapol(wpa_s);
2663 if (old_ssid != wpa_s->current_ssid)
2664 wpas_notify_network_changed(wpa_s);
2665}
2666
2667
2668static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2669 const u8 *addr)
2670{
2671 struct wpa_ssid *old_ssid;
2672
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002673 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 wpa_sm_set_config(wpa_s->wpa, NULL);
2678 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2679 if (old_ssid != wpa_s->current_ssid)
2680 wpas_notify_network_changed(wpa_s);
2681 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2682}
2683
2684
2685/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2687 * @wpa_s: Pointer to wpa_supplicant data
2688 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2689 *
2690 * This function is used to request %wpa_supplicant to deauthenticate from the
2691 * current AP.
2692 */
2693void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2694 int reason_code)
2695{
2696 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002697 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002698 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002700 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2701 " pending_bssid=" MACSTR " reason=%d state=%s",
2702 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2703 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2704
2705 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002707 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2708 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2709 wpa_s->wpa_state == WPA_ASSOCIATING))
2710 addr = wpa_s->pending_bssid;
2711 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2712 /*
2713 * When using driver-based BSS selection, we may not know the
2714 * BSSID with which we are currently trying to associate. We
2715 * need to notify the driver of this disconnection even in such
2716 * a case, so use the all zeros address here.
2717 */
2718 addr = wpa_s->bssid;
2719 zero_addr = 1;
2720 }
2721
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002722#ifdef CONFIG_TDLS
2723 wpa_tdls_teardown_peers(wpa_s->wpa);
2724#endif /* CONFIG_TDLS */
2725
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002726#ifdef CONFIG_MESH
2727 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002728 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2729 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002730 wpa_supplicant_leave_mesh(wpa_s);
2731 }
2732#endif /* CONFIG_MESH */
2733
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002734 if (addr) {
2735 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002736 os_memset(&event, 0, sizeof(event));
2737 event.deauth_info.reason_code = (u16) reason_code;
2738 event.deauth_info.locally_generated = 1;
2739 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002740 if (zero_addr)
2741 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 }
2743
2744 wpa_supplicant_clear_connection(wpa_s, addr);
2745}
2746
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002747static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2748 struct wpa_ssid *ssid)
2749{
2750 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2751 return;
2752
2753 ssid->disabled = 0;
2754 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2755 wpas_notify_network_enabled_changed(wpa_s, ssid);
2756
2757 /*
2758 * Try to reassociate since there is no current configuration and a new
2759 * network was made available.
2760 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002761 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002762 wpa_s->reassociate = 1;
2763}
2764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765
2766/**
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002767 * wpa_supplicant_add_network - Add a new network
2768 * @wpa_s: wpa_supplicant structure for a network interface
2769 * Returns: The new network configuration or %NULL if operation failed
2770 *
2771 * This function performs the following operations:
2772 * 1. Adds a new network.
2773 * 2. Send network addition notification.
2774 * 3. Marks the network disabled.
2775 * 4. Set network default parameters.
2776 */
2777struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2778{
2779 struct wpa_ssid *ssid;
2780
2781 ssid = wpa_config_add_network(wpa_s->conf);
2782 if (!ssid)
2783 return NULL;
2784 wpas_notify_network_added(wpa_s, ssid);
2785 ssid->disabled = 1;
2786 wpa_config_set_network_defaults(ssid);
2787
2788 return ssid;
2789}
2790
2791
2792/**
2793 * wpa_supplicant_remove_network - Remove a configured network based on id
2794 * @wpa_s: wpa_supplicant structure for a network interface
2795 * @id: Unique network id to search for
2796 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2797 * could not be removed
2798 *
2799 * This function performs the following operations:
2800 * 1. Removes the network.
2801 * 2. Send network removal notification.
2802 * 3. Update internal state machines.
2803 * 4. Stop any running sched scans.
2804 */
2805int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2806{
2807 struct wpa_ssid *ssid;
2808 int was_disabled;
2809
2810 ssid = wpa_config_get_network(wpa_s->conf, id);
2811 if (!ssid)
2812 return -1;
2813 wpas_notify_network_removed(wpa_s, ssid);
2814
2815 if (wpa_s->last_ssid == ssid)
2816 wpa_s->last_ssid = NULL;
2817
2818 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
2819#ifdef CONFIG_SME
2820 wpa_s->sme.prev_bssid_set = 0;
2821#endif /* CONFIG_SME */
2822 /*
2823 * Invalidate the EAP session cache if the current or
2824 * previously used network is removed.
2825 */
2826 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2827 }
2828
2829 if (ssid == wpa_s->current_ssid) {
2830 wpa_sm_set_config(wpa_s->wpa, NULL);
2831 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2832
2833 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2834 wpa_s->own_disconnect_req = 1;
2835 wpa_supplicant_deauthenticate(wpa_s,
2836 WLAN_REASON_DEAUTH_LEAVING);
2837 }
2838
2839 was_disabled = ssid->disabled;
2840
2841 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
2842 return -2;
2843
2844 if (!was_disabled && wpa_s->sched_scanning) {
2845 wpa_printf(MSG_DEBUG,
2846 "Stop ongoing sched_scan to remove network from filters");
2847 wpa_supplicant_cancel_sched_scan(wpa_s);
2848 wpa_supplicant_req_scan(wpa_s, 0, 0);
2849 }
2850
2851 return 0;
2852}
2853
2854
2855/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856 * wpa_supplicant_enable_network - Mark a configured network as enabled
2857 * @wpa_s: wpa_supplicant structure for a network interface
2858 * @ssid: wpa_ssid structure for a configured network or %NULL
2859 *
2860 * Enables the specified network or all networks if no network specified.
2861 */
2862void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2863 struct wpa_ssid *ssid)
2864{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002866 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2867 wpa_supplicant_enable_one_network(wpa_s, ssid);
2868 } else
2869 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002871 if (wpa_s->reassociate && !wpa_s->disconnected &&
2872 (!wpa_s->current_ssid ||
2873 wpa_s->wpa_state == WPA_DISCONNECTED ||
2874 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002875 if (wpa_s->sched_scanning) {
2876 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2877 "new network to scan filters");
2878 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002879 }
2880
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002881 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2882 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002883 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 }
2886}
2887
2888
2889/**
2890 * wpa_supplicant_disable_network - Mark a configured network as disabled
2891 * @wpa_s: wpa_supplicant structure for a network interface
2892 * @ssid: wpa_ssid structure for a configured network or %NULL
2893 *
2894 * Disables the specified network or all networks if no network specified.
2895 */
2896void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2897 struct wpa_ssid *ssid)
2898{
2899 struct wpa_ssid *other_ssid;
2900 int was_disabled;
2901
2902 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002903 if (wpa_s->sched_scanning)
2904 wpa_supplicant_cancel_sched_scan(wpa_s);
2905
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2907 other_ssid = other_ssid->next) {
2908 was_disabled = other_ssid->disabled;
2909 if (was_disabled == 2)
2910 continue; /* do not change persistent P2P group
2911 * data */
2912
2913 other_ssid->disabled = 1;
2914
2915 if (was_disabled != other_ssid->disabled)
2916 wpas_notify_network_enabled_changed(
2917 wpa_s, other_ssid);
2918 }
2919 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002920 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2922 } else if (ssid->disabled != 2) {
2923 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002924 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2926
2927 was_disabled = ssid->disabled;
2928
2929 ssid->disabled = 1;
2930
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002931 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002932 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002933 if (wpa_s->sched_scanning) {
2934 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2935 "to remove network from filters");
2936 wpa_supplicant_cancel_sched_scan(wpa_s);
2937 wpa_supplicant_req_scan(wpa_s, 0, 0);
2938 }
2939 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 }
2941}
2942
2943
2944/**
2945 * wpa_supplicant_select_network - Attempt association with a network
2946 * @wpa_s: wpa_supplicant structure for a network interface
2947 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2948 */
2949void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2950 struct wpa_ssid *ssid)
2951{
2952
2953 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002954 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002956 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002957 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2958 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002959 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002961 disconnected = 1;
2962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002964 if (ssid)
2965 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002967 /*
2968 * Mark all other networks disabled or mark all networks enabled if no
2969 * network specified.
2970 */
2971 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2972 other_ssid = other_ssid->next) {
2973 int was_disabled = other_ssid->disabled;
2974 if (was_disabled == 2)
2975 continue; /* do not change persistent P2P group data */
2976
2977 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002978 if (was_disabled && !other_ssid->disabled)
2979 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980
2981 if (was_disabled != other_ssid->disabled)
2982 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2983 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002984
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002985 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
2986 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002987 /* We are already associated with the selected network */
2988 wpa_printf(MSG_DEBUG, "Already associated with the "
2989 "selected network - do nothing");
2990 return;
2991 }
2992
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002993 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002994 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002995 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002996 wpa_s->connect_without_scan =
2997 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002998
2999 /*
3000 * Don't optimize next scan freqs since a new ESS has been
3001 * selected.
3002 */
3003 os_free(wpa_s->next_scan_freqs);
3004 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003005 } else {
3006 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003007 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003009 wpa_s->disconnected = 0;
3010 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003011
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003012 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003013 wpa_supplicant_fast_associate(wpa_s) != 1) {
3014 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003015 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003016 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003017
3018 if (ssid)
3019 wpas_notify_network_selected(wpa_s, ssid);
3020}
3021
3022
3023/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003024 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3025 * @wpa_s: wpa_supplicant structure for a network interface
3026 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3027 * @pkcs11_module_path: PKCS #11 module path or NULL
3028 * Returns: 0 on success; -1 on failure
3029 *
3030 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3031 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3032 * module path fails the paths will be reset to the default value (NULL).
3033 */
3034int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3035 const char *pkcs11_engine_path,
3036 const char *pkcs11_module_path)
3037{
3038 char *pkcs11_engine_path_copy = NULL;
3039 char *pkcs11_module_path_copy = NULL;
3040
3041 if (pkcs11_engine_path != NULL) {
3042 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3043 if (pkcs11_engine_path_copy == NULL)
3044 return -1;
3045 }
3046 if (pkcs11_module_path != NULL) {
3047 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003048 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003049 os_free(pkcs11_engine_path_copy);
3050 return -1;
3051 }
3052 }
3053
3054 os_free(wpa_s->conf->pkcs11_engine_path);
3055 os_free(wpa_s->conf->pkcs11_module_path);
3056 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3057 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3058
3059 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3060 eapol_sm_deinit(wpa_s->eapol);
3061 wpa_s->eapol = NULL;
3062 if (wpa_supplicant_init_eapol(wpa_s)) {
3063 /* Error -> Reset paths to the default value (NULL) once. */
3064 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3065 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3066 NULL);
3067
3068 return -1;
3069 }
3070 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3071
3072 return 0;
3073}
3074
3075
3076/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003077 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3078 * @wpa_s: wpa_supplicant structure for a network interface
3079 * @ap_scan: AP scan mode
3080 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3081 *
3082 */
3083int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3084{
3085
3086 int old_ap_scan;
3087
3088 if (ap_scan < 0 || ap_scan > 2)
3089 return -1;
3090
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003091 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3092 wpa_printf(MSG_INFO,
3093 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3094 }
3095
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003096#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003097 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3098 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3099 wpa_s->wpa_state < WPA_COMPLETED) {
3100 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3101 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003102 return 0;
3103 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003104#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003106 old_ap_scan = wpa_s->conf->ap_scan;
3107 wpa_s->conf->ap_scan = ap_scan;
3108
3109 if (old_ap_scan != wpa_s->conf->ap_scan)
3110 wpas_notify_ap_scan_changed(wpa_s);
3111
3112 return 0;
3113}
3114
3115
3116/**
3117 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3118 * @wpa_s: wpa_supplicant structure for a network interface
3119 * @expire_age: Expiration age in seconds
3120 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3121 *
3122 */
3123int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3124 unsigned int bss_expire_age)
3125{
3126 if (bss_expire_age < 10) {
3127 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3128 bss_expire_age);
3129 return -1;
3130 }
3131 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3132 bss_expire_age);
3133 wpa_s->conf->bss_expiration_age = bss_expire_age;
3134
3135 return 0;
3136}
3137
3138
3139/**
3140 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3141 * @wpa_s: wpa_supplicant structure for a network interface
3142 * @expire_count: number of scans after which an unseen BSS is reclaimed
3143 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3144 *
3145 */
3146int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3147 unsigned int bss_expire_count)
3148{
3149 if (bss_expire_count < 1) {
3150 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3151 bss_expire_count);
3152 return -1;
3153 }
3154 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3155 bss_expire_count);
3156 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3157
3158 return 0;
3159}
3160
3161
3162/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003163 * wpa_supplicant_set_scan_interval - Set scan interval
3164 * @wpa_s: wpa_supplicant structure for a network interface
3165 * @scan_interval: scan interval in seconds
3166 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3167 *
3168 */
3169int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3170 int scan_interval)
3171{
3172 if (scan_interval < 0) {
3173 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3174 scan_interval);
3175 return -1;
3176 }
3177 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3178 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003179 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003180
3181 return 0;
3182}
3183
3184
3185/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003186 * wpa_supplicant_set_debug_params - Set global debug params
3187 * @global: wpa_global structure
3188 * @debug_level: debug level
3189 * @debug_timestamp: determines if show timestamp in debug data
3190 * @debug_show_keys: determines if show keys in debug data
3191 * Returns: 0 if succeed or -1 if debug_level has wrong value
3192 */
3193int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3194 int debug_timestamp, int debug_show_keys)
3195{
3196
3197 int old_level, old_timestamp, old_show_keys;
3198
3199 /* check for allowed debuglevels */
3200 if (debug_level != MSG_EXCESSIVE &&
3201 debug_level != MSG_MSGDUMP &&
3202 debug_level != MSG_DEBUG &&
3203 debug_level != MSG_INFO &&
3204 debug_level != MSG_WARNING &&
3205 debug_level != MSG_ERROR)
3206 return -1;
3207
3208 old_level = wpa_debug_level;
3209 old_timestamp = wpa_debug_timestamp;
3210 old_show_keys = wpa_debug_show_keys;
3211
3212 wpa_debug_level = debug_level;
3213 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3214 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3215
3216 if (wpa_debug_level != old_level)
3217 wpas_notify_debug_level_changed(global);
3218 if (wpa_debug_timestamp != old_timestamp)
3219 wpas_notify_debug_timestamp_changed(global);
3220 if (wpa_debug_show_keys != old_show_keys)
3221 wpas_notify_debug_show_keys_changed(global);
3222
3223 return 0;
3224}
3225
3226
3227/**
3228 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3229 * @wpa_s: Pointer to wpa_supplicant data
3230 * Returns: A pointer to the current network structure or %NULL on failure
3231 */
3232struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3233{
3234 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003235 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236 int res;
3237 size_t ssid_len;
3238 u8 bssid[ETH_ALEN];
3239 int wired;
3240
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003241 res = wpa_drv_get_ssid(wpa_s, ssid);
3242 if (res < 0) {
3243 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3244 "driver");
3245 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003247 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003248
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003249 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003250 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3251 "driver");
3252 return NULL;
3253 }
3254
3255 wired = wpa_s->conf->ap_scan == 0 &&
3256 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3257
3258 entry = wpa_s->conf->ssid;
3259 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003260 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261 ((ssid_len == entry->ssid_len &&
3262 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3263 (!entry->bssid_set ||
3264 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3265 return entry;
3266#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003267 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3269 (entry->ssid == NULL || entry->ssid_len == 0) &&
3270 (!entry->bssid_set ||
3271 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3272 return entry;
3273#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003274
Dmitry Shmidt04949592012-07-19 12:16:46 -07003275 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003276 entry->ssid_len == 0 &&
3277 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3278 return entry;
3279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003280 entry = entry->next;
3281 }
3282
3283 return NULL;
3284}
3285
3286
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003287static int select_driver(struct wpa_supplicant *wpa_s, int i)
3288{
3289 struct wpa_global *global = wpa_s->global;
3290
3291 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003292 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003293 if (global->drv_priv[i] == NULL) {
3294 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3295 "'%s'", wpa_drivers[i]->name);
3296 return -1;
3297 }
3298 }
3299
3300 wpa_s->driver = wpa_drivers[i];
3301 wpa_s->global_drv_priv = global->drv_priv[i];
3302
3303 return 0;
3304}
3305
3306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3308 const char *name)
3309{
3310 int i;
3311 size_t len;
3312 const char *pos, *driver = name;
3313
3314 if (wpa_s == NULL)
3315 return -1;
3316
3317 if (wpa_drivers[0] == NULL) {
3318 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3319 "wpa_supplicant");
3320 return -1;
3321 }
3322
3323 if (name == NULL) {
3324 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003325 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326 }
3327
3328 do {
3329 pos = os_strchr(driver, ',');
3330 if (pos)
3331 len = pos - driver;
3332 else
3333 len = os_strlen(driver);
3334
3335 for (i = 0; wpa_drivers[i]; i++) {
3336 if (os_strlen(wpa_drivers[i]->name) == len &&
3337 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003338 0) {
3339 /* First driver that succeeds wins */
3340 if (select_driver(wpa_s, i) == 0)
3341 return 0;
3342 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343 }
3344
3345 driver = pos + 1;
3346 } while (pos);
3347
3348 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3349 return -1;
3350}
3351
3352
3353/**
3354 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3355 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3356 * with struct wpa_driver_ops::init()
3357 * @src_addr: Source address of the EAPOL frame
3358 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3359 * @len: Length of the EAPOL data
3360 *
3361 * This function is called for each received EAPOL frame. Most driver
3362 * interfaces rely on more generic OS mechanism for receiving frames through
3363 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3364 * take care of received EAPOL frames and deliver them to the core supplicant
3365 * code by calling this function.
3366 */
3367void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3368 const u8 *buf, size_t len)
3369{
3370 struct wpa_supplicant *wpa_s = ctx;
3371
3372 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3373 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3374
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003375#ifdef CONFIG_PEERKEY
3376 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3377 wpa_s->current_ssid->peerkey &&
3378 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3379 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3380 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3381 return;
3382 }
3383#endif /* CONFIG_PEERKEY */
3384
Jouni Malinena05074c2012-12-21 21:35:35 +02003385 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3386 (wpa_s->last_eapol_matches_bssid &&
3387#ifdef CONFIG_AP
3388 !wpa_s->ap_iface &&
3389#endif /* CONFIG_AP */
3390 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391 /*
3392 * There is possible race condition between receiving the
3393 * association event and the EAPOL frame since they are coming
3394 * through different paths from the driver. In order to avoid
3395 * issues in trying to process the EAPOL frame before receiving
3396 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003397 * the association event is received. This may also be needed in
3398 * driver-based roaming case, so also use src_addr != BSSID as a
3399 * trigger if we have previously confirmed that the
3400 * Authenticator uses BSSID as the src_addr (which is not the
3401 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003402 */
3403 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003404 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3405 wpa_supplicant_state_txt(wpa_s->wpa_state),
3406 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407 wpabuf_free(wpa_s->pending_eapol_rx);
3408 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3409 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003410 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003411 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3412 ETH_ALEN);
3413 }
3414 return;
3415 }
3416
Jouni Malinena05074c2012-12-21 21:35:35 +02003417 wpa_s->last_eapol_matches_bssid =
3418 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420#ifdef CONFIG_AP
3421 if (wpa_s->ap_iface) {
3422 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3423 return;
3424 }
3425#endif /* CONFIG_AP */
3426
3427 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3428 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3429 "no key management is configured");
3430 return;
3431 }
3432
3433 if (wpa_s->eapol_received == 0 &&
3434 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3435 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3436 wpa_s->wpa_state != WPA_COMPLETED) &&
3437 (wpa_s->current_ssid == NULL ||
3438 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3439 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003440 int timeout = 10;
3441
3442 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3443 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3444 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3445 /* Use longer timeout for IEEE 802.1X/EAP */
3446 timeout = 70;
3447 }
3448
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003449#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003450 if (wpa_s->current_ssid && wpa_s->current_bss &&
3451 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3452 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3453 /*
3454 * Use shorter timeout if going through WPS AP iteration
3455 * for PIN config method with an AP that does not
3456 * advertise Selected Registrar.
3457 */
3458 struct wpabuf *wps_ie;
3459
3460 wps_ie = wpa_bss_get_vendor_ie_multi(
3461 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3462 if (wps_ie &&
3463 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3464 timeout = 10;
3465 wpabuf_free(wps_ie);
3466 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003467#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003468
3469 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470 }
3471 wpa_s->eapol_received++;
3472
3473 if (wpa_s->countermeasures) {
3474 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3475 "EAPOL packet");
3476 return;
3477 }
3478
3479#ifdef CONFIG_IBSS_RSN
3480 if (wpa_s->current_ssid &&
3481 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3482 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3483 return;
3484 }
3485#endif /* CONFIG_IBSS_RSN */
3486
3487 /* Source address of the incoming EAPOL frame could be compared to the
3488 * current BSSID. However, it is possible that a centralized
3489 * Authenticator could be using another MAC address than the BSSID of
3490 * an AP, so just allow any address to be used for now. The replies are
3491 * still sent to the current BSSID (if available), though. */
3492
3493 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3494 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3495 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3496 return;
3497 wpa_drv_poll(wpa_s);
3498 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3499 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3500 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3501 /*
3502 * Set portValid = TRUE here since we are going to skip 4-way
3503 * handshake processing which would normally set portValid. We
3504 * need this to allow the EAPOL state machines to be completed
3505 * without going through EAPOL-Key handshake.
3506 */
3507 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3508 }
3509}
3510
3511
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003512int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003514 if ((!wpa_s->p2p_mgmt ||
3515 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3516 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003517 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3519 wpa_drv_get_mac_addr(wpa_s),
3520 ETH_P_EAPOL,
3521 wpa_supplicant_rx_eapol, wpa_s, 0);
3522 if (wpa_s->l2 == NULL)
3523 return -1;
3524 } else {
3525 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3526 if (addr)
3527 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3528 }
3529
3530 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3531 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3532 return -1;
3533 }
3534
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003535 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003537 return 0;
3538}
3539
3540
Dmitry Shmidt04949592012-07-19 12:16:46 -07003541static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3542 const u8 *buf, size_t len)
3543{
3544 struct wpa_supplicant *wpa_s = ctx;
3545 const struct l2_ethhdr *eth;
3546
3547 if (len < sizeof(*eth))
3548 return;
3549 eth = (const struct l2_ethhdr *) buf;
3550
3551 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3552 !(eth->h_dest[0] & 0x01)) {
3553 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3554 " (bridge - not for this interface - ignore)",
3555 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3556 return;
3557 }
3558
3559 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3560 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3561 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3562 len - sizeof(*eth));
3563}
3564
3565
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003566/**
3567 * wpa_supplicant_driver_init - Initialize driver interface parameters
3568 * @wpa_s: Pointer to wpa_supplicant data
3569 * Returns: 0 on success, -1 on failure
3570 *
3571 * This function is called to initialize driver interface parameters.
3572 * wpa_drv_init() must have been called before this function to initialize the
3573 * driver interface.
3574 */
3575int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3576{
3577 static int interface_count = 0;
3578
3579 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3580 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003581
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003582 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3583 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003584 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003585 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 if (wpa_s->bridge_ifname[0]) {
3588 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3589 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003590 wpa_s->l2_br = l2_packet_init_bridge(
3591 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3592 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003593 if (wpa_s->l2_br == NULL) {
3594 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3595 "connection for the bridge interface '%s'",
3596 wpa_s->bridge_ifname);
3597 return -1;
3598 }
3599 }
3600
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003601 if (wpa_s->conf->ap_scan == 2 &&
3602 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3603 wpa_printf(MSG_INFO,
3604 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3605 }
3606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 wpa_clear_keys(wpa_s, NULL);
3608
3609 /* Make sure that TKIP countermeasures are not left enabled (could
3610 * happen if wpa_supplicant is killed during countermeasures. */
3611 wpa_drv_set_countermeasures(wpa_s, 0);
3612
3613 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3614 wpa_drv_flush_pmkid(wpa_s);
3615
3616 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003617 wpa_s->prev_scan_wildcard = 0;
3618
Dmitry Shmidt04949592012-07-19 12:16:46 -07003619 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003620 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3621 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3622 interface_count = 0;
3623 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003624#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003625 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003626 wpa_supplicant_delayed_sched_scan(wpa_s,
3627 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003628 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003629 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003630 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003631#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632 interface_count++;
3633 } else
3634 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3635
3636 return 0;
3637}
3638
3639
3640static int wpa_supplicant_daemon(const char *pid_file)
3641{
3642 wpa_printf(MSG_DEBUG, "Daemonize..");
3643 return os_daemonize(pid_file);
3644}
3645
3646
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003647static struct wpa_supplicant *
3648wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649{
3650 struct wpa_supplicant *wpa_s;
3651
3652 wpa_s = os_zalloc(sizeof(*wpa_s));
3653 if (wpa_s == NULL)
3654 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003655 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 wpa_s->scan_interval = 5;
3657 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003658 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003659 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003660 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003661
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003662 dl_list_init(&wpa_s->bss_tmp_disallowed);
3663
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664 return wpa_s;
3665}
3666
3667
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003668#ifdef CONFIG_HT_OVERRIDES
3669
3670static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3671 struct ieee80211_ht_capabilities *htcaps,
3672 struct ieee80211_ht_capabilities *htcaps_mask,
3673 const char *ht_mcs)
3674{
3675 /* parse ht_mcs into hex array */
3676 int i;
3677 const char *tmp = ht_mcs;
3678 char *end = NULL;
3679
3680 /* If ht_mcs is null, do not set anything */
3681 if (!ht_mcs)
3682 return 0;
3683
3684 /* This is what we are setting in the kernel */
3685 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3686
3687 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3688
3689 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3690 errno = 0;
3691 long v = strtol(tmp, &end, 16);
3692 if (errno == 0) {
3693 wpa_msg(wpa_s, MSG_DEBUG,
3694 "htcap value[%i]: %ld end: %p tmp: %p",
3695 i, v, end, tmp);
3696 if (end == tmp)
3697 break;
3698
3699 htcaps->supported_mcs_set[i] = v;
3700 tmp = end;
3701 } else {
3702 wpa_msg(wpa_s, MSG_ERROR,
3703 "Failed to parse ht-mcs: %s, error: %s\n",
3704 ht_mcs, strerror(errno));
3705 return -1;
3706 }
3707 }
3708
3709 /*
3710 * If we were able to parse any values, then set mask for the MCS set.
3711 */
3712 if (i) {
3713 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3714 IEEE80211_HT_MCS_MASK_LEN - 1);
3715 /* skip the 3 reserved bits */
3716 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3717 0x1f;
3718 }
3719
3720 return 0;
3721}
3722
3723
3724static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3725 struct ieee80211_ht_capabilities *htcaps,
3726 struct ieee80211_ht_capabilities *htcaps_mask,
3727 int disabled)
3728{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003729 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003730
3731 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3732
3733 if (disabled == -1)
3734 return 0;
3735
3736 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3737 htcaps_mask->ht_capabilities_info |= msk;
3738 if (disabled)
3739 htcaps->ht_capabilities_info &= msk;
3740 else
3741 htcaps->ht_capabilities_info |= msk;
3742
3743 return 0;
3744}
3745
3746
3747static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3748 struct ieee80211_ht_capabilities *htcaps,
3749 struct ieee80211_ht_capabilities *htcaps_mask,
3750 int factor)
3751{
3752 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3753
3754 if (factor == -1)
3755 return 0;
3756
3757 if (factor < 0 || factor > 3) {
3758 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3759 "Must be 0-3 or -1", factor);
3760 return -EINVAL;
3761 }
3762
3763 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3764 htcaps->a_mpdu_params &= ~0x3;
3765 htcaps->a_mpdu_params |= factor & 0x3;
3766
3767 return 0;
3768}
3769
3770
3771static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3772 struct ieee80211_ht_capabilities *htcaps,
3773 struct ieee80211_ht_capabilities *htcaps_mask,
3774 int density)
3775{
3776 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3777
3778 if (density == -1)
3779 return 0;
3780
3781 if (density < 0 || density > 7) {
3782 wpa_msg(wpa_s, MSG_ERROR,
3783 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3784 density);
3785 return -EINVAL;
3786 }
3787
3788 htcaps_mask->a_mpdu_params |= 0x1C;
3789 htcaps->a_mpdu_params &= ~(0x1C);
3790 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3791
3792 return 0;
3793}
3794
3795
3796static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3797 struct ieee80211_ht_capabilities *htcaps,
3798 struct ieee80211_ht_capabilities *htcaps_mask,
3799 int disabled)
3800{
3801 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003802 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3803 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003804
3805 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3806
3807 if (disabled)
3808 htcaps->ht_capabilities_info &= ~msk;
3809 else
3810 htcaps->ht_capabilities_info |= msk;
3811
3812 htcaps_mask->ht_capabilities_info |= msk;
3813
3814 return 0;
3815}
3816
3817
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003818static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3819 struct ieee80211_ht_capabilities *htcaps,
3820 struct ieee80211_ht_capabilities *htcaps_mask,
3821 int disabled)
3822{
3823 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003824 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3825 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003826
3827 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3828
3829 if (disabled)
3830 htcaps->ht_capabilities_info &= ~msk;
3831 else
3832 htcaps->ht_capabilities_info |= msk;
3833
3834 htcaps_mask->ht_capabilities_info |= msk;
3835
3836 return 0;
3837}
3838
3839
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003840static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3841 struct ieee80211_ht_capabilities *htcaps,
3842 struct ieee80211_ht_capabilities *htcaps_mask,
3843 int disabled)
3844{
3845 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003846 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003847
3848 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3849
3850 if (disabled)
3851 htcaps->ht_capabilities_info &= ~msk;
3852 else
3853 htcaps->ht_capabilities_info |= msk;
3854
3855 htcaps_mask->ht_capabilities_info |= msk;
3856
3857 return 0;
3858}
3859
3860
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003861void wpa_supplicant_apply_ht_overrides(
3862 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3863 struct wpa_driver_associate_params *params)
3864{
3865 struct ieee80211_ht_capabilities *htcaps;
3866 struct ieee80211_ht_capabilities *htcaps_mask;
3867
3868 if (!ssid)
3869 return;
3870
3871 params->disable_ht = ssid->disable_ht;
3872 if (!params->htcaps || !params->htcaps_mask)
3873 return;
3874
3875 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3876 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3877 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3878 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3879 ssid->disable_max_amsdu);
3880 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3881 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3882 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003883 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003884 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003885
3886 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003887 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003888 htcaps->ht_capabilities_info |= bit;
3889 htcaps_mask->ht_capabilities_info |= bit;
3890 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003891}
3892
3893#endif /* CONFIG_HT_OVERRIDES */
3894
3895
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003896#ifdef CONFIG_VHT_OVERRIDES
3897void wpa_supplicant_apply_vht_overrides(
3898 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3899 struct wpa_driver_associate_params *params)
3900{
3901 struct ieee80211_vht_capabilities *vhtcaps;
3902 struct ieee80211_vht_capabilities *vhtcaps_mask;
3903
3904 if (!ssid)
3905 return;
3906
3907 params->disable_vht = ssid->disable_vht;
3908
3909 vhtcaps = (void *) params->vhtcaps;
3910 vhtcaps_mask = (void *) params->vhtcaps_mask;
3911
3912 if (!vhtcaps || !vhtcaps_mask)
3913 return;
3914
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003915 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3916 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003917
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003918#ifdef CONFIG_HT_OVERRIDES
3919 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003920 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3921 int max_ampdu;
3922
3923 max_ampdu = (ssid->vht_capa &
3924 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3925 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003926
3927 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3928 wpa_set_ampdu_factor(wpa_s,
3929 (void *) params->htcaps,
3930 (void *) params->htcaps_mask,
3931 max_ampdu);
3932 }
3933#endif /* CONFIG_HT_OVERRIDES */
3934
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003935#define OVERRIDE_MCS(i) \
3936 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3937 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003938 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003939 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003940 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3941 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003942 } \
3943 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3944 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003945 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003946 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003947 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3948 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003949 }
3950
3951 OVERRIDE_MCS(1);
3952 OVERRIDE_MCS(2);
3953 OVERRIDE_MCS(3);
3954 OVERRIDE_MCS(4);
3955 OVERRIDE_MCS(5);
3956 OVERRIDE_MCS(6);
3957 OVERRIDE_MCS(7);
3958 OVERRIDE_MCS(8);
3959}
3960#endif /* CONFIG_VHT_OVERRIDES */
3961
3962
Dmitry Shmidt04949592012-07-19 12:16:46 -07003963static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3964{
3965#ifdef PCSC_FUNCS
3966 size_t len;
3967
3968 if (!wpa_s->conf->pcsc_reader)
3969 return 0;
3970
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003971 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003972 if (!wpa_s->scard)
3973 return 1;
3974
3975 if (wpa_s->conf->pcsc_pin &&
3976 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3977 scard_deinit(wpa_s->scard);
3978 wpa_s->scard = NULL;
3979 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3980 return -1;
3981 }
3982
3983 len = sizeof(wpa_s->imsi) - 1;
3984 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3985 scard_deinit(wpa_s->scard);
3986 wpa_s->scard = NULL;
3987 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3988 return -1;
3989 }
3990 wpa_s->imsi[len] = '\0';
3991
3992 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3993
3994 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3995 wpa_s->imsi, wpa_s->mnc_len);
3996
3997 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3998 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3999#endif /* PCSC_FUNCS */
4000
4001 return 0;
4002}
4003
4004
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004005int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4006{
4007 char *val, *pos;
4008
4009 ext_password_deinit(wpa_s->ext_pw);
4010 wpa_s->ext_pw = NULL;
4011 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4012
4013 if (!wpa_s->conf->ext_password_backend)
4014 return 0;
4015
4016 val = os_strdup(wpa_s->conf->ext_password_backend);
4017 if (val == NULL)
4018 return -1;
4019 pos = os_strchr(val, ':');
4020 if (pos)
4021 *pos++ = '\0';
4022
4023 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4024
4025 wpa_s->ext_pw = ext_password_init(val, pos);
4026 os_free(val);
4027 if (wpa_s->ext_pw == NULL) {
4028 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4029 return -1;
4030 }
4031 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4032
4033 return 0;
4034}
4035
4036
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004037#ifdef CONFIG_FST
4038
4039static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4040{
4041 struct wpa_supplicant *wpa_s = ctx;
4042
4043 return (is_zero_ether_addr(wpa_s->bssid) ||
4044 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4045}
4046
4047
4048static void wpas_fst_get_channel_info_cb(void *ctx,
4049 enum hostapd_hw_mode *hw_mode,
4050 u8 *channel)
4051{
4052 struct wpa_supplicant *wpa_s = ctx;
4053
4054 if (wpa_s->current_bss) {
4055 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4056 channel);
4057 } else if (wpa_s->hw.num_modes) {
4058 *hw_mode = wpa_s->hw.modes[0].mode;
4059 } else {
4060 WPA_ASSERT(0);
4061 *hw_mode = 0;
4062 }
4063}
4064
4065
4066static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4067{
4068 struct wpa_supplicant *wpa_s = ctx;
4069
4070 *modes = wpa_s->hw.modes;
4071 return wpa_s->hw.num_modes;
4072}
4073
4074
4075static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4076{
4077 struct wpa_supplicant *wpa_s = ctx;
4078
4079 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4080 wpa_s->fst_ies = fst_ies;
4081}
4082
4083
4084static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4085{
4086 struct wpa_supplicant *wpa_s = ctx;
4087
4088 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4089 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4090 wpa_s->own_addr, wpa_s->bssid,
4091 wpabuf_head(data), wpabuf_len(data),
4092 0);
4093}
4094
4095
4096static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4097{
4098 struct wpa_supplicant *wpa_s = ctx;
4099
4100 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4101 return wpa_s->received_mb_ies;
4102}
4103
4104
4105static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4106 const u8 *buf, size_t size)
4107{
4108 struct wpa_supplicant *wpa_s = ctx;
4109 struct mb_ies_info info;
4110
4111 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4112
4113 if (!mb_ies_info_by_ies(&info, buf, size)) {
4114 wpabuf_free(wpa_s->received_mb_ies);
4115 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4116 }
4117}
4118
4119
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004120static const u8 * wpas_fst_get_peer_first(void *ctx,
4121 struct fst_get_peer_ctx **get_ctx,
4122 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004123{
4124 struct wpa_supplicant *wpa_s = ctx;
4125
4126 *get_ctx = NULL;
4127 if (!is_zero_ether_addr(wpa_s->bssid))
4128 return (wpa_s->received_mb_ies || !mb_only) ?
4129 wpa_s->bssid : NULL;
4130 return NULL;
4131}
4132
4133
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004134static const u8 * wpas_fst_get_peer_next(void *ctx,
4135 struct fst_get_peer_ctx **get_ctx,
4136 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004137{
4138 return NULL;
4139}
4140
4141void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4142 struct fst_wpa_obj *iface_obj)
4143{
4144 iface_obj->ctx = wpa_s;
4145 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4146 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4147 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4148 iface_obj->set_ies = wpas_fst_set_ies_cb;
4149 iface_obj->send_action = wpas_fst_send_action_cb;
4150 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4151 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4152 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4153 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4154}
4155#endif /* CONFIG_FST */
4156
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004157static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004158 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004159{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004160 struct wowlan_triggers *triggers;
4161 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004162
4163 if (!wpa_s->conf->wowlan_triggers)
4164 return 0;
4165
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004166 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4167 if (triggers) {
4168 ret = wpa_drv_wowlan(wpa_s, triggers);
4169 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004170 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004171 return ret;
4172}
4173
4174
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004175enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004176{
4177 if (freq < 3000)
4178 return BAND_2_4_GHZ;
4179 if (freq > 50000)
4180 return BAND_60_GHZ;
4181 return BAND_5_GHZ;
4182}
4183
4184
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004185unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004186{
4187 int i;
4188 unsigned int band = 0;
4189
4190 if (freqs) {
4191 /* freqs are specified for the radio work */
4192 for (i = 0; freqs[i]; i++)
4193 band |= wpas_freq_to_band(freqs[i]);
4194 } else {
4195 /*
4196 * freqs are not specified, implies all
4197 * the supported freqs by HW
4198 */
4199 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4200 if (wpa_s->hw.modes[i].num_channels != 0) {
4201 if (wpa_s->hw.modes[i].mode ==
4202 HOSTAPD_MODE_IEEE80211B ||
4203 wpa_s->hw.modes[i].mode ==
4204 HOSTAPD_MODE_IEEE80211G)
4205 band |= BAND_2_4_GHZ;
4206 else if (wpa_s->hw.modes[i].mode ==
4207 HOSTAPD_MODE_IEEE80211A)
4208 band |= BAND_5_GHZ;
4209 else if (wpa_s->hw.modes[i].mode ==
4210 HOSTAPD_MODE_IEEE80211AD)
4211 band |= BAND_60_GHZ;
4212 else if (wpa_s->hw.modes[i].mode ==
4213 HOSTAPD_MODE_IEEE80211ANY)
4214 band = BAND_2_4_GHZ | BAND_5_GHZ |
4215 BAND_60_GHZ;
4216 }
4217 }
4218 }
4219
4220 return band;
4221}
4222
4223
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004224static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4225 const char *rn)
4226{
4227 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4228 struct wpa_radio *radio;
4229
4230 while (rn && iface) {
4231 radio = iface->radio;
4232 if (radio && os_strcmp(rn, radio->name) == 0) {
4233 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4234 wpa_s->ifname, rn);
4235 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4236 return radio;
4237 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004238
4239 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004240 }
4241
4242 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4243 wpa_s->ifname, rn ? rn : "N/A");
4244 radio = os_zalloc(sizeof(*radio));
4245 if (radio == NULL)
4246 return NULL;
4247
4248 if (rn)
4249 os_strlcpy(radio->name, rn, sizeof(radio->name));
4250 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004251 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004252 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4253
4254 return radio;
4255}
4256
4257
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004258static void radio_work_free(struct wpa_radio_work *work)
4259{
4260 if (work->wpa_s->scan_work == work) {
4261 /* This should not really happen. */
4262 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4263 work->type, work, work->started);
4264 work->wpa_s->scan_work = NULL;
4265 }
4266
4267#ifdef CONFIG_P2P
4268 if (work->wpa_s->p2p_scan_work == work) {
4269 /* This should not really happen. */
4270 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4271 work->type, work, work->started);
4272 work->wpa_s->p2p_scan_work = NULL;
4273 }
4274#endif /* CONFIG_P2P */
4275
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004276 if (work->started) {
4277 work->wpa_s->radio->num_active_works--;
4278 wpa_dbg(work->wpa_s, MSG_DEBUG,
4279 "radio_work_free('%s'@%p: num_active_works --> %u",
4280 work->type, work,
4281 work->wpa_s->radio->num_active_works);
4282 }
4283
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004284 dl_list_del(&work->list);
4285 os_free(work);
4286}
4287
4288
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004289static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4290{
4291 struct wpa_radio_work *active_work = NULL;
4292 struct wpa_radio_work *tmp;
4293
4294 /* Get the active work to know the type and band. */
4295 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4296 if (tmp->started) {
4297 active_work = tmp;
4298 break;
4299 }
4300 }
4301
4302 if (!active_work) {
4303 /* No active work, start one */
4304 radio->num_active_works = 0;
4305 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4306 list) {
4307 if (os_strcmp(tmp->type, "scan") == 0 &&
4308 radio->external_scan_running &&
4309 (((struct wpa_driver_scan_params *)
4310 tmp->ctx)->only_new_results ||
4311 tmp->wpa_s->clear_driver_scan_cache))
4312 continue;
4313 return tmp;
4314 }
4315 return NULL;
4316 }
4317
4318 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4319 os_strcmp(active_work->type, "connect") == 0) {
4320 /*
4321 * If the active work is either connect or sme-connect,
4322 * do not parallelize them with other radio works.
4323 */
4324 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4325 "Do not parallelize radio work with %s",
4326 active_work->type);
4327 return NULL;
4328 }
4329
4330 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4331 if (tmp->started)
4332 continue;
4333
4334 /*
4335 * If connect or sme-connect are enqueued, parallelize only
4336 * those operations ahead of them in the queue.
4337 */
4338 if (os_strcmp(tmp->type, "connect") == 0 ||
4339 os_strcmp(tmp->type, "sme-connect") == 0)
4340 break;
4341
4342 /*
4343 * Check that the radio works are distinct and
4344 * on different bands.
4345 */
4346 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4347 (active_work->bands != tmp->bands)) {
4348 /*
4349 * If a scan has to be scheduled through nl80211 scan
4350 * interface and if an external scan is already running,
4351 * do not schedule the scan since it is likely to get
4352 * rejected by kernel.
4353 */
4354 if (os_strcmp(tmp->type, "scan") == 0 &&
4355 radio->external_scan_running &&
4356 (((struct wpa_driver_scan_params *)
4357 tmp->ctx)->only_new_results ||
4358 tmp->wpa_s->clear_driver_scan_cache))
4359 continue;
4360
4361 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4362 "active_work:%s new_work:%s",
4363 active_work->type, tmp->type);
4364 return tmp;
4365 }
4366 }
4367
4368 /* Did not find a radio work to schedule in parallel. */
4369 return NULL;
4370}
4371
4372
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004373static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4374{
4375 struct wpa_radio *radio = eloop_ctx;
4376 struct wpa_radio_work *work;
4377 struct os_reltime now, diff;
4378 struct wpa_supplicant *wpa_s;
4379
4380 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004381 if (work == NULL) {
4382 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004383 return;
4384 }
4385
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004386 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4387 radio_list);
4388
4389 if (!(wpa_s &&
4390 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4391 if (work->started)
4392 return; /* already started and still in progress */
4393
4394 if (wpa_s && wpa_s->radio->external_scan_running) {
4395 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4396 return;
4397 }
4398 } else {
4399 work = NULL;
4400 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4401 /* get the work to schedule next */
4402 work = radio_work_get_next_work(radio);
4403 }
4404 if (!work)
4405 return;
4406 }
4407
4408 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004409 os_get_reltime(&now);
4410 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004411 wpa_dbg(wpa_s, MSG_DEBUG,
4412 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004413 work->type, work, diff.sec, diff.usec);
4414 work->started = 1;
4415 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004416 radio->num_active_works++;
4417
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004418 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004419
4420 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4421 radio->num_active_works < MAX_ACTIVE_WORKS)
4422 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004423}
4424
4425
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004426/*
4427 * This function removes both started and pending radio works running on
4428 * the provided interface's radio.
4429 * Prior to the removal of the radio work, its callback (cb) is called with
4430 * deinit set to be 1. Each work's callback is responsible for clearing its
4431 * internal data and restoring to a correct state.
4432 * @wpa_s: wpa_supplicant data
4433 * @type: type of works to be removed
4434 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4435 * this interface's works.
4436 */
4437void radio_remove_works(struct wpa_supplicant *wpa_s,
4438 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004439{
4440 struct wpa_radio_work *work, *tmp;
4441 struct wpa_radio *radio = wpa_s->radio;
4442
4443 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4444 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004445 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004446 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004447
4448 /* skip other ifaces' works */
4449 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004450 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004451
4452 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4453 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004454 work->cb(work, 1);
4455 radio_work_free(work);
4456 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004457
4458 /* in case we removed the started work */
4459 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004460}
4461
4462
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004463static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4464{
4465 struct wpa_radio *radio = wpa_s->radio;
4466
4467 if (!radio)
4468 return;
4469
4470 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4471 wpa_s->ifname, radio->name);
4472 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004473 radio_remove_works(wpa_s, NULL, 0);
4474 wpa_s->radio = NULL;
4475 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004476 return; /* Interfaces remain for this radio */
4477
4478 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004479 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004480 os_free(radio);
4481}
4482
4483
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004484void radio_work_check_next(struct wpa_supplicant *wpa_s)
4485{
4486 struct wpa_radio *radio = wpa_s->radio;
4487
4488 if (dl_list_empty(&radio->work))
4489 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004490 if (wpa_s->ext_work_in_progress) {
4491 wpa_printf(MSG_DEBUG,
4492 "External radio work in progress - delay start of pending item");
4493 return;
4494 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004495 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4496 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4497}
4498
4499
4500/**
4501 * radio_add_work - Add a radio work item
4502 * @wpa_s: Pointer to wpa_supplicant data
4503 * @freq: Frequency of the offchannel operation in MHz or 0
4504 * @type: Unique identifier for each type of work
4505 * @next: Force as the next work to be executed
4506 * @cb: Callback function for indicating when radio is available
4507 * @ctx: Context pointer for the work (work->ctx in cb())
4508 * Returns: 0 on success, -1 on failure
4509 *
4510 * This function is used to request time for an operation that requires
4511 * exclusive radio control. Once the radio is available, the registered callback
4512 * function will be called. radio_work_done() must be called once the exclusive
4513 * radio operation has been completed, so that the radio is freed for other
4514 * operations. The special case of deinit=1 is used to free the context data
4515 * during interface removal. That does not allow the callback function to start
4516 * the radio operation, i.e., it must free any resources allocated for the radio
4517 * work and return.
4518 *
4519 * The @freq parameter can be used to indicate a single channel on which the
4520 * offchannel operation will occur. This may allow multiple radio work
4521 * operations to be performed in parallel if they apply for the same channel.
4522 * Setting this to 0 indicates that the work item may use multiple channels or
4523 * requires exclusive control of the radio.
4524 */
4525int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4526 const char *type, int next,
4527 void (*cb)(struct wpa_radio_work *work, int deinit),
4528 void *ctx)
4529{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004530 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004531 struct wpa_radio_work *work;
4532 int was_empty;
4533
4534 work = os_zalloc(sizeof(*work));
4535 if (work == NULL)
4536 return -1;
4537 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4538 os_get_reltime(&work->time);
4539 work->freq = freq;
4540 work->type = type;
4541 work->wpa_s = wpa_s;
4542 work->cb = cb;
4543 work->ctx = ctx;
4544
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004545 if (freq)
4546 work->bands = wpas_freq_to_band(freq);
4547 else if (os_strcmp(type, "scan") == 0 ||
4548 os_strcmp(type, "p2p-scan") == 0)
4549 work->bands = wpas_get_bands(wpa_s,
4550 ((struct wpa_driver_scan_params *)
4551 ctx)->freqs);
4552 else
4553 work->bands = wpas_get_bands(wpa_s, NULL);
4554
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004555 was_empty = dl_list_empty(&wpa_s->radio->work);
4556 if (next)
4557 dl_list_add(&wpa_s->radio->work, &work->list);
4558 else
4559 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4560 if (was_empty) {
4561 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4562 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004563 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4564 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4565 wpa_dbg(wpa_s, MSG_DEBUG,
4566 "Try to schedule a radio work (num_active_works=%u)",
4567 radio->num_active_works);
4568 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004569 }
4570
4571 return 0;
4572}
4573
4574
4575/**
4576 * radio_work_done - Indicate that a radio work item has been completed
4577 * @work: Completed work
4578 *
4579 * This function is called once the callback function registered with
4580 * radio_add_work() has completed its work.
4581 */
4582void radio_work_done(struct wpa_radio_work *work)
4583{
4584 struct wpa_supplicant *wpa_s = work->wpa_s;
4585 struct os_reltime now, diff;
4586 unsigned int started = work->started;
4587
4588 os_get_reltime(&now);
4589 os_reltime_sub(&now, &work->time, &diff);
4590 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4591 work->type, work, started ? "done" : "canceled",
4592 diff.sec, diff.usec);
4593 radio_work_free(work);
4594 if (started)
4595 radio_work_check_next(wpa_s);
4596}
4597
4598
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004599struct wpa_radio_work *
4600radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004601{
4602 struct wpa_radio_work *work;
4603 struct wpa_radio *radio = wpa_s->radio;
4604
4605 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4606 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004607 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004608 }
4609
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004610 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004611}
4612
4613
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004614static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4615 struct wpa_interface *iface)
4616{
4617 const char *ifname, *driver, *rn;
4618
4619 driver = iface->driver;
4620next_driver:
4621 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4622 return -1;
4623
4624 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4625 if (wpa_s->drv_priv == NULL) {
4626 const char *pos;
4627 pos = driver ? os_strchr(driver, ',') : NULL;
4628 if (pos) {
4629 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4630 "driver interface - try next driver wrapper");
4631 driver = pos + 1;
4632 goto next_driver;
4633 }
4634 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4635 "interface");
4636 return -1;
4637 }
4638 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4639 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4640 "driver_param '%s'", wpa_s->conf->driver_param);
4641 return -1;
4642 }
4643
4644 ifname = wpa_drv_get_ifname(wpa_s);
4645 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4646 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4647 "interface name with '%s'", ifname);
4648 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4649 }
4650
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004651 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004652 if (rn && rn[0] == '\0')
4653 rn = NULL;
4654
4655 wpa_s->radio = radio_add_interface(wpa_s, rn);
4656 if (wpa_s->radio == NULL)
4657 return -1;
4658
4659 return 0;
4660}
4661
4662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004663static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4664 struct wpa_interface *iface)
4665{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004666 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004667 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004668
4669 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4670 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4671 iface->confname ? iface->confname : "N/A",
4672 iface->driver ? iface->driver : "default",
4673 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4674 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4675
4676 if (iface->confname) {
4677#ifdef CONFIG_BACKEND_FILE
4678 wpa_s->confname = os_rel2abs_path(iface->confname);
4679 if (wpa_s->confname == NULL) {
4680 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4681 "for configuration file '%s'.",
4682 iface->confname);
4683 return -1;
4684 }
4685 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4686 iface->confname, wpa_s->confname);
4687#else /* CONFIG_BACKEND_FILE */
4688 wpa_s->confname = os_strdup(iface->confname);
4689#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004690 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004691 if (wpa_s->conf == NULL) {
4692 wpa_printf(MSG_ERROR, "Failed to read or parse "
4693 "configuration '%s'.", wpa_s->confname);
4694 return -1;
4695 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004696 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4697 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698
4699 /*
4700 * Override ctrl_interface and driver_param if set on command
4701 * line.
4702 */
4703 if (iface->ctrl_interface) {
4704 os_free(wpa_s->conf->ctrl_interface);
4705 wpa_s->conf->ctrl_interface =
4706 os_strdup(iface->ctrl_interface);
4707 }
4708
4709 if (iface->driver_param) {
4710 os_free(wpa_s->conf->driver_param);
4711 wpa_s->conf->driver_param =
4712 os_strdup(iface->driver_param);
4713 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004714
4715 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4716 os_free(wpa_s->conf->ctrl_interface);
4717 wpa_s->conf->ctrl_interface = NULL;
4718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004719 } else
4720 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4721 iface->driver_param);
4722
4723 if (wpa_s->conf == NULL) {
4724 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4725 return -1;
4726 }
4727
4728 if (iface->ifname == NULL) {
4729 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4730 return -1;
4731 }
4732 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4733 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4734 iface->ifname);
4735 return -1;
4736 }
4737 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4738
4739 if (iface->bridge_ifname) {
4740 if (os_strlen(iface->bridge_ifname) >=
4741 sizeof(wpa_s->bridge_ifname)) {
4742 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4743 "name '%s'.", iface->bridge_ifname);
4744 return -1;
4745 }
4746 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4747 sizeof(wpa_s->bridge_ifname));
4748 }
4749
4750 /* RSNA Supplicant Key Management - INITIALIZE */
4751 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4752 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4753
4754 /* Initialize driver interface and register driver event handler before
4755 * L2 receive handler so that association events are processed before
4756 * EAPOL-Key packets if both become available for the same select()
4757 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004758 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759 return -1;
4760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4762 return -1;
4763
4764 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4765 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4766 NULL);
4767 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4768
4769 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4770 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4771 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4772 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4773 "dot11RSNAConfigPMKLifetime");
4774 return -1;
4775 }
4776
4777 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4778 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4779 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4780 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4781 "dot11RSNAConfigPMKReauthThreshold");
4782 return -1;
4783 }
4784
4785 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4786 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4787 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4788 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4789 "dot11RSNAConfigSATimeout");
4790 return -1;
4791 }
4792
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004793 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4794 &wpa_s->hw.num_modes,
4795 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004796 if (wpa_s->hw.modes) {
4797 u16 i;
4798
4799 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4800 if (wpa_s->hw.modes[i].vht_capab) {
4801 wpa_s->hw_capab = CAPAB_VHT;
4802 break;
4803 }
4804
4805 if (wpa_s->hw.modes[i].ht_capab &
4806 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4807 wpa_s->hw_capab = CAPAB_HT40;
4808 else if (wpa_s->hw.modes[i].ht_capab &&
4809 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4810 wpa_s->hw_capab = CAPAB_HT;
4811 }
4812 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004813
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004814 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4815 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004816 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004817 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004818 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004819 wpa_s->drv_smps_modes = capa.smps_modes;
4820 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004821 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004822 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004823 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004824 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4825 wpa_s->max_sched_scan_plan_interval =
4826 capa.max_sched_scan_plan_interval;
4827 wpa_s->max_sched_scan_plan_iterations =
4828 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004829 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4830 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004831 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4832 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004833 wpa_s->extended_capa = capa.extended_capa;
4834 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4835 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004836 wpa_s->num_multichan_concurrent =
4837 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004838 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4839
4840 if (capa.mac_addr_rand_scan_supported)
4841 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4842 if (wpa_s->sched_scan_supported &&
4843 capa.mac_addr_rand_sched_scan_supported)
4844 wpa_s->mac_addr_rand_supported |=
4845 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004846 }
4847 if (wpa_s->max_remain_on_chan == 0)
4848 wpa_s->max_remain_on_chan = 1000;
4849
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004850 /*
4851 * Only take p2p_mgmt parameters when P2P Device is supported.
4852 * Doing it here as it determines whether l2_packet_init() will be done
4853 * during wpa_supplicant_driver_init().
4854 */
4855 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4856 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4857 else
4858 iface->p2p_mgmt = 1;
4859
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004860 if (wpa_s->num_multichan_concurrent == 0)
4861 wpa_s->num_multichan_concurrent = 1;
4862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004863 if (wpa_supplicant_driver_init(wpa_s) < 0)
4864 return -1;
4865
4866#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004867 if ((!iface->p2p_mgmt ||
4868 !(wpa_s->drv_flags &
4869 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4870 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871 return -1;
4872#endif /* CONFIG_TDLS */
4873
4874 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4875 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4876 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4877 return -1;
4878 }
4879
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004880#ifdef CONFIG_FST
4881 if (wpa_s->conf->fst_group_id) {
4882 struct fst_iface_cfg cfg;
4883 struct fst_wpa_obj iface_obj;
4884
4885 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4886 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4887 sizeof(cfg.group_id));
4888 cfg.priority = wpa_s->conf->fst_priority;
4889 cfg.llt = wpa_s->conf->fst_llt;
4890
4891 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4892 &iface_obj, &cfg);
4893 if (!wpa_s->fst) {
4894 wpa_msg(wpa_s, MSG_ERROR,
4895 "FST: Cannot attach iface %s to group %s",
4896 wpa_s->ifname, cfg.group_id);
4897 return -1;
4898 }
4899 }
4900#endif /* CONFIG_FST */
4901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 if (wpas_wps_init(wpa_s))
4903 return -1;
4904
4905 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4906 return -1;
4907 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4908
4909 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4910 if (wpa_s->ctrl_iface == NULL) {
4911 wpa_printf(MSG_ERROR,
4912 "Failed to initialize control interface '%s'.\n"
4913 "You may have another wpa_supplicant process "
4914 "already running or the file was\n"
4915 "left by an unclean termination of wpa_supplicant "
4916 "in which case you will need\n"
4917 "to manually remove this file before starting "
4918 "wpa_supplicant again.\n",
4919 wpa_s->conf->ctrl_interface);
4920 return -1;
4921 }
4922
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004923 wpa_s->gas = gas_query_init(wpa_s);
4924 if (wpa_s->gas == NULL) {
4925 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4926 return -1;
4927 }
4928
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004929 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004930 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4931 return -1;
4932 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004933
4934 if (wpa_bss_init(wpa_s) < 0)
4935 return -1;
4936
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004937 /*
4938 * Set Wake-on-WLAN triggers, if configured.
4939 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4940 * have effect anyway when the interface is down).
4941 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004942 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004943 return -1;
4944
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004945#ifdef CONFIG_EAP_PROXY
4946{
4947 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004948 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4949 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004950 if (wpa_s->mnc_len > 0) {
4951 wpa_s->imsi[len] = '\0';
4952 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4953 wpa_s->imsi, wpa_s->mnc_len);
4954 } else {
4955 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4956 }
4957}
4958#endif /* CONFIG_EAP_PROXY */
4959
Dmitry Shmidt04949592012-07-19 12:16:46 -07004960 if (pcsc_reader_init(wpa_s) < 0)
4961 return -1;
4962
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004963 if (wpas_init_ext_pw(wpa_s) < 0)
4964 return -1;
4965
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004966 wpas_rrm_reset(wpa_s);
4967
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004968 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
4969
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08004970#ifdef CONFIG_HS20
4971 hs20_init(wpa_s);
4972#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004973#ifdef CONFIG_MBO
4974 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
4975#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08004976
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07004977 wpa_supplicant_set_default_scan_ies(wpa_s);
4978
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004979 return 0;
4980}
4981
4982
4983static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004984 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004985{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004986 struct wpa_global *global = wpa_s->global;
4987 struct wpa_supplicant *iface, *prev;
4988
4989 if (wpa_s == wpa_s->parent)
4990 wpas_p2p_group_remove(wpa_s, "*");
4991
4992 iface = global->ifaces;
4993 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004994 if (iface->p2pdev == wpa_s)
4995 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004996 if (iface == wpa_s || iface->parent != wpa_s) {
4997 iface = iface->next;
4998 continue;
4999 }
5000 wpa_printf(MSG_DEBUG,
5001 "Remove remaining child interface %s from parent %s",
5002 iface->ifname, wpa_s->ifname);
5003 prev = iface;
5004 iface = iface->next;
5005 wpa_supplicant_remove_iface(global, prev, terminate);
5006 }
5007
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005008 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005009 if (wpa_s->drv_priv) {
5010 wpa_supplicant_deauthenticate(wpa_s,
5011 WLAN_REASON_DEAUTH_LEAVING);
5012
5013 wpa_drv_set_countermeasures(wpa_s, 0);
5014 wpa_clear_keys(wpa_s, NULL);
5015 }
5016
5017 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005018 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005019
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005020 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005021 radio_remove_interface(wpa_s);
5022
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005023#ifdef CONFIG_FST
5024 if (wpa_s->fst) {
5025 fst_detach(wpa_s->fst);
5026 wpa_s->fst = NULL;
5027 }
5028 if (wpa_s->received_mb_ies) {
5029 wpabuf_free(wpa_s->received_mb_ies);
5030 wpa_s->received_mb_ies = NULL;
5031 }
5032#endif /* CONFIG_FST */
5033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005034 if (wpa_s->drv_priv)
5035 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005036
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005037 if (notify)
5038 wpas_notify_iface_removed(wpa_s);
5039
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005040 if (terminate)
5041 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005042
5043 if (wpa_s->ctrl_iface) {
5044 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5045 wpa_s->ctrl_iface = NULL;
5046 }
5047
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005048#ifdef CONFIG_MESH
5049 if (wpa_s->ifmsh) {
5050 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5051 wpa_s->ifmsh = NULL;
5052 }
5053#endif /* CONFIG_MESH */
5054
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005055 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005056 wpa_config_free(wpa_s->conf);
5057 wpa_s->conf = NULL;
5058 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005059
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005060 os_free(wpa_s->ssids_from_scan_req);
5061
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005062 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005063}
5064
5065
Dmitry Shmidte4663042016-04-04 10:07:49 -07005066#ifdef CONFIG_MATCH_IFACE
5067
5068/**
5069 * wpa_supplicant_match_iface - Match an interface description to a name
5070 * @global: Pointer to global data from wpa_supplicant_init()
5071 * @ifname: Name of the interface to match
5072 * Returns: Pointer to the created interface description or %NULL on failure
5073 */
5074struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5075 const char *ifname)
5076{
5077 int i;
5078 struct wpa_interface *iface, *miface;
5079
5080 for (i = 0; i < global->params.match_iface_count; i++) {
5081 miface = &global->params.match_ifaces[i];
5082 if (!miface->ifname ||
5083 fnmatch(miface->ifname, ifname, 0) == 0) {
5084 iface = os_zalloc(sizeof(*iface));
5085 if (!iface)
5086 return NULL;
5087 *iface = *miface;
5088 iface->ifname = ifname;
5089 return iface;
5090 }
5091 }
5092
5093 return NULL;
5094}
5095
5096
5097/**
5098 * wpa_supplicant_match_existing - Match existing interfaces
5099 * @global: Pointer to global data from wpa_supplicant_init()
5100 * Returns: 0 on success, -1 on failure
5101 */
5102static int wpa_supplicant_match_existing(struct wpa_global *global)
5103{
5104 struct if_nameindex *ifi, *ifp;
5105 struct wpa_supplicant *wpa_s;
5106 struct wpa_interface *iface;
5107
5108 ifp = if_nameindex();
5109 if (!ifp) {
5110 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5111 return -1;
5112 }
5113
5114 for (ifi = ifp; ifi->if_name; ifi++) {
5115 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5116 if (wpa_s)
5117 continue;
5118 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5119 if (iface) {
5120 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5121 os_free(iface);
5122 if (wpa_s)
5123 wpa_s->matched = 1;
5124 }
5125 }
5126
5127 if_freenameindex(ifp);
5128 return 0;
5129}
5130
5131#endif /* CONFIG_MATCH_IFACE */
5132
5133
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005134/**
5135 * wpa_supplicant_add_iface - Add a new network interface
5136 * @global: Pointer to global data from wpa_supplicant_init()
5137 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005138 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005139 * Returns: Pointer to the created interface or %NULL on failure
5140 *
5141 * This function is used to add new network interfaces for %wpa_supplicant.
5142 * This can be called before wpa_supplicant_run() to add interfaces before the
5143 * main event loop has been started. In addition, new interfaces can be added
5144 * dynamically while %wpa_supplicant is already running. This could happen,
5145 * e.g., when a hotplug network adapter is inserted.
5146 */
5147struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005148 struct wpa_interface *iface,
5149 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005150{
5151 struct wpa_supplicant *wpa_s;
5152 struct wpa_interface t_iface;
5153 struct wpa_ssid *ssid;
5154
5155 if (global == NULL || iface == NULL)
5156 return NULL;
5157
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005158 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005159 if (wpa_s == NULL)
5160 return NULL;
5161
5162 wpa_s->global = global;
5163
5164 t_iface = *iface;
5165 if (global->params.override_driver) {
5166 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5167 "('%s' -> '%s')",
5168 iface->driver, global->params.override_driver);
5169 t_iface.driver = global->params.override_driver;
5170 }
5171 if (global->params.override_ctrl_interface) {
5172 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5173 "ctrl_interface ('%s' -> '%s')",
5174 iface->ctrl_interface,
5175 global->params.override_ctrl_interface);
5176 t_iface.ctrl_interface =
5177 global->params.override_ctrl_interface;
5178 }
5179 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5180 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5181 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005182 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005183 return NULL;
5184 }
5185
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005186 if (iface->p2p_mgmt == 0) {
5187 /* Notify the control interfaces about new iface */
5188 if (wpas_notify_iface_added(wpa_s)) {
5189 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5190 return NULL;
5191 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005193 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5194 wpas_notify_network_added(wpa_s, ssid);
5195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005196
5197 wpa_s->next = global->ifaces;
5198 global->ifaces = wpa_s;
5199
5200 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005201 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005203#ifdef CONFIG_P2P
5204 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005205 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005206 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005207 wpas_p2p_add_p2pdev_interface(
5208 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005209 wpa_printf(MSG_INFO,
5210 "P2P: Failed to enable P2P Device interface");
5211 /* Try to continue without. P2P will be disabled. */
5212 }
5213#endif /* CONFIG_P2P */
5214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005215 return wpa_s;
5216}
5217
5218
5219/**
5220 * wpa_supplicant_remove_iface - Remove a network interface
5221 * @global: Pointer to global data from wpa_supplicant_init()
5222 * @wpa_s: Pointer to the network interface to be removed
5223 * Returns: 0 if interface was removed, -1 if interface was not found
5224 *
5225 * This function can be used to dynamically remove network interfaces from
5226 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5227 * addition, this function is used to remove all remaining interfaces when
5228 * %wpa_supplicant is terminated.
5229 */
5230int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005231 struct wpa_supplicant *wpa_s,
5232 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233{
5234 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005235#ifdef CONFIG_MESH
5236 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5237 char *ifname = NULL;
5238#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005239
5240 /* Remove interface from the global list of interfaces */
5241 prev = global->ifaces;
5242 if (prev == wpa_s) {
5243 global->ifaces = wpa_s->next;
5244 } else {
5245 while (prev && prev->next != wpa_s)
5246 prev = prev->next;
5247 if (prev == NULL)
5248 return -1;
5249 prev->next = wpa_s->next;
5250 }
5251
5252 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5253
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005254#ifdef CONFIG_MESH
5255 if (mesh_if_created) {
5256 ifname = os_strdup(wpa_s->ifname);
5257 if (ifname == NULL) {
5258 wpa_dbg(wpa_s, MSG_ERROR,
5259 "mesh: Failed to malloc ifname");
5260 return -1;
5261 }
5262 }
5263#endif /* CONFIG_MESH */
5264
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005265 if (global->p2p_group_formation == wpa_s)
5266 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005267 if (global->p2p_invite_group == wpa_s)
5268 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005269 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005270
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005271#ifdef CONFIG_MESH
5272 if (mesh_if_created) {
5273 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5274 os_free(ifname);
5275 }
5276#endif /* CONFIG_MESH */
5277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005278 return 0;
5279}
5280
5281
5282/**
5283 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5284 * @wpa_s: Pointer to the network interface
5285 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5286 */
5287const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5288{
5289 const char *eapol_method;
5290
5291 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5292 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5293 return "NO-EAP";
5294 }
5295
5296 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5297 if (eapol_method == NULL)
5298 return "UNKNOWN-EAP";
5299
5300 return eapol_method;
5301}
5302
5303
5304/**
5305 * wpa_supplicant_get_iface - Get a new network interface
5306 * @global: Pointer to global data from wpa_supplicant_init()
5307 * @ifname: Interface name
5308 * Returns: Pointer to the interface or %NULL if not found
5309 */
5310struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5311 const char *ifname)
5312{
5313 struct wpa_supplicant *wpa_s;
5314
5315 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5316 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5317 return wpa_s;
5318 }
5319 return NULL;
5320}
5321
5322
5323#ifndef CONFIG_NO_WPA_MSG
5324static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5325{
5326 struct wpa_supplicant *wpa_s = ctx;
5327 if (wpa_s == NULL)
5328 return NULL;
5329 return wpa_s->ifname;
5330}
5331#endif /* CONFIG_NO_WPA_MSG */
5332
5333
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005334#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5335#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5336#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5337
5338/* Periodic cleanup tasks */
5339static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5340{
5341 struct wpa_global *global = eloop_ctx;
5342 struct wpa_supplicant *wpa_s;
5343
5344 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5345 wpas_periodic, global, NULL);
5346
5347#ifdef CONFIG_P2P
5348 if (global->p2p)
5349 p2p_expire_peers(global->p2p);
5350#endif /* CONFIG_P2P */
5351
5352 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5353 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5354#ifdef CONFIG_AP
5355 ap_periodic(wpa_s);
5356#endif /* CONFIG_AP */
5357 }
5358}
5359
5360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005361/**
5362 * wpa_supplicant_init - Initialize %wpa_supplicant
5363 * @params: Parameters for %wpa_supplicant
5364 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5365 *
5366 * This function is used to initialize %wpa_supplicant. After successful
5367 * initialization, the returned data pointer can be used to add and remove
5368 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5369 */
5370struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5371{
5372 struct wpa_global *global;
5373 int ret, i;
5374
5375 if (params == NULL)
5376 return NULL;
5377
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005378#ifdef CONFIG_DRIVER_NDIS
5379 {
5380 void driver_ndis_init_ops(void);
5381 driver_ndis_init_ops();
5382 }
5383#endif /* CONFIG_DRIVER_NDIS */
5384
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005385#ifndef CONFIG_NO_WPA_MSG
5386 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5387#endif /* CONFIG_NO_WPA_MSG */
5388
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005389 if (params->wpa_debug_file_path)
5390 wpa_debug_open_file(params->wpa_debug_file_path);
5391 else
5392 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005393 if (params->wpa_debug_syslog)
5394 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005395 if (params->wpa_debug_tracing) {
5396 ret = wpa_debug_open_linux_tracing();
5397 if (ret) {
5398 wpa_printf(MSG_ERROR,
5399 "Failed to enable trace logging");
5400 return NULL;
5401 }
5402 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005403
5404 ret = eap_register_methods();
5405 if (ret) {
5406 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5407 if (ret == -2)
5408 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5409 "the same EAP type.");
5410 return NULL;
5411 }
5412
5413 global = os_zalloc(sizeof(*global));
5414 if (global == NULL)
5415 return NULL;
5416 dl_list_init(&global->p2p_srv_bonjour);
5417 dl_list_init(&global->p2p_srv_upnp);
5418 global->params.daemonize = params->daemonize;
5419 global->params.wait_for_monitor = params->wait_for_monitor;
5420 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5421 if (params->pid_file)
5422 global->params.pid_file = os_strdup(params->pid_file);
5423 if (params->ctrl_interface)
5424 global->params.ctrl_interface =
5425 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005426 if (params->ctrl_interface_group)
5427 global->params.ctrl_interface_group =
5428 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005429 if (params->override_driver)
5430 global->params.override_driver =
5431 os_strdup(params->override_driver);
5432 if (params->override_ctrl_interface)
5433 global->params.override_ctrl_interface =
5434 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005435#ifdef CONFIG_MATCH_IFACE
5436 global->params.match_iface_count = params->match_iface_count;
5437 if (params->match_iface_count) {
5438 global->params.match_ifaces =
5439 os_calloc(params->match_iface_count,
5440 sizeof(struct wpa_interface));
5441 os_memcpy(global->params.match_ifaces,
5442 params->match_ifaces,
5443 params->match_iface_count *
5444 sizeof(struct wpa_interface));
5445 }
5446#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005447#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005448 if (params->conf_p2p_dev)
5449 global->params.conf_p2p_dev =
5450 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005451#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005452 wpa_debug_level = global->params.wpa_debug_level =
5453 params->wpa_debug_level;
5454 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5455 params->wpa_debug_show_keys;
5456 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5457 params->wpa_debug_timestamp;
5458
5459 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5460
5461 if (eloop_init()) {
5462 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5463 wpa_supplicant_deinit(global);
5464 return NULL;
5465 }
5466
Jouni Malinen75ecf522011-06-27 15:19:46 -07005467 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005468
5469 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5470 if (global->ctrl_iface == NULL) {
5471 wpa_supplicant_deinit(global);
5472 return NULL;
5473 }
5474
5475 if (wpas_notify_supplicant_initialized(global)) {
5476 wpa_supplicant_deinit(global);
5477 return NULL;
5478 }
5479
5480 for (i = 0; wpa_drivers[i]; i++)
5481 global->drv_count++;
5482 if (global->drv_count == 0) {
5483 wpa_printf(MSG_ERROR, "No drivers enabled");
5484 wpa_supplicant_deinit(global);
5485 return NULL;
5486 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005487 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005488 if (global->drv_priv == NULL) {
5489 wpa_supplicant_deinit(global);
5490 return NULL;
5491 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005492
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005493#ifdef CONFIG_WIFI_DISPLAY
5494 if (wifi_display_init(global) < 0) {
5495 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5496 wpa_supplicant_deinit(global);
5497 return NULL;
5498 }
5499#endif /* CONFIG_WIFI_DISPLAY */
5500
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005501 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5502 wpas_periodic, global, NULL);
5503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005504 return global;
5505}
5506
5507
5508/**
5509 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5510 * @global: Pointer to global data from wpa_supplicant_init()
5511 * Returns: 0 after successful event loop run, -1 on failure
5512 *
5513 * This function starts the main event loop and continues running as long as
5514 * there are any remaining events. In most cases, this function is running as
5515 * long as the %wpa_supplicant process in still in use.
5516 */
5517int wpa_supplicant_run(struct wpa_global *global)
5518{
5519 struct wpa_supplicant *wpa_s;
5520
5521 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005522 (wpa_supplicant_daemon(global->params.pid_file) ||
5523 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005524 return -1;
5525
Dmitry Shmidte4663042016-04-04 10:07:49 -07005526#ifdef CONFIG_MATCH_IFACE
5527 if (wpa_supplicant_match_existing(global))
5528 return -1;
5529#endif
5530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005531 if (global->params.wait_for_monitor) {
5532 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005533 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005534 wpa_supplicant_ctrl_iface_wait(
5535 wpa_s->ctrl_iface);
5536 }
5537
5538 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5539 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5540
5541 eloop_run();
5542
5543 return 0;
5544}
5545
5546
5547/**
5548 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5549 * @global: Pointer to global data from wpa_supplicant_init()
5550 *
5551 * This function is called to deinitialize %wpa_supplicant and to free all
5552 * allocated resources. Remaining network interfaces will also be removed.
5553 */
5554void wpa_supplicant_deinit(struct wpa_global *global)
5555{
5556 int i;
5557
5558 if (global == NULL)
5559 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005560
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005561 eloop_cancel_timeout(wpas_periodic, global, NULL);
5562
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005563#ifdef CONFIG_WIFI_DISPLAY
5564 wifi_display_deinit(global);
5565#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566
5567 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005568 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569
5570 if (global->ctrl_iface)
5571 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5572
5573 wpas_notify_supplicant_deinitialized(global);
5574
5575 eap_peer_unregister_methods();
5576#ifdef CONFIG_AP
5577 eap_server_unregister_methods();
5578#endif /* CONFIG_AP */
5579
5580 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5581 if (!global->drv_priv[i])
5582 continue;
5583 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5584 }
5585 os_free(global->drv_priv);
5586
5587 random_deinit();
5588
5589 eloop_destroy();
5590
5591 if (global->params.pid_file) {
5592 os_daemonize_terminate(global->params.pid_file);
5593 os_free(global->params.pid_file);
5594 }
5595 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005596 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005597 os_free(global->params.override_driver);
5598 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005599#ifdef CONFIG_MATCH_IFACE
5600 os_free(global->params.match_ifaces);
5601#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005602#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005603 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005604#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005605
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005606 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005607 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005608 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005609
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610 os_free(global);
5611 wpa_debug_close_syslog();
5612 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005613 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614}
5615
5616
5617void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5618{
5619 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5620 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5621 char country[3];
5622 country[0] = wpa_s->conf->country[0];
5623 country[1] = wpa_s->conf->country[1];
5624 country[2] = '\0';
5625 if (wpa_drv_set_country(wpa_s, country) < 0) {
5626 wpa_printf(MSG_ERROR, "Failed to set country code "
5627 "'%s'", country);
5628 }
5629 }
5630
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005631 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5632 wpas_init_ext_pw(wpa_s);
5633
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005634 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5635 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637#ifdef CONFIG_WPS
5638 wpas_wps_update_config(wpa_s);
5639#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005640 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005641 wpa_s->conf->changed_parameters = 0;
5642}
5643
5644
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005645void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005646{
5647 int i;
5648
5649 for (i = 0; i < *num_freqs; i++) {
5650 if (freqs[i] == freq)
5651 return;
5652 }
5653
5654 freqs[*num_freqs] = freq;
5655 (*num_freqs)++;
5656}
5657
5658
5659static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5660{
5661 struct wpa_bss *bss, *cbss;
5662 const int max_freqs = 10;
5663 int *freqs;
5664 int num_freqs = 0;
5665
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005666 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005667 if (freqs == NULL)
5668 return NULL;
5669
5670 cbss = wpa_s->current_bss;
5671
5672 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5673 if (bss == cbss)
5674 continue;
5675 if (bss->ssid_len == cbss->ssid_len &&
5676 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5677 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5678 add_freq(freqs, &num_freqs, bss->freq);
5679 if (num_freqs == max_freqs)
5680 break;
5681 }
5682 }
5683
5684 if (num_freqs == 0) {
5685 os_free(freqs);
5686 freqs = NULL;
5687 }
5688
5689 return freqs;
5690}
5691
5692
5693void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5694{
5695 int timeout;
5696 int count;
5697 int *freqs = NULL;
5698
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005699 wpas_connect_work_done(wpa_s);
5700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005701 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005702 * Remove possible authentication timeout since the connection failed.
5703 */
5704 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5705
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005706 /*
5707 * There is no point in blacklisting the AP if this event is
5708 * generated based on local request to disconnect.
5709 */
5710 if (wpa_s->own_disconnect_req) {
5711 wpa_s->own_disconnect_req = 0;
5712 wpa_dbg(wpa_s, MSG_DEBUG,
5713 "Ignore connection failure due to local request to disconnect");
5714 return;
5715 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005716 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005717 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5718 "indication since interface has been put into "
5719 "disconnected state");
5720 return;
5721 }
5722
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005723 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005724 * Add the failed BSSID into the blacklist and speed up next scan
5725 * attempt if there could be other APs that could accept association.
5726 * The current blacklist count indicates how many times we have tried
5727 * connecting to this AP and multiple attempts mean that other APs are
5728 * either not available or has already been tried, so that we can start
5729 * increasing the delay here to avoid constant scanning.
5730 */
5731 count = wpa_blacklist_add(wpa_s, bssid);
5732 if (count == 1 && wpa_s->current_bss) {
5733 /*
5734 * This BSS was not in the blacklist before. If there is
5735 * another BSS available for the same ESS, we should try that
5736 * next. Otherwise, we may as well try this one once more
5737 * before allowing other, likely worse, ESSes to be considered.
5738 */
5739 freqs = get_bss_freqs_in_ess(wpa_s);
5740 if (freqs) {
5741 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5742 "has been seen; try it next");
5743 wpa_blacklist_add(wpa_s, bssid);
5744 /*
5745 * On the next scan, go through only the known channels
5746 * used in this ESS based on previous scans to speed up
5747 * common load balancing use case.
5748 */
5749 os_free(wpa_s->next_scan_freqs);
5750 wpa_s->next_scan_freqs = freqs;
5751 }
5752 }
5753
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005754 /*
5755 * Add previous failure count in case the temporary blacklist was
5756 * cleared due to no other BSSes being available.
5757 */
5758 count += wpa_s->extra_blacklist_count;
5759
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005760 if (count > 3 && wpa_s->current_ssid) {
5761 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5762 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005763 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005764 }
5765
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005766 switch (count) {
5767 case 1:
5768 timeout = 100;
5769 break;
5770 case 2:
5771 timeout = 500;
5772 break;
5773 case 3:
5774 timeout = 1000;
5775 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005776 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005777 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005778 break;
5779 default:
5780 timeout = 10000;
5781 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005782 }
5783
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005784 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5785 "ms", count, timeout);
5786
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005787 /*
5788 * TODO: if more than one possible AP is available in scan results,
5789 * could try the other ones before requesting a new scan.
5790 */
5791 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5792 1000 * (timeout % 1000));
5793}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005794
5795
5796int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5797{
5798 return wpa_s->conf->ap_scan == 2 ||
5799 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5800}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005801
Dmitry Shmidt04949592012-07-19 12:16:46 -07005802
5803#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
5804int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5805 struct wpa_ssid *ssid,
5806 const char *field,
5807 const char *value)
5808{
5809#ifdef IEEE8021X_EAPOL
5810 struct eap_peer_config *eap = &ssid->eap;
5811
5812 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5813 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5814 (const u8 *) value, os_strlen(value));
5815
5816 switch (wpa_supplicant_ctrl_req_from_string(field)) {
5817 case WPA_CTRL_REQ_EAP_IDENTITY:
5818 os_free(eap->identity);
5819 eap->identity = (u8 *) os_strdup(value);
5820 eap->identity_len = os_strlen(value);
5821 eap->pending_req_identity = 0;
5822 if (ssid == wpa_s->current_ssid)
5823 wpa_s->reassociate = 1;
5824 break;
5825 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005826 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005827 eap->password = (u8 *) os_strdup(value);
5828 eap->password_len = os_strlen(value);
5829 eap->pending_req_password = 0;
5830 if (ssid == wpa_s->current_ssid)
5831 wpa_s->reassociate = 1;
5832 break;
5833 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005834 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005835 eap->new_password = (u8 *) os_strdup(value);
5836 eap->new_password_len = os_strlen(value);
5837 eap->pending_req_new_password = 0;
5838 if (ssid == wpa_s->current_ssid)
5839 wpa_s->reassociate = 1;
5840 break;
5841 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005842 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005843 eap->pin = os_strdup(value);
5844 eap->pending_req_pin = 0;
5845 if (ssid == wpa_s->current_ssid)
5846 wpa_s->reassociate = 1;
5847 break;
5848 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005849 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005850 eap->otp = (u8 *) os_strdup(value);
5851 eap->otp_len = os_strlen(value);
5852 os_free(eap->pending_req_otp);
5853 eap->pending_req_otp = NULL;
5854 eap->pending_req_otp_len = 0;
5855 break;
5856 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005857 str_clear_free(eap->private_key_passwd);
5858 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005859 eap->pending_req_passphrase = 0;
5860 if (ssid == wpa_s->current_ssid)
5861 wpa_s->reassociate = 1;
5862 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005863 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005864 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005865 eap->external_sim_resp = os_strdup(value);
5866 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005867 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5868 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5869 return -1;
5870 ssid->mem_only_psk = 1;
5871 if (ssid->passphrase)
5872 wpa_config_update_psk(ssid);
5873 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5874 wpa_supplicant_req_scan(wpa_s, 0, 0);
5875 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005876 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5877 if (eap->pending_ext_cert_check != PENDING_CHECK)
5878 return -1;
5879 if (os_strcmp(value, "good") == 0)
5880 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5881 else if (os_strcmp(value, "bad") == 0)
5882 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5883 else
5884 return -1;
5885 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005886 default:
5887 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
5888 return -1;
5889 }
5890
5891 return 0;
5892#else /* IEEE8021X_EAPOL */
5893 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5894 return -1;
5895#endif /* IEEE8021X_EAPOL */
5896}
5897#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5898
5899
5900int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5901{
5902 int i;
5903 unsigned int drv_enc;
5904
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005905 if (wpa_s->p2p_mgmt)
5906 return 1; /* no normal network profiles on p2p_mgmt interface */
5907
Dmitry Shmidt04949592012-07-19 12:16:46 -07005908 if (ssid == NULL)
5909 return 1;
5910
5911 if (ssid->disabled)
5912 return 1;
5913
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005914 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005915 drv_enc = wpa_s->drv_enc;
5916 else
5917 drv_enc = (unsigned int) -1;
5918
5919 for (i = 0; i < NUM_WEP_KEYS; i++) {
5920 size_t len = ssid->wep_key_len[i];
5921 if (len == 0)
5922 continue;
5923 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5924 continue;
5925 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5926 continue;
5927 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5928 continue;
5929 return 1; /* invalid WEP key */
5930 }
5931
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005932 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005933 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5934 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005935 return 1;
5936
Dmitry Shmidt04949592012-07-19 12:16:46 -07005937 return 0;
5938}
5939
5940
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005941int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5942{
5943#ifdef CONFIG_IEEE80211W
5944 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5945 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5946 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5947 /*
5948 * Driver does not support BIP -- ignore pmf=1 default
5949 * since the connection with PMF would fail and the
5950 * configuration does not require PMF to be enabled.
5951 */
5952 return NO_MGMT_FRAME_PROTECTION;
5953 }
5954
Dmitry Shmidt849734c2016-05-27 09:59:01 -07005955 if (ssid &&
5956 (ssid->key_mgmt &
5957 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
5958 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
5959 /*
5960 * Do not use the default PMF value for non-RSN networks
5961 * since PMF is available only with RSN and pmf=2
5962 * configuration would otherwise prevent connections to
5963 * all open networks.
5964 */
5965 return NO_MGMT_FRAME_PROTECTION;
5966 }
5967
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005968 return wpa_s->conf->pmf;
5969 }
5970
5971 return ssid->ieee80211w;
5972#else /* CONFIG_IEEE80211W */
5973 return NO_MGMT_FRAME_PROTECTION;
5974#endif /* CONFIG_IEEE80211W */
5975}
5976
5977
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005978int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005979{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005980 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005981 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005982 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005983 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005984 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005985}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005986
5987
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005988void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005989{
5990 struct wpa_ssid *ssid = wpa_s->current_ssid;
5991 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005992 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005993
5994 if (ssid == NULL) {
5995 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5996 "SSID block");
5997 return;
5998 }
5999
6000 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6001 return;
6002
6003 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006004
6005#ifdef CONFIG_P2P
6006 if (ssid->p2p_group &&
6007 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6008 /*
6009 * Skip the wait time since there is a short timeout on the
6010 * connection to a P2P group.
6011 */
6012 return;
6013 }
6014#endif /* CONFIG_P2P */
6015
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006016 if (ssid->auth_failures > 50)
6017 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006018 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006019 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006020 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006021 dur = 90;
6022 else if (ssid->auth_failures > 3)
6023 dur = 60;
6024 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006025 dur = 30;
6026 else if (ssid->auth_failures > 1)
6027 dur = 20;
6028 else
6029 dur = 10;
6030
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006031 if (ssid->auth_failures > 1 &&
6032 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6033 dur += os_random() % (ssid->auth_failures * 10);
6034
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006035 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006036 if (now.sec + dur <= ssid->disabled_until.sec)
6037 return;
6038
6039 ssid->disabled_until.sec = now.sec + dur;
6040
6041 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006042 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006043 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006044 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006045}
6046
6047
6048void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6049 struct wpa_ssid *ssid, int clear_failures)
6050{
6051 if (ssid == NULL)
6052 return;
6053
6054 if (ssid->disabled_until.sec) {
6055 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6056 "id=%d ssid=\"%s\"",
6057 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6058 }
6059 ssid->disabled_until.sec = 0;
6060 ssid->disabled_until.usec = 0;
6061 if (clear_failures)
6062 ssid->auth_failures = 0;
6063}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006064
6065
6066int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6067{
6068 size_t i;
6069
6070 if (wpa_s->disallow_aps_bssid == NULL)
6071 return 0;
6072
6073 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6074 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6075 bssid, ETH_ALEN) == 0)
6076 return 1;
6077 }
6078
6079 return 0;
6080}
6081
6082
6083int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6084 size_t ssid_len)
6085{
6086 size_t i;
6087
6088 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6089 return 0;
6090
6091 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6092 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6093 if (ssid_len == s->ssid_len &&
6094 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6095 return 1;
6096 }
6097
6098 return 0;
6099}
6100
6101
6102/**
6103 * wpas_request_connection - Request a new connection
6104 * @wpa_s: Pointer to the network interface
6105 *
6106 * This function is used to request a new connection to be found. It will mark
6107 * the interface to allow reassociation and request a new scan to find a
6108 * suitable network to connect to.
6109 */
6110void wpas_request_connection(struct wpa_supplicant *wpa_s)
6111{
6112 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006113 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006114 wpa_supplicant_reinit_autoscan(wpa_s);
6115 wpa_s->extra_blacklist_count = 0;
6116 wpa_s->disconnected = 0;
6117 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006118
6119 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6120 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006121 else
6122 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006123}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006124
6125
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006126/**
6127 * wpas_request_disconnection - Request disconnection
6128 * @wpa_s: Pointer to the network interface
6129 *
6130 * This function is used to request disconnection from the currently connected
6131 * network. This will stop any ongoing scans and initiate deauthentication.
6132 */
6133void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6134{
6135#ifdef CONFIG_SME
6136 wpa_s->sme.prev_bssid_set = 0;
6137#endif /* CONFIG_SME */
6138 wpa_s->reassociate = 0;
6139 wpa_s->disconnected = 1;
6140 wpa_supplicant_cancel_sched_scan(wpa_s);
6141 wpa_supplicant_cancel_scan(wpa_s);
6142 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6143 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6144}
6145
6146
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006147void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6148 struct wpa_used_freq_data *freqs_data,
6149 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006150{
6151 unsigned int i;
6152
6153 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6154 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006155 for (i = 0; i < len; i++) {
6156 struct wpa_used_freq_data *cur = &freqs_data[i];
6157 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6158 i, cur->freq, cur->flags);
6159 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006160}
6161
6162
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006163/*
6164 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006165 * are using the same radio as the current interface, and in addition, get
6166 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006167 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006168int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6169 struct wpa_used_freq_data *freqs_data,
6170 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006171{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006172 struct wpa_supplicant *ifs;
6173 u8 bssid[ETH_ALEN];
6174 int freq;
6175 unsigned int idx = 0, i;
6176
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006177 wpa_dbg(wpa_s, MSG_DEBUG,
6178 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006179 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006180
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006181 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6182 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006183 if (idx == len)
6184 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006185
6186 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6187 continue;
6188
6189 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006190 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6191 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006192 freq = ifs->current_ssid->frequency;
6193 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6194 freq = ifs->assoc_freq;
6195 else
6196 continue;
6197
6198 /* Hold only distinct freqs */
6199 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006200 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006201 break;
6202
6203 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006204 freqs_data[idx++].freq = freq;
6205
6206 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006207 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006208 WPA_FREQ_USED_BY_P2P_CLIENT :
6209 WPA_FREQ_USED_BY_INFRA_STATION;
6210 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006211 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006212
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006213 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006214 return idx;
6215}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006216
6217
6218/*
6219 * Find the operating frequencies of any of the virtual interfaces that
6220 * are using the same radio as the current interface.
6221 */
6222int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6223 int *freq_array, unsigned int len)
6224{
6225 struct wpa_used_freq_data *freqs_data;
6226 int num, i;
6227
6228 os_memset(freq_array, 0, sizeof(int) * len);
6229
6230 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6231 if (!freqs_data)
6232 return -1;
6233
6234 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6235 for (i = 0; i < num; i++)
6236 freq_array[i] = freqs_data[i].freq;
6237
6238 os_free(freqs_data);
6239
6240 return num;
6241}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006242
6243
6244static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6245{
6246 struct rrm_data *rrm = data;
6247
6248 if (!rrm->notify_neighbor_rep) {
6249 wpa_printf(MSG_ERROR,
6250 "RRM: Unexpected neighbor report timeout");
6251 return;
6252 }
6253
6254 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6255 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6256
6257 rrm->notify_neighbor_rep = NULL;
6258 rrm->neighbor_rep_cb_ctx = NULL;
6259}
6260
6261
6262/*
6263 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6264 * @wpa_s: Pointer to wpa_supplicant
6265 */
6266void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6267{
6268 wpa_s->rrm.rrm_used = 0;
6269
6270 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6271 NULL);
6272 if (wpa_s->rrm.notify_neighbor_rep)
6273 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6274 wpa_s->rrm.next_neighbor_rep_token = 1;
6275}
6276
6277
6278/*
6279 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6280 * @wpa_s: Pointer to wpa_supplicant
6281 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6282 * @report_len: Length of neighbor report buffer
6283 */
6284void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6285 const u8 *report, size_t report_len)
6286{
6287 struct wpabuf *neighbor_rep;
6288
6289 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6290 if (report_len < 1)
6291 return;
6292
6293 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6294 wpa_printf(MSG_DEBUG,
6295 "RRM: Discarding neighbor report with token %d (expected %d)",
6296 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6297 return;
6298 }
6299
6300 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6301 NULL);
6302
6303 if (!wpa_s->rrm.notify_neighbor_rep) {
6304 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6305 return;
6306 }
6307
6308 /* skipping the first byte, which is only an id (dialog token) */
6309 neighbor_rep = wpabuf_alloc(report_len - 1);
6310 if (neighbor_rep == NULL)
6311 return;
6312 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6313 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6314 report[0]);
6315 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6316 neighbor_rep);
6317 wpa_s->rrm.notify_neighbor_rep = NULL;
6318 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6319}
6320
6321
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006322#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6323/* Workaround different, undefined for Windows, error codes used here */
6324#define ENOTCONN -1
6325#define EOPNOTSUPP -1
6326#define ECANCELED -1
6327#endif
6328
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006329/* Measurement Request element + Location Subject + Maximum Age subelement */
6330#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6331/* Measurement Request element + Location Civic Request */
6332#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6333
6334
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006335/**
6336 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6337 * @wpa_s: Pointer to wpa_supplicant
6338 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6339 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006340 * @lci: if set, neighbor request will include LCI request
6341 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006342 * @cb: Callback function to be called once the requested report arrives, or
6343 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6344 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6345 * the requester's responsibility to free it.
6346 * In the latter case NULL will be sent in 'neighbor_rep'.
6347 * @cb_ctx: Context value to send the callback function
6348 * Returns: 0 in case of success, negative error code otherwise
6349 *
6350 * In case there is a previous request which has not been answered yet, the
6351 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6352 * Request must contain a callback function.
6353 */
6354int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006355 const struct wpa_ssid_value *ssid,
6356 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006357 void (*cb)(void *ctx,
6358 struct wpabuf *neighbor_rep),
6359 void *cb_ctx)
6360{
6361 struct wpabuf *buf;
6362 const u8 *rrm_ie;
6363
6364 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6365 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6366 return -ENOTCONN;
6367 }
6368
6369 if (!wpa_s->rrm.rrm_used) {
6370 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6371 return -EOPNOTSUPP;
6372 }
6373
6374 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6375 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6376 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6377 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6378 wpa_printf(MSG_DEBUG,
6379 "RRM: No network support for Neighbor Report.");
6380 return -EOPNOTSUPP;
6381 }
6382
6383 if (!cb) {
6384 wpa_printf(MSG_DEBUG,
6385 "RRM: Neighbor Report request must provide a callback.");
6386 return -EINVAL;
6387 }
6388
6389 /* Refuse if there's a live request */
6390 if (wpa_s->rrm.notify_neighbor_rep) {
6391 wpa_printf(MSG_DEBUG,
6392 "RRM: Currently handling previous Neighbor Report.");
6393 return -EBUSY;
6394 }
6395
6396 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006397 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6398 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6399 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006400 if (buf == NULL) {
6401 wpa_printf(MSG_DEBUG,
6402 "RRM: Failed to allocate Neighbor Report Request");
6403 return -ENOMEM;
6404 }
6405
6406 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6407 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6408 wpa_s->rrm.next_neighbor_rep_token);
6409
6410 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6411 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6412 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6413 if (ssid) {
6414 wpabuf_put_u8(buf, WLAN_EID_SSID);
6415 wpabuf_put_u8(buf, ssid->ssid_len);
6416 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6417 }
6418
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006419 if (lci) {
6420 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6421 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6422 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6423
6424 /*
6425 * Measurement token; nonzero number that is unique among the
6426 * Measurement Request elements in a particular frame.
6427 */
6428 wpabuf_put_u8(buf, 1); /* Measurement Token */
6429
6430 /*
6431 * Parallel, Enable, Request, and Report bits are 0, Duration is
6432 * reserved.
6433 */
6434 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6435 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6436
6437 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6438 /* Location Subject */
6439 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6440
6441 /* Optional Subelements */
6442 /*
6443 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6444 * The Maximum Age subelement is required, otherwise the AP can
6445 * send only data that was determined after receiving the
6446 * request. Setting it here to unlimited age.
6447 */
6448 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6449 wpabuf_put_u8(buf, 2);
6450 wpabuf_put_le16(buf, 0xffff);
6451 }
6452
6453 if (civic) {
6454 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6455 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6456 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6457
6458 /*
6459 * Measurement token; nonzero number that is unique among the
6460 * Measurement Request elements in a particular frame.
6461 */
6462 wpabuf_put_u8(buf, 2); /* Measurement Token */
6463
6464 /*
6465 * Parallel, Enable, Request, and Report bits are 0, Duration is
6466 * reserved.
6467 */
6468 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6469 /* Measurement Type */
6470 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6471
6472 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6473 * Location Civic request */
6474 /* Location Subject */
6475 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6476 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6477 /* Location Service Interval Units: Seconds */
6478 wpabuf_put_u8(buf, 0);
6479 /* Location Service Interval: 0 - Only one report is requested
6480 */
6481 wpabuf_put_le16(buf, 0);
6482 /* No optional subelements */
6483 }
6484
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006485 wpa_s->rrm.next_neighbor_rep_token++;
6486
6487 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6488 wpa_s->own_addr, wpa_s->bssid,
6489 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6490 wpa_printf(MSG_DEBUG,
6491 "RRM: Failed to send Neighbor Report Request");
6492 wpabuf_free(buf);
6493 return -ECANCELED;
6494 }
6495
6496 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6497 wpa_s->rrm.notify_neighbor_rep = cb;
6498 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6499 wpas_rrm_neighbor_rep_timeout_handler,
6500 &wpa_s->rrm, NULL);
6501
6502 wpabuf_free(buf);
6503 return 0;
6504}
6505
6506
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006507static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6508 const u8 *request, size_t len,
6509 struct wpabuf *report)
6510{
6511 u8 token, type, subject;
6512 u16 max_age = 0;
6513 struct os_reltime t, diff;
6514 unsigned long diff_l;
6515 u8 *ptoken;
6516 const u8 *subelem;
6517
6518 if (!wpa_s->lci || len < 3 + 4)
6519 return report;
6520
6521 token = *request++;
6522 /* Measurement request mode isn't used */
6523 request++;
6524 type = *request++;
6525 subject = *request++;
6526
6527 wpa_printf(MSG_DEBUG,
6528 "Measurement request token %u type %u location subject %u",
6529 token, type, subject);
6530
6531 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6532 wpa_printf(MSG_INFO,
6533 "Not building LCI report - bad type or location subject");
6534 return report;
6535 }
6536
6537 /* Subelements are formatted exactly like elements */
6538 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6539 if (subelem && subelem[1] == 2)
6540 max_age = WPA_GET_LE16(subelem + 2);
6541
6542 if (os_get_reltime(&t))
6543 return report;
6544
6545 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6546 /* LCI age is calculated in 10th of a second units. */
6547 diff_l = diff.sec * 10 + diff.usec / 100000;
6548
6549 if (max_age != 0xffff && max_age < diff_l)
6550 return report;
6551
6552 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6553 return report;
6554
6555 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6556 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6557 /* We'll override user's measurement token */
6558 ptoken = wpabuf_put(report, 0);
6559 wpabuf_put_buf(report, wpa_s->lci);
6560 *ptoken = token;
6561
6562 return report;
6563}
6564
6565
6566void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6567 const u8 *src,
6568 const u8 *frame, size_t len)
6569{
6570 struct wpabuf *buf, *report;
6571 u8 token;
6572 const u8 *ie, *end;
6573
6574 if (wpa_s->wpa_state != WPA_COMPLETED) {
6575 wpa_printf(MSG_INFO,
6576 "RRM: Ignoring radio measurement request: Not associated");
6577 return;
6578 }
6579
6580 if (!wpa_s->rrm.rrm_used) {
6581 wpa_printf(MSG_INFO,
6582 "RRM: Ignoring radio measurement request: Not RRM network");
6583 return;
6584 }
6585
6586 if (len < 3) {
6587 wpa_printf(MSG_INFO,
6588 "RRM: Ignoring too short radio measurement request");
6589 return;
6590 }
6591
6592 end = frame + len;
6593
6594 token = *frame++;
6595
6596 /* Ignore number of repetitions because it's not used in LCI request */
6597 frame += 2;
6598
6599 report = NULL;
6600 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6601 ie[1] >= 3) {
6602 u8 msmt_type;
6603
6604 msmt_type = ie[4];
6605 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6606
6607 switch (msmt_type) {
6608 case MEASURE_TYPE_LCI:
6609 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6610 report);
6611 break;
6612 default:
6613 wpa_printf(MSG_INFO,
6614 "RRM: Unsupported radio measurement request %d",
6615 msmt_type);
6616 break;
6617 }
6618
6619 frame = ie + ie[1] + 2;
6620 }
6621
6622 if (!report)
6623 return;
6624
6625 buf = wpabuf_alloc(3 + wpabuf_len(report));
6626 if (!buf) {
6627 wpabuf_free(report);
6628 return;
6629 }
6630
6631 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6632 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6633 wpabuf_put_u8(buf, token);
6634
6635 wpabuf_put_buf(buf, report);
6636 wpabuf_free(report);
6637
6638 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6639 wpa_s->own_addr, wpa_s->bssid,
6640 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6641 wpa_printf(MSG_ERROR,
6642 "RRM: Radio measurement report failed: Sending Action frame failed");
6643 }
6644 wpabuf_free(buf);
6645}
6646
6647
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006648void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6649 const u8 *src,
6650 const u8 *frame, size_t len,
6651 int rssi)
6652{
6653 struct wpabuf *buf;
6654 const struct rrm_link_measurement_request *req;
6655 struct rrm_link_measurement_report report;
6656
6657 if (wpa_s->wpa_state != WPA_COMPLETED) {
6658 wpa_printf(MSG_INFO,
6659 "RRM: Ignoring link measurement request. Not associated");
6660 return;
6661 }
6662
6663 if (!wpa_s->rrm.rrm_used) {
6664 wpa_printf(MSG_INFO,
6665 "RRM: Ignoring link measurement request. Not RRM network");
6666 return;
6667 }
6668
6669 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6670 wpa_printf(MSG_INFO,
6671 "RRM: Measurement report failed. TX power insertion not supported");
6672 return;
6673 }
6674
6675 req = (const struct rrm_link_measurement_request *) frame;
6676 if (len < sizeof(*req)) {
6677 wpa_printf(MSG_INFO,
6678 "RRM: Link measurement report failed. Request too short");
6679 return;
6680 }
6681
6682 os_memset(&report, 0, sizeof(report));
6683 report.tpc.eid = WLAN_EID_TPC_REPORT;
6684 report.tpc.len = 2;
6685 report.rsni = 255; /* 255 indicates that RSNI is not available */
6686 report.dialog_token = req->dialog_token;
6687
6688 /*
6689 * It's possible to estimate RCPI based on RSSI in dBm. This
6690 * calculation will not reflect the correct value for high rates,
6691 * but it's good enough for Action frames which are transmitted
6692 * with up to 24 Mbps rates.
6693 */
6694 if (!rssi)
6695 report.rcpi = 255; /* not available */
6696 else if (rssi < -110)
6697 report.rcpi = 0;
6698 else if (rssi > 0)
6699 report.rcpi = 220;
6700 else
6701 report.rcpi = (rssi + 110) * 2;
6702
6703 /* action_category + action_code */
6704 buf = wpabuf_alloc(2 + sizeof(report));
6705 if (buf == NULL) {
6706 wpa_printf(MSG_ERROR,
6707 "RRM: Link measurement report failed. Buffer allocation failed");
6708 return;
6709 }
6710
6711 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6712 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6713 wpabuf_put_data(buf, &report, sizeof(report));
6714 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6715 wpabuf_head(buf), wpabuf_len(buf));
6716
6717 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6718 wpa_s->own_addr, wpa_s->bssid,
6719 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6720 wpa_printf(MSG_ERROR,
6721 "RRM: Link measurement report failed. Send action failed");
6722 }
6723 wpabuf_free(buf);
6724}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006725
6726
6727struct wpa_supplicant *
6728wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6729{
6730 switch (frame) {
6731#ifdef CONFIG_P2P
6732 case VENDOR_ELEM_PROBE_REQ_P2P:
6733 case VENDOR_ELEM_PROBE_RESP_P2P:
6734 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6735 case VENDOR_ELEM_BEACON_P2P_GO:
6736 case VENDOR_ELEM_P2P_PD_REQ:
6737 case VENDOR_ELEM_P2P_PD_RESP:
6738 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6739 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6740 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6741 case VENDOR_ELEM_P2P_INV_REQ:
6742 case VENDOR_ELEM_P2P_INV_RESP:
6743 case VENDOR_ELEM_P2P_ASSOC_REQ:
6744 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006745 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006746#endif /* CONFIG_P2P */
6747 default:
6748 return wpa_s;
6749 }
6750}
6751
6752
6753void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6754{
6755 unsigned int i;
6756 char buf[30];
6757
6758 wpa_printf(MSG_DEBUG, "Update vendor elements");
6759
6760 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6761 if (wpa_s->vendor_elem[i]) {
6762 int res;
6763
6764 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6765 if (!os_snprintf_error(sizeof(buf), res)) {
6766 wpa_hexdump_buf(MSG_DEBUG, buf,
6767 wpa_s->vendor_elem[i]);
6768 }
6769 }
6770 }
6771
6772#ifdef CONFIG_P2P
6773 if (wpa_s->parent == wpa_s &&
6774 wpa_s->global->p2p &&
6775 !wpa_s->global->p2p_disabled)
6776 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6777#endif /* CONFIG_P2P */
6778}
6779
6780
6781int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6782 const u8 *elem, size_t len)
6783{
6784 u8 *ie, *end;
6785
6786 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6787 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6788
6789 for (; ie + 1 < end; ie += 2 + ie[1]) {
6790 if (ie + len > end)
6791 break;
6792 if (os_memcmp(ie, elem, len) != 0)
6793 continue;
6794
6795 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6796 wpabuf_free(wpa_s->vendor_elem[frame]);
6797 wpa_s->vendor_elem[frame] = NULL;
6798 } else {
6799 os_memmove(ie, ie + len, end - (ie + len));
6800 wpa_s->vendor_elem[frame]->used -= len;
6801 }
6802 wpas_vendor_elem_update(wpa_s);
6803 return 0;
6804 }
6805
6806 return -1;
6807}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006808
6809
6810struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6811 u16 num_modes, enum hostapd_hw_mode mode)
6812{
6813 u16 i;
6814
6815 for (i = 0; i < num_modes; i++) {
6816 if (modes[i].mode == mode)
6817 return &modes[i];
6818 }
6819
6820 return NULL;
6821}
6822
6823
6824static struct
6825wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6826 const u8 *bssid)
6827{
6828 struct wpa_bss_tmp_disallowed *bss;
6829
6830 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6831 struct wpa_bss_tmp_disallowed, list) {
6832 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6833 return bss;
6834 }
6835
6836 return NULL;
6837}
6838
6839
6840void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6841 unsigned int sec)
6842{
6843 struct wpa_bss_tmp_disallowed *bss;
6844 struct os_reltime until;
6845
6846 os_get_reltime(&until);
6847 until.sec += sec;
6848
6849 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6850 if (bss) {
6851 bss->disallowed_until = until;
6852 return;
6853 }
6854
6855 bss = os_malloc(sizeof(*bss));
6856 if (!bss) {
6857 wpa_printf(MSG_DEBUG,
6858 "Failed to allocate memory for temp disallow BSS");
6859 return;
6860 }
6861
6862 bss->disallowed_until = until;
6863 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6864 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6865}
6866
6867
6868int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6869{
6870 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6871 struct os_reltime now, age;
6872
6873 os_get_reltime(&now);
6874
6875 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6876 struct wpa_bss_tmp_disallowed, list) {
6877 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6878 /* This BSS is not disallowed anymore */
6879 dl_list_del(&tmp->list);
6880 os_free(tmp);
6881 continue;
6882 }
6883 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6884 bss = tmp;
6885 break;
6886 }
6887 }
6888 if (!bss)
6889 return 0;
6890
6891 os_reltime_sub(&bss->disallowed_until, &now, &age);
6892 wpa_printf(MSG_DEBUG,
6893 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6894 MAC2STR(bss->bssid), age.sec, age.usec);
6895 return 1;
6896}