blob: f3e7d01194fe2afc5022d8e99074bb92f3e1e198 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalom74f70d42019-02-11 14:42:39 -08003 * Copyright (c) 2003-2019, 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 Shmidtd2986c22017-10-23 14:22:09 -070041#include "common/gas_server.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080043#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "blacklist.h"
45#include "wpas_glue.h"
46#include "wps_supplicant.h"
47#include "ibss_rsn.h"
48#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080049#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070050#include "ap.h"
51#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070052#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "notify.h"
54#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070055#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "bss.h"
57#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080058#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070060#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070061#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080062#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070063#include "dpp_supplicant.h"
64#ifdef CONFIG_MESH
65#include "ap/ap_config.h"
66#include "ap/hostapd.h"
67#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070068
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070069const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070"wpa_supplicant v" VERSION_STR "\n"
Hai Shalom74f70d42019-02-11 14:42:39 -080071"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080074"This software may be distributed under the terms of the BSD license.\n"
75"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076#ifdef EAP_TLS_OPENSSL
77"\nThis product includes software developed by the OpenSSL Project\n"
78"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
79#endif /* EAP_TLS_OPENSSL */
80;
81
82#ifndef CONFIG_NO_STDOUT_DEBUG
83/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070084const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080085"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070086const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080087"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"\n"
89"Redistribution and use in source and binary forms, with or without\n"
90"modification, are permitted provided that the following conditions are\n"
91"met:\n"
92"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070093const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070094"1. Redistributions of source code must retain the above copyright\n"
95" notice, this list of conditions and the following disclaimer.\n"
96"\n"
97"2. Redistributions in binary form must reproduce the above copyright\n"
98" notice, this list of conditions and the following disclaimer in the\n"
99" documentation and/or other materials provided with the distribution.\n"
100"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700101const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
103" names of its contributors may be used to endorse or promote products\n"
104" derived from this software without specific prior written permission.\n"
105"\n"
106"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
107"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
108"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
109"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700110const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
112"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
113"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
114"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
115"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
116"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
117"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
118"\n";
119#endif /* CONFIG_NO_STDOUT_DEBUG */
120
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700121
122static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
123#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
124static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
125#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
126
127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128/* Configure default/group WEP keys for static WEP */
129int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
130{
131 int i, set = 0;
132
133 for (i = 0; i < NUM_WEP_KEYS; i++) {
134 if (ssid->wep_key_len[i] == 0)
135 continue;
136
137 set = 1;
138 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
139 i, i == ssid->wep_tx_keyidx, NULL, 0,
140 ssid->wep_key[i], ssid->wep_key_len[i]);
141 }
142
143 return set;
144}
145
146
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700147int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
148 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149{
150 u8 key[32];
151 size_t keylen;
152 enum wpa_alg alg;
153 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800154 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155
156 /* IBSS/WPA-None uses only one key (Group) for both receiving and
157 * sending unicast and multicast packets. */
158
159 if (ssid->mode != WPAS_MODE_IBSS) {
160 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
161 "IBSS/ad-hoc) for WPA-None", ssid->mode);
162 return -1;
163 }
164
165 if (!ssid->psk_set) {
166 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
167 "WPA-None");
168 return -1;
169 }
170
171 switch (wpa_s->group_cipher) {
172 case WPA_CIPHER_CCMP:
173 os_memcpy(key, ssid->psk, 16);
174 keylen = 16;
175 alg = WPA_ALG_CCMP;
176 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700177 case WPA_CIPHER_GCMP:
178 os_memcpy(key, ssid->psk, 16);
179 keylen = 16;
180 alg = WPA_ALG_GCMP;
181 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182 case WPA_CIPHER_TKIP:
183 /* WPA-None uses the same Michael MIC key for both TX and RX */
184 os_memcpy(key, ssid->psk, 16 + 8);
185 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
186 keylen = 32;
187 alg = WPA_ALG_TKIP;
188 break;
189 default:
190 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
191 "WPA-None", wpa_s->group_cipher);
192 return -1;
193 }
194
195 /* TODO: should actually remember the previously used seq#, both for TX
196 * and RX from each STA.. */
197
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800198 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
199 os_memset(key, 0, sizeof(key));
200 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700201}
202
203
204static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
205{
206 struct wpa_supplicant *wpa_s = eloop_ctx;
207 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700208 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
209 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
210 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211 bssid = wpa_s->pending_bssid;
212 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
213 MAC2STR(bssid));
214 wpa_blacklist_add(wpa_s, bssid);
215 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800216 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800218 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700219
220 /*
221 * If we timed out, the AP or the local radio may be busy.
222 * So, wait a second until scanning again.
223 */
224 wpa_supplicant_req_scan(wpa_s, 1, 0);
225}
226
227
228/**
229 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
230 * @wpa_s: Pointer to wpa_supplicant data
231 * @sec: Number of seconds after which to time out authentication
232 * @usec: Number of microseconds after which to time out authentication
233 *
234 * This function is used to schedule a timeout for the current authentication
235 * attempt.
236 */
237void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
238 int sec, int usec)
239{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700240 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700241 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
242 return;
243
244 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
245 "%d usec", sec, usec);
246 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700247 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
249}
250
251
Roshan Pius3a1667e2018-07-03 15:17:14 -0700252/*
253 * wpas_auth_timeout_restart - Restart and change timeout for authentication
254 * @wpa_s: Pointer to wpa_supplicant data
255 * @sec_diff: difference in seconds applied to original timeout value
256 */
257void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
258{
259 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
260
261 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
262 wpa_dbg(wpa_s, MSG_DEBUG,
263 "Authentication timeout restart: %d sec", new_sec);
264 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
265 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
266 wpa_s, NULL);
267 }
268}
269
270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271/**
272 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
273 * @wpa_s: Pointer to wpa_supplicant data
274 *
275 * This function is used to cancel authentication timeout scheduled with
276 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
277 * been completed.
278 */
279void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
280{
281 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
282 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
283 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700284 os_free(wpa_s->last_con_fail_realm);
285 wpa_s->last_con_fail_realm = NULL;
286 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287}
288
289
290/**
291 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
292 * @wpa_s: Pointer to wpa_supplicant data
293 *
294 * This function is used to configure EAPOL state machine based on the selected
295 * authentication mode.
296 */
297void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
298{
299#ifdef IEEE8021X_EAPOL
300 struct eapol_config eapol_conf;
301 struct wpa_ssid *ssid = wpa_s->current_ssid;
302
303#ifdef CONFIG_IBSS_RSN
304 if (ssid->mode == WPAS_MODE_IBSS &&
305 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
306 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
307 /*
308 * RSN IBSS authentication is per-STA and we can disable the
309 * per-BSSID EAPOL authentication.
310 */
311 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
312 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
313 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
314 return;
315 }
316#endif /* CONFIG_IBSS_RSN */
317
318 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
319 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
320
321 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
322 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
324 else
325 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
326
327 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
328 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
329 eapol_conf.accept_802_1x_keys = 1;
330 eapol_conf.required_keys = 0;
331 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
332 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
333 }
334 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
335 eapol_conf.required_keys |=
336 EAPOL_REQUIRE_KEY_BROADCAST;
337 }
338
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700339 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340 eapol_conf.required_keys = 0;
341 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700342 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 eapol_conf.workaround = ssid->eap_workaround;
344 eapol_conf.eap_disabled =
345 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
346 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
347 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700348 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800349
350#ifdef CONFIG_WPS
351 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
352 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
353 if (wpa_s->current_bss) {
354 struct wpabuf *ie;
355 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
356 WPS_IE_VENDOR_TYPE);
357 if (ie) {
358 if (wps_is_20(ie))
359 eapol_conf.wps |=
360 EAPOL_PEER_IS_WPS20_AP;
361 wpabuf_free(ie);
362 }
363 }
364 }
365#endif /* CONFIG_WPS */
366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700367 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700368
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800369#ifdef CONFIG_MACSEC
370 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
371 ieee802_1x_create_preshared_mka(wpa_s, ssid);
372 else
373 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
374#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800375#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700376}
377
378
379/**
380 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
381 * @wpa_s: Pointer to wpa_supplicant data
382 * @ssid: Configuration data for the network
383 *
384 * This function is used to configure WPA state machine and related parameters
385 * to a mode where WPA is not enabled. This is called as part of the
386 * authentication configuration when the selected network does not use WPA.
387 */
388void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
389 struct wpa_ssid *ssid)
390{
391 int i;
392
393 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
394 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
395 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
396 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
397 else
398 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
399 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
400 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
401 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
402 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
403 wpa_s->group_cipher = WPA_CIPHER_NONE;
404 wpa_s->mgmt_group_cipher = 0;
405
406 for (i = 0; i < NUM_WEP_KEYS; i++) {
407 if (ssid->wep_key_len[i] > 5) {
408 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
409 wpa_s->group_cipher = WPA_CIPHER_WEP104;
410 break;
411 } else if (ssid->wep_key_len[i] > 0) {
412 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
413 wpa_s->group_cipher = WPA_CIPHER_WEP40;
414 break;
415 }
416 }
417
418 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
419 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
420 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
421 wpa_s->pairwise_cipher);
422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
423#ifdef CONFIG_IEEE80211W
424 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
425 wpa_s->mgmt_group_cipher);
426#endif /* CONFIG_IEEE80211W */
427
428 pmksa_cache_clear_current(wpa_s->wpa);
429}
430
431
Dmitry Shmidt04949592012-07-19 12:16:46 -0700432void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800433{
434 int i;
435 if (wpa_s->hw.modes == NULL)
436 return;
437
438 for (i = 0; i < wpa_s->hw.num_modes; i++) {
439 os_free(wpa_s->hw.modes[i].channels);
440 os_free(wpa_s->hw.modes[i].rates);
441 }
442
443 os_free(wpa_s->hw.modes);
444 wpa_s->hw.modes = NULL;
445}
446
447
Hai Shalom74f70d42019-02-11 14:42:39 -0800448void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800449{
450 struct wpa_bss_tmp_disallowed *bss, *prev;
451
452 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
453 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700454 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800455 dl_list_del(&bss->list);
456 os_free(bss);
457 }
458}
459
460
Paul Stewart092955c2017-02-06 09:13:09 -0800461void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
462{
463 struct fils_hlp_req *req;
464
465 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
466 list)) != NULL) {
467 dl_list_del(&req->list);
468 wpabuf_free(req->pkt);
469 os_free(req);
470 }
471}
472
473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
475{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700476 int i;
477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700479 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 scard_deinit(wpa_s->scard);
481 wpa_s->scard = NULL;
482 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
483 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
484 l2_packet_deinit(wpa_s->l2);
485 wpa_s->l2 = NULL;
486 if (wpa_s->l2_br) {
487 l2_packet_deinit(wpa_s->l2_br);
488 wpa_s->l2_br = NULL;
489 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800490#ifdef CONFIG_TESTING_OPTIONS
491 l2_packet_deinit(wpa_s->l2_test);
492 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800493 os_free(wpa_s->get_pref_freq_list_override);
494 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700495 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
496 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800497#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499 if (wpa_s->conf != NULL) {
500 struct wpa_ssid *ssid;
501 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
502 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503 }
504
505 os_free(wpa_s->confname);
506 wpa_s->confname = NULL;
507
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700508 os_free(wpa_s->confanother);
509 wpa_s->confanother = NULL;
510
Hai Shalomce48b4a2018-09-05 11:41:35 -0700511 os_free(wpa_s->last_con_fail_realm);
512 wpa_s->last_con_fail_realm = NULL;
513 wpa_s->last_con_fail_realm_len = 0;
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 wpa_sm_set_eapol(wpa_s->wpa, NULL);
516 eapol_sm_deinit(wpa_s->eapol);
517 wpa_s->eapol = NULL;
518
519 rsn_preauth_deinit(wpa_s->wpa);
520
521#ifdef CONFIG_TDLS
522 wpa_tdls_deinit(wpa_s->wpa);
523#endif /* CONFIG_TDLS */
524
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800525 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526 pmksa_candidate_free(wpa_s->wpa);
527 wpa_sm_deinit(wpa_s->wpa);
528 wpa_s->wpa = NULL;
529 wpa_blacklist_clear(wpa_s);
530
531 wpa_bss_deinit(wpa_s);
532
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700533 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534 wpa_supplicant_cancel_scan(wpa_s);
535 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800536 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
537#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
538 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
539 wpa_s, NULL);
540#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700542 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544 wpas_wps_deinit(wpa_s);
545
546 wpabuf_free(wpa_s->pending_eapol_rx);
547 wpa_s->pending_eapol_rx = NULL;
548
549#ifdef CONFIG_IBSS_RSN
550 ibss_rsn_deinit(wpa_s->ibss_rsn);
551 wpa_s->ibss_rsn = NULL;
552#endif /* CONFIG_IBSS_RSN */
553
554 sme_deinit(wpa_s);
555
556#ifdef CONFIG_AP
557 wpa_supplicant_ap_deinit(wpa_s);
558#endif /* CONFIG_AP */
559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800562#ifdef CONFIG_OFFCHANNEL
563 offchannel_deinit(wpa_s);
564#endif /* CONFIG_OFFCHANNEL */
565
566 wpa_supplicant_cancel_sched_scan(wpa_s);
567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568 os_free(wpa_s->next_scan_freqs);
569 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800570
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800571 os_free(wpa_s->manual_scan_freqs);
572 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700573 os_free(wpa_s->select_network_scan_freqs);
574 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800575
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700576 os_free(wpa_s->manual_sched_scan_freqs);
577 wpa_s->manual_sched_scan_freqs = NULL;
578
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800579 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
580
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700581 /*
582 * Need to remove any pending gas-query radio work before the
583 * gas_query_deinit() call because gas_query::work has not yet been set
584 * for works that have not been started. gas_query_free() will be unable
585 * to cancel such pending radio works and once the pending gas-query
586 * radio work eventually gets removed, the deinit notification call to
587 * gas_query_start_cb() would result in dereferencing freed memory.
588 */
589 if (wpa_s->radio)
590 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800591 gas_query_deinit(wpa_s->gas);
592 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700593 gas_server_deinit(wpa_s->gas_server);
594 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800595
596 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700597
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700598 ieee802_1x_dealloc_kay_sm(wpa_s);
599
Dmitry Shmidt04949592012-07-19 12:16:46 -0700600 os_free(wpa_s->bssid_filter);
601 wpa_s->bssid_filter = NULL;
602
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800603 os_free(wpa_s->disallow_aps_bssid);
604 wpa_s->disallow_aps_bssid = NULL;
605 os_free(wpa_s->disallow_aps_ssid);
606 wpa_s->disallow_aps_ssid = NULL;
607
Dmitry Shmidt04949592012-07-19 12:16:46 -0700608 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700609#ifdef CONFIG_WNM
610 wnm_deallocate_memory(wpa_s);
611#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700612
613 ext_password_deinit(wpa_s->ext_pw);
614 wpa_s->ext_pw = NULL;
615
616 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800617 wpa_s->last_gas_resp = NULL;
618 wpabuf_free(wpa_s->prev_gas_resp);
619 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700620
621 os_free(wpa_s->last_scan_res);
622 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800623
624#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700625 if (wpa_s->drv_priv)
626 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700627 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800628#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700629
630 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
631 wpabuf_free(wpa_s->vendor_elem[i]);
632 wpa_s->vendor_elem[i] = NULL;
633 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800634
635 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800636
637 wpa_s->sched_scan_plans_num = 0;
638 os_free(wpa_s->sched_scan_plans);
639 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800640
641#ifdef CONFIG_MBO
642 wpa_s->non_pref_chan_num = 0;
643 os_free(wpa_s->non_pref_chan);
644 wpa_s->non_pref_chan = NULL;
645#endif /* CONFIG_MBO */
646
647 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700648
649 wpabuf_free(wpa_s->lci);
650 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800651 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800652
653#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
654#ifdef CONFIG_MESH
655 {
656 struct external_pmksa_cache *entry;
657
658 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
659 struct external_pmksa_cache,
660 list)) != NULL) {
661 dl_list_del(&entry->list);
662 os_free(entry->pmksa_cache);
663 os_free(entry);
664 }
665 }
666#endif /* CONFIG_MESH */
667#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
668
669 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800670
671 wpabuf_free(wpa_s->ric_ies);
672 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673
674#ifdef CONFIG_DPP
675 wpas_dpp_deinit(wpa_s);
676#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677}
678
679
680/**
681 * wpa_clear_keys - Clear keys configured for the driver
682 * @wpa_s: Pointer to wpa_supplicant data
683 * @addr: Previously used BSSID or %NULL if not available
684 *
685 * This function clears the encryption keys that has been previously configured
686 * for the driver.
687 */
688void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
689{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800690 int i, max;
691
692#ifdef CONFIG_IEEE80211W
693 max = 6;
694#else /* CONFIG_IEEE80211W */
695 max = 4;
696#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697
698 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800699 for (i = 0; i < max; i++) {
700 if (wpa_s->keys_cleared & BIT(i))
701 continue;
702 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
703 NULL, 0);
704 }
705 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
706 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
708 0);
709 /* MLME-SETPROTECTION.request(None) */
710 wpa_drv_mlme_setprotection(
711 wpa_s, addr,
712 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
713 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
714 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800715 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716}
717
718
719/**
720 * wpa_supplicant_state_txt - Get the connection state name as a text string
721 * @state: State (wpa_state; WPA_*)
722 * Returns: The state name as a printable text string
723 */
724const char * wpa_supplicant_state_txt(enum wpa_states state)
725{
726 switch (state) {
727 case WPA_DISCONNECTED:
728 return "DISCONNECTED";
729 case WPA_INACTIVE:
730 return "INACTIVE";
731 case WPA_INTERFACE_DISABLED:
732 return "INTERFACE_DISABLED";
733 case WPA_SCANNING:
734 return "SCANNING";
735 case WPA_AUTHENTICATING:
736 return "AUTHENTICATING";
737 case WPA_ASSOCIATING:
738 return "ASSOCIATING";
739 case WPA_ASSOCIATED:
740 return "ASSOCIATED";
741 case WPA_4WAY_HANDSHAKE:
742 return "4WAY_HANDSHAKE";
743 case WPA_GROUP_HANDSHAKE:
744 return "GROUP_HANDSHAKE";
745 case WPA_COMPLETED:
746 return "COMPLETED";
747 default:
748 return "UNKNOWN";
749 }
750}
751
752
753#ifdef CONFIG_BGSCAN
754
755static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
756{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800757 const char *name;
758
759 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
760 name = wpa_s->current_ssid->bgscan;
761 else
762 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800763 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800764 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800765 if (wpas_driver_bss_selection(wpa_s))
766 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
768 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800769#ifdef CONFIG_P2P
770 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
771 return;
772#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773
774 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800775 if (wpa_s->current_ssid) {
776 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
778 "bgscan");
779 /*
780 * Live without bgscan; it is only used as a roaming
781 * optimization, so the initial connection is not
782 * affected.
783 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700784 } else {
785 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700787 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
788 0);
789 if (scan_res) {
790 bgscan_notify_scan(wpa_s, scan_res);
791 wpa_scan_results_free(scan_res);
792 }
793 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700794 } else
795 wpa_s->bgscan_ssid = NULL;
796}
797
798
799static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
800{
801 if (wpa_s->bgscan_ssid != NULL) {
802 bgscan_deinit(wpa_s);
803 wpa_s->bgscan_ssid = NULL;
804 }
805}
806
807#endif /* CONFIG_BGSCAN */
808
809
Dmitry Shmidt04949592012-07-19 12:16:46 -0700810static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
811{
812 if (autoscan_init(wpa_s, 0))
813 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
814}
815
816
817static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
818{
819 autoscan_deinit(wpa_s);
820}
821
822
823void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
824{
825 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
826 wpa_s->wpa_state == WPA_SCANNING) {
827 autoscan_deinit(wpa_s);
828 wpa_supplicant_start_autoscan(wpa_s);
829 }
830}
831
832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833/**
834 * wpa_supplicant_set_state - Set current connection state
835 * @wpa_s: Pointer to wpa_supplicant data
836 * @state: The new connection state
837 *
838 * This function is called whenever the connection state changes, e.g.,
839 * association is completed for WPA/WPA2 4-Way Handshake is started.
840 */
841void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
842 enum wpa_states state)
843{
844 enum wpa_states old_state = wpa_s->wpa_state;
845
846 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
847 wpa_supplicant_state_txt(wpa_s->wpa_state),
848 wpa_supplicant_state_txt(state));
849
Hai Shalom74f70d42019-02-11 14:42:39 -0800850 if (state == WPA_COMPLETED &&
851 os_reltime_initialized(&wpa_s->roam_start)) {
852 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
853 wpa_s->roam_start.sec = 0;
854 wpa_s->roam_start.usec = 0;
855 wpas_notify_auth_changed(wpa_s);
856 wpas_notify_roam_time(wpa_s);
857 wpas_notify_roam_complete(wpa_s);
858 } else if (state == WPA_DISCONNECTED &&
859 os_reltime_initialized(&wpa_s->roam_start)) {
860 wpa_s->roam_start.sec = 0;
861 wpa_s->roam_start.usec = 0;
862 wpa_s->roam_time.sec = 0;
863 wpa_s->roam_time.usec = 0;
864 wpas_notify_roam_complete(wpa_s);
865 }
866
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800867 if (state == WPA_INTERFACE_DISABLED) {
868 /* Assure normal scan when interface is restored */
869 wpa_s->normal_scans = 0;
870 }
871
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700872 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800873 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700874 /* Reinitialize normal_scan counter */
875 wpa_s->normal_scans = 0;
876 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800877
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700878#ifdef CONFIG_P2P
879 /*
880 * P2PS client has to reply to Probe Request frames received on the
881 * group operating channel. Enable Probe Request frame reporting for
882 * P2P connected client in case p2p_cli_probe configuration property is
883 * set to 1.
884 */
885 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
886 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
887 wpa_s->current_ssid->p2p_group) {
888 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
889 wpa_dbg(wpa_s, MSG_DEBUG,
890 "P2P: Enable CLI Probe Request RX reporting");
891 wpa_s->p2p_cli_probe =
892 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
893 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
894 wpa_dbg(wpa_s, MSG_DEBUG,
895 "P2P: Disable CLI Probe Request RX reporting");
896 wpa_s->p2p_cli_probe = 0;
897 wpa_drv_probe_req_report(wpa_s, 0);
898 }
899 }
900#endif /* CONFIG_P2P */
901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902 if (state != WPA_SCANNING)
903 wpa_supplicant_notify_scanning(wpa_s, 0);
904
905 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700907 int fils_hlp_sent = 0;
908
909#ifdef CONFIG_SME
910 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
911 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
912 fils_hlp_sent = 1;
913#endif /* CONFIG_SME */
914 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
915 wpa_auth_alg_fils(wpa_s->auth_alg))
916 fils_hlp_sent = 1;
917
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700918#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700920 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800921 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700923 ssid && ssid->id_str ? ssid->id_str : "",
924 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700926 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700927 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800928 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 wpa_drv_set_operstate(wpa_s, 1);
931#ifndef IEEE8021X_EAPOL
932 wpa_drv_set_supp_port(wpa_s, 1);
933#endif /* IEEE8021X_EAPOL */
934 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700935 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700937
938 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700939
940#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
941 if (!fils_hlp_sent && ssid && ssid->eap.erp)
942 wpas_update_fils_connect_params(wpa_s);
943#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700944 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
945 state == WPA_ASSOCIATED) {
946 wpa_s->new_connection = 1;
947 wpa_drv_set_operstate(wpa_s, 0);
948#ifndef IEEE8021X_EAPOL
949 wpa_drv_set_supp_port(wpa_s, 0);
950#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700951 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700952 }
953 wpa_s->wpa_state = state;
954
955#ifdef CONFIG_BGSCAN
956 if (state == WPA_COMPLETED)
957 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800958 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959 wpa_supplicant_stop_bgscan(wpa_s);
960#endif /* CONFIG_BGSCAN */
961
Dmitry Shmidt04949592012-07-19 12:16:46 -0700962 if (state == WPA_AUTHENTICATING)
963 wpa_supplicant_stop_autoscan(wpa_s);
964
965 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
966 wpa_supplicant_start_autoscan(wpa_s);
967
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800968 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
969 wmm_ac_notify_disassoc(wpa_s);
970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 if (wpa_s->wpa_state != old_state) {
972 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
973
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700974 /*
975 * Notify the P2P Device interface about a state change in one
976 * of the interfaces.
977 */
978 wpas_p2p_indicate_state_change(wpa_s);
979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980 if (wpa_s->wpa_state == WPA_COMPLETED ||
981 old_state == WPA_COMPLETED)
982 wpas_notify_auth_changed(wpa_s);
983 }
984}
985
986
987void wpa_supplicant_terminate_proc(struct wpa_global *global)
988{
989 int pending = 0;
990#ifdef CONFIG_WPS
991 struct wpa_supplicant *wpa_s = global->ifaces;
992 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800993 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700994 if (wpas_wps_terminate_pending(wpa_s) == 1)
995 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700996#ifdef CONFIG_P2P
997 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
998 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
999 wpas_p2p_disconnect(wpa_s);
1000#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001001 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 }
1003#endif /* CONFIG_WPS */
1004 if (pending)
1005 return;
1006 eloop_terminate();
1007}
1008
1009
1010static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1011{
1012 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 wpa_supplicant_terminate_proc(global);
1014}
1015
1016
1017void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1018{
1019 enum wpa_states old_state = wpa_s->wpa_state;
1020
1021 wpa_s->pairwise_cipher = 0;
1022 wpa_s->group_cipher = 0;
1023 wpa_s->mgmt_group_cipher = 0;
1024 wpa_s->key_mgmt = 0;
1025 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001026 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027
1028 if (wpa_s->wpa_state != old_state)
1029 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1030}
1031
1032
1033/**
1034 * wpa_supplicant_reload_configuration - Reload configuration data
1035 * @wpa_s: Pointer to wpa_supplicant data
1036 * Returns: 0 on success or -1 if configuration parsing failed
1037 *
1038 * This function can be used to request that the configuration data is reloaded
1039 * (e.g., after configuration file change). This function is reloading
1040 * configuration only for one interface, so this may need to be called multiple
1041 * times if %wpa_supplicant is controlling multiple interfaces and all
1042 * interfaces need reconfiguration.
1043 */
1044int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1045{
1046 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 int reconf_ctrl;
1048 int old_ap_scan;
1049
1050 if (wpa_s->confname == NULL)
1051 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001052 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053 if (conf == NULL) {
1054 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1055 "file '%s' - exiting", wpa_s->confname);
1056 return -1;
1057 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001058 if (wpa_s->confanother &&
1059 !wpa_config_read(wpa_s->confanother, conf)) {
1060 wpa_msg(wpa_s, MSG_ERROR,
1061 "Failed to parse the configuration file '%s' - exiting",
1062 wpa_s->confanother);
1063 return -1;
1064 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 conf->changed_parameters = (unsigned int) -1;
1067
1068 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1069 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1070 os_strcmp(conf->ctrl_interface,
1071 wpa_s->conf->ctrl_interface) != 0);
1072
1073 if (reconf_ctrl && wpa_s->ctrl_iface) {
1074 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1075 wpa_s->ctrl_iface = NULL;
1076 }
1077
1078 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001079 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001080 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1081 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001082 wpa_supplicant_deauthenticate(wpa_s,
1083 WLAN_REASON_DEAUTH_LEAVING);
1084 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085
1086 /*
1087 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001088 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001090 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1091 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1092 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001093 /*
1094 * Clear forced success to clear EAP state for next
1095 * authentication.
1096 */
1097 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1098 }
1099 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1100 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001101 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1103 rsn_preauth_deinit(wpa_s->wpa);
1104
1105 old_ap_scan = wpa_s->conf->ap_scan;
1106 wpa_config_free(wpa_s->conf);
1107 wpa_s->conf = conf;
1108 if (old_ap_scan != wpa_s->conf->ap_scan)
1109 wpas_notify_ap_scan_changed(wpa_s);
1110
1111 if (reconf_ctrl)
1112 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1113
1114 wpa_supplicant_update_config(wpa_s);
1115
1116 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001117 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 wpa_s->reassociate = 1;
1119 wpa_supplicant_req_scan(wpa_s, 0, 0);
1120 }
1121 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1122 return 0;
1123}
1124
1125
1126static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1127{
1128 struct wpa_global *global = signal_ctx;
1129 struct wpa_supplicant *wpa_s;
1130 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1131 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1132 sig);
1133 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1134 wpa_supplicant_terminate_proc(global);
1135 }
1136 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001137
1138 if (wpa_debug_reopen_file() < 0) {
1139 /* Ignore errors since we cannot really do much to fix this */
1140 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1141 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142}
1143
1144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1146 struct wpa_ssid *ssid,
1147 struct wpa_ie_data *ie)
1148{
1149 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1150 if (ret) {
1151 if (ret == -2) {
1152 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1153 "from association info");
1154 }
1155 return -1;
1156 }
1157
1158 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1159 "cipher suites");
1160 if (!(ie->group_cipher & ssid->group_cipher)) {
1161 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1162 "cipher 0x%x (mask 0x%x) - reject",
1163 ie->group_cipher, ssid->group_cipher);
1164 return -1;
1165 }
1166 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1167 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1168 "cipher 0x%x (mask 0x%x) - reject",
1169 ie->pairwise_cipher, ssid->pairwise_cipher);
1170 return -1;
1171 }
1172 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1173 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1174 "management 0x%x (mask 0x%x) - reject",
1175 ie->key_mgmt, ssid->key_mgmt);
1176 return -1;
1177 }
1178
1179#ifdef CONFIG_IEEE80211W
1180 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001181 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001182 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1183 "that does not support management frame protection - "
1184 "reject");
1185 return -1;
1186 }
1187#endif /* CONFIG_IEEE80211W */
1188
1189 return 0;
1190}
1191
1192
1193/**
1194 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1195 * @wpa_s: Pointer to wpa_supplicant data
1196 * @bss: Scan results for the selected BSS, or %NULL if not available
1197 * @ssid: Configuration data for the selected network
1198 * @wpa_ie: Buffer for the WPA/RSN IE
1199 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1200 * used buffer length in case the functions returns success.
1201 * Returns: 0 on success or -1 on failure
1202 *
1203 * This function is used to configure authentication and encryption parameters
1204 * based on the network configuration and scan result for the selected BSS (if
1205 * available).
1206 */
1207int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1208 struct wpa_bss *bss, struct wpa_ssid *ssid,
1209 u8 *wpa_ie, size_t *wpa_ie_len)
1210{
1211 struct wpa_ie_data ie;
1212 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001213 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214
1215 if (bss) {
1216 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1217 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001218 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001220 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001221
1222 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1223 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1224 (ie.group_cipher & ssid->group_cipher) &&
1225 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1226 (ie.key_mgmt & ssid->key_mgmt)) {
1227 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1228 proto = WPA_PROTO_RSN;
1229 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001230 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231 (ie.group_cipher & ssid->group_cipher) &&
1232 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1233 (ie.key_mgmt & ssid->key_mgmt)) {
1234 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1235 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001236#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001237 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1238 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1239 (ie.group_cipher & ssid->group_cipher) &&
1240 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1241 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001242 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001243 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001244 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1245 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1246 (ie.group_cipher & ssid->group_cipher) &&
1247 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1248 (ie.key_mgmt & ssid->key_mgmt)) {
1249 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1250 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001251#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252 } else if (bss) {
1253 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001254 wpa_dbg(wpa_s, MSG_DEBUG,
1255 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1256 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1257 ssid->key_mgmt);
1258 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1259 MAC2STR(bss->bssid),
1260 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1261 bss_wpa ? " WPA" : "",
1262 bss_rsn ? " RSN" : "",
1263 bss_osen ? " OSEN" : "");
1264 if (bss_rsn) {
1265 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1266 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1267 wpa_dbg(wpa_s, MSG_DEBUG,
1268 "Could not parse RSN element");
1269 } else {
1270 wpa_dbg(wpa_s, MSG_DEBUG,
1271 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1272 ie.pairwise_cipher, ie.group_cipher,
1273 ie.key_mgmt);
1274 }
1275 }
1276 if (bss_wpa) {
1277 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1278 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1279 wpa_dbg(wpa_s, MSG_DEBUG,
1280 "Could not parse WPA element");
1281 } else {
1282 wpa_dbg(wpa_s, MSG_DEBUG,
1283 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1284 ie.pairwise_cipher, ie.group_cipher,
1285 ie.key_mgmt);
1286 }
1287 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288 return -1;
1289 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001290 if (ssid->proto & WPA_PROTO_OSEN)
1291 proto = WPA_PROTO_OSEN;
1292 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293 proto = WPA_PROTO_RSN;
1294 else
1295 proto = WPA_PROTO_WPA;
1296 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1297 os_memset(&ie, 0, sizeof(ie));
1298 ie.group_cipher = ssid->group_cipher;
1299 ie.pairwise_cipher = ssid->pairwise_cipher;
1300 ie.key_mgmt = ssid->key_mgmt;
1301#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302 ie.mgmt_group_cipher = 0;
1303 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1304 if (ssid->group_mgmt_cipher &
1305 WPA_CIPHER_BIP_GMAC_256)
1306 ie.mgmt_group_cipher =
1307 WPA_CIPHER_BIP_GMAC_256;
1308 else if (ssid->group_mgmt_cipher &
1309 WPA_CIPHER_BIP_CMAC_256)
1310 ie.mgmt_group_cipher =
1311 WPA_CIPHER_BIP_CMAC_256;
1312 else if (ssid->group_mgmt_cipher &
1313 WPA_CIPHER_BIP_GMAC_128)
1314 ie.mgmt_group_cipher =
1315 WPA_CIPHER_BIP_GMAC_128;
1316 else
1317 ie.mgmt_group_cipher =
1318 WPA_CIPHER_AES_128_CMAC;
1319 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320#endif /* CONFIG_IEEE80211W */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001321#ifdef CONFIG_OWE
1322 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1323 !ssid->owe_only &&
1324 !bss_wpa && !bss_rsn && !bss_osen) {
1325 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1326 wpa_s->wpa_proto = 0;
1327 *wpa_ie_len = 0;
1328 return 0;
1329 }
1330#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1332 "based on configuration");
1333 } else
1334 proto = ie.proto;
1335 }
1336
1337 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1338 "pairwise %d key_mgmt %d proto %d",
1339 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1340#ifdef CONFIG_IEEE80211W
1341 if (ssid->ieee80211w) {
1342 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1343 ie.mgmt_group_cipher);
1344 }
1345#endif /* CONFIG_IEEE80211W */
1346
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001347 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001350 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001351
1352 if (bss || !wpa_s->ap_ies_from_associnfo) {
1353 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1354 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1355 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1356 bss_rsn ? 2 + bss_rsn[1] : 0))
1357 return -1;
1358 }
1359
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001360#ifdef CONFIG_NO_WPA
1361 wpa_s->group_cipher = WPA_CIPHER_NONE;
1362 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1363#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001364 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001365 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1366 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1368 "cipher");
1369 return -1;
1370 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001371 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1372 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373
1374 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001375 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1376 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001377 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1378 "cipher");
1379 return -1;
1380 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001381 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1382 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001383#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384
1385 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001386#ifdef CONFIG_SAE
1387 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1388 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1389#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001391#ifdef CONFIG_SUITEB192
1392 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1393 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1394 wpa_dbg(wpa_s, MSG_DEBUG,
1395 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1396#endif /* CONFIG_SUITEB192 */
1397#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001398 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1399 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1400 wpa_dbg(wpa_s, MSG_DEBUG,
1401 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001402#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001403#ifdef CONFIG_FILS
1404#ifdef CONFIG_IEEE80211R
1405 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1406 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1407 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1408 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1409 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1410 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1411#endif /* CONFIG_IEEE80211R */
1412 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1413 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1414 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1415 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1416 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1417 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1418#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07001420#ifdef CONFIG_SHA384
1421 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
1422 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1423 wpa_dbg(wpa_s, MSG_DEBUG,
1424 "WPA: using KEY_MGMT FT/802.1X-SHA384");
1425 if (pmksa_cache_get_current(wpa_s->wpa)) {
1426 /* PMKSA caching with FT is not fully functional, so
1427 * disable the case for now. */
1428 wpa_dbg(wpa_s, MSG_DEBUG,
1429 "WPA: Disable PMKSA caching for FT/802.1X connection");
1430 pmksa_cache_clear_current(wpa_s->wpa);
1431 }
1432#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1434 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1435 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001436 if (pmksa_cache_get_current(wpa_s->wpa)) {
1437 /* PMKSA caching with FT is not fully functional, so
1438 * disable the case for now. */
1439 wpa_dbg(wpa_s, MSG_DEBUG,
1440 "WPA: Disable PMKSA caching for FT/802.1X connection");
1441 pmksa_cache_clear_current(wpa_s->wpa);
1442 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001443 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1444 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1445 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1446#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001447#ifdef CONFIG_SAE
1448 } else if (sel & WPA_KEY_MGMT_SAE) {
1449 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1450 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1451 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1452 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1453 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1454#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455#ifdef CONFIG_IEEE80211W
1456 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1457 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1458 wpa_dbg(wpa_s, MSG_DEBUG,
1459 "WPA: using KEY_MGMT 802.1X with SHA256");
1460 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1461 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1462 wpa_dbg(wpa_s, MSG_DEBUG,
1463 "WPA: using KEY_MGMT PSK with SHA256");
1464#endif /* CONFIG_IEEE80211W */
1465 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1466 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1467 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1468 } else if (sel & WPA_KEY_MGMT_PSK) {
1469 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1470 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1471 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1472 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1473 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001474#ifdef CONFIG_HS20
1475 } else if (sel & WPA_KEY_MGMT_OSEN) {
1476 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1477 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1478#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001479#ifdef CONFIG_OWE
1480 } else if (sel & WPA_KEY_MGMT_OWE) {
1481 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1482 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1483#endif /* CONFIG_OWE */
1484#ifdef CONFIG_DPP
1485 } else if (sel & WPA_KEY_MGMT_DPP) {
1486 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1487 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1488#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489 } else {
1490 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1491 "authenticated key management type");
1492 return -1;
1493 }
1494
1495 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1496 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1497 wpa_s->pairwise_cipher);
1498 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1499
1500#ifdef CONFIG_IEEE80211W
1501 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001502 if (ssid->group_mgmt_cipher)
1503 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001504 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1506 sel = 0;
1507 if (sel & WPA_CIPHER_AES_128_CMAC) {
1508 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1509 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1510 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001511 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1512 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1513 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1514 "BIP-GMAC-128");
1515 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1516 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1517 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1518 "BIP-GMAC-256");
1519 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1520 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1521 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1522 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001523 } else {
1524 wpa_s->mgmt_group_cipher = 0;
1525 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1526 }
1527 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1528 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001529 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001530 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531#endif /* CONFIG_IEEE80211W */
Hai Shalom74f70d42019-02-11 14:42:39 -08001532#ifdef CONFIG_OCV
1533 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1534#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535
1536 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1537 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1538 return -1;
1539 }
1540
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001541 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001542 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001543 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001544
Roshan Pius3a1667e2018-07-03 15:17:14 -07001545 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1546 WPA_KEY_MGMT_FT_PSK |
1547 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1548
1549 if (ssid->psk_set && !sae_only) {
1550 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1551 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001552 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1553 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001554 psk_set = 1;
1555 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001556
Roshan Pius3a1667e2018-07-03 15:17:14 -07001557 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1558 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001559 psk_set = 1;
1560
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001561#ifndef CONFIG_NO_PBKDF2
1562 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001563 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001564 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001565 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1566 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001567 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1568 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001569 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001570 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001571 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001572 }
1573#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001574#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001575 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001576 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1577 ssid->ext_psk);
1578 char pw_str[64 + 1];
1579 u8 psk[PMK_LEN];
1580
1581 if (pw == NULL) {
1582 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1583 "found from external storage");
1584 return -1;
1585 }
1586
1587 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1588 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1589 "PSK length %d in external storage",
1590 (int) wpabuf_len(pw));
1591 ext_password_free(pw);
1592 return -1;
1593 }
1594
1595 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1596 pw_str[wpabuf_len(pw)] = '\0';
1597
1598#ifndef CONFIG_NO_PBKDF2
1599 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1600 {
1601 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1602 4096, psk, PMK_LEN);
1603 os_memset(pw_str, 0, sizeof(pw_str));
1604 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1605 "external passphrase)",
1606 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001607 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1608 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001609 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001610 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001611 } else
1612#endif /* CONFIG_NO_PBKDF2 */
1613 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1614 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1615 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1616 "Invalid PSK hex string");
1617 os_memset(pw_str, 0, sizeof(pw_str));
1618 ext_password_free(pw);
1619 return -1;
1620 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001621 wpa_hexdump_key(MSG_MSGDUMP,
1622 "PSK (from external PSK)",
1623 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001624 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1625 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001626 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001627 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001628 } else {
1629 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1630 "PSK available");
1631 os_memset(pw_str, 0, sizeof(pw_str));
1632 ext_password_free(pw);
1633 return -1;
1634 }
1635
1636 os_memset(pw_str, 0, sizeof(pw_str));
1637 ext_password_free(pw);
1638 }
1639#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001640
1641 if (!psk_set) {
1642 wpa_msg(wpa_s, MSG_INFO,
1643 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001644 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001645 return -1;
1646 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001647#ifdef CONFIG_OWE
1648 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1649 /* OWE Diffie-Hellman exchange in (Re)Association
1650 * Request/Response frames set the PMK, so do not override it
1651 * here. */
1652#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001653 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1655
1656 return 0;
1657}
1658
1659
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001660static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1661{
1662 *pos = 0x00;
1663
1664 switch (idx) {
1665 case 0: /* Bits 0-7 */
1666 break;
1667 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001668 if (wpa_s->conf->coloc_intf_reporting) {
1669 /* Bit 13 - Collocated Interference Reporting */
1670 *pos |= 0x20;
1671 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001672 break;
1673 case 2: /* Bits 16-23 */
1674#ifdef CONFIG_WNM
1675 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1676 *pos |= 0x08; /* Bit 19 - BSS Transition */
1677#endif /* CONFIG_WNM */
1678 break;
1679 case 3: /* Bits 24-31 */
1680#ifdef CONFIG_WNM
1681 *pos |= 0x02; /* Bit 25 - SSID List */
1682#endif /* CONFIG_WNM */
1683#ifdef CONFIG_INTERWORKING
1684 if (wpa_s->conf->interworking)
1685 *pos |= 0x80; /* Bit 31 - Interworking */
1686#endif /* CONFIG_INTERWORKING */
1687 break;
1688 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001689#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001690 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001691 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001692#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001693 break;
1694 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001695#ifdef CONFIG_HS20
1696 if (wpa_s->conf->hs20)
1697 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1698#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001699#ifdef CONFIG_MBO
1700 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1701#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001702 break;
1703 case 6: /* Bits 48-55 */
1704 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001705 case 7: /* Bits 56-63 */
1706 break;
1707 case 8: /* Bits 64-71 */
1708 if (wpa_s->conf->ftm_responder)
1709 *pos |= 0x40; /* Bit 70 - FTM responder */
1710 if (wpa_s->conf->ftm_initiator)
1711 *pos |= 0x80; /* Bit 71 - FTM initiator */
1712 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001713 case 9: /* Bits 72-79 */
1714#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001715 if (!wpa_s->disable_fils)
1716 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001717#endif /* CONFIG_FILS */
1718 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001719 }
1720}
1721
1722
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001723int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001724{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001725 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001726 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001727
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001728 if (len < wpa_s->extended_capa_len)
1729 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001730 if (buflen < (size_t) len + 2) {
1731 wpa_printf(MSG_INFO,
1732 "Not enough room for building extended capabilities element");
1733 return -1;
1734 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001735
1736 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001737 *pos++ = len;
1738 for (i = 0; i < len; i++, pos++) {
1739 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001740
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001741 if (i < wpa_s->extended_capa_len) {
1742 *pos &= ~wpa_s->extended_capa_mask[i];
1743 *pos |= wpa_s->extended_capa[i];
1744 }
1745 }
1746
1747 while (len > 0 && buf[1 + len] == 0) {
1748 len--;
1749 buf[1] = len;
1750 }
1751 if (len == 0)
1752 return 0;
1753
1754 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001755}
1756
1757
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001758static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1759 struct wpa_bss *test_bss)
1760{
1761 struct wpa_bss *bss;
1762
1763 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1764 if (bss == test_bss)
1765 return 1;
1766 }
1767
1768 return 0;
1769}
1770
1771
1772static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1773 struct wpa_ssid *test_ssid)
1774{
1775 struct wpa_ssid *ssid;
1776
1777 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1778 if (ssid == test_ssid)
1779 return 1;
1780 }
1781
1782 return 0;
1783}
1784
1785
1786int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1787 struct wpa_ssid *test_ssid)
1788{
1789 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1790 return 0;
1791
1792 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1793}
1794
1795
1796void wpas_connect_work_free(struct wpa_connect_work *cwork)
1797{
1798 if (cwork == NULL)
1799 return;
1800 os_free(cwork);
1801}
1802
1803
1804void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1805{
1806 struct wpa_connect_work *cwork;
1807 struct wpa_radio_work *work = wpa_s->connect_work;
1808
1809 if (!work)
1810 return;
1811
1812 wpa_s->connect_work = NULL;
1813 cwork = work->ctx;
1814 work->ctx = NULL;
1815 wpas_connect_work_free(cwork);
1816 radio_work_done(work);
1817}
1818
1819
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001820int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1821{
1822 struct os_reltime now;
1823 u8 addr[ETH_ALEN];
1824
1825 os_get_reltime(&now);
1826 if (wpa_s->last_mac_addr_style == style &&
1827 wpa_s->last_mac_addr_change.sec != 0 &&
1828 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1829 wpa_s->conf->rand_addr_lifetime)) {
1830 wpa_msg(wpa_s, MSG_DEBUG,
1831 "Previously selected random MAC address has not yet expired");
1832 return 0;
1833 }
1834
1835 switch (style) {
1836 case 1:
1837 if (random_mac_addr(addr) < 0)
1838 return -1;
1839 break;
1840 case 2:
1841 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1842 if (random_mac_addr_keep_oui(addr) < 0)
1843 return -1;
1844 break;
1845 default:
1846 return -1;
1847 }
1848
1849 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1850 wpa_msg(wpa_s, MSG_INFO,
1851 "Failed to set random MAC address");
1852 return -1;
1853 }
1854
1855 os_get_reltime(&wpa_s->last_mac_addr_change);
1856 wpa_s->mac_addr_changed = 1;
1857 wpa_s->last_mac_addr_style = style;
1858
1859 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1860 wpa_msg(wpa_s, MSG_INFO,
1861 "Could not update MAC address information");
1862 return -1;
1863 }
1864
1865 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1866 MAC2STR(addr));
1867
1868 return 0;
1869}
1870
1871
1872int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1873{
1874 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1875 !wpa_s->conf->preassoc_mac_addr)
1876 return 0;
1877
1878 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1879}
1880
1881
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001882static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884/**
1885 * wpa_supplicant_associate - Request association
1886 * @wpa_s: Pointer to wpa_supplicant data
1887 * @bss: Scan results for the selected BSS, or %NULL if not available
1888 * @ssid: Configuration data for the selected network
1889 *
1890 * This function is used to request %wpa_supplicant to associate with a BSS.
1891 */
1892void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1893 struct wpa_bss *bss, struct wpa_ssid *ssid)
1894{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001895 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001896 int rand_style;
1897
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001898 wpa_s->own_disconnect_req = 0;
1899
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001900 /*
1901 * If we are starting a new connection, any previously pending EAPOL
1902 * RX cannot be valid anymore.
1903 */
1904 wpabuf_free(wpa_s->pending_eapol_rx);
1905 wpa_s->pending_eapol_rx = NULL;
1906
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001907 if (ssid->mac_addr == -1)
1908 rand_style = wpa_s->conf->mac_addr;
1909 else
1910 rand_style = ssid->mac_addr;
1911
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001912 wmm_ac_clear_saved_tspecs(wpa_s);
1913 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001914 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001915#ifdef CONFIG_TESTING_OPTIONS
1916 wpa_s->testing_resend_assoc = 0;
1917#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001918
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001919 if (wpa_s->last_ssid == ssid) {
1920 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001921 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001922 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1923 wmm_ac_save_tspecs(wpa_s);
1924 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001925 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
1926 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001927 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001928 }
1929
1930 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001931 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1932 return;
1933 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001934 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001935 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1936 wpa_msg(wpa_s, MSG_INFO,
1937 "Could not restore permanent MAC address");
1938 return;
1939 }
1940 wpa_s->mac_addr_changed = 0;
1941 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1942 wpa_msg(wpa_s, MSG_INFO,
1943 "Could not update MAC address information");
1944 return;
1945 }
1946 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1947 }
1948 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949
1950#ifdef CONFIG_IBSS_RSN
1951 ibss_rsn_deinit(wpa_s->ibss_rsn);
1952 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001953#else /* CONFIG_IBSS_RSN */
1954 if (ssid->mode == WPAS_MODE_IBSS &&
1955 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1956 wpa_msg(wpa_s, MSG_INFO,
1957 "IBSS RSN not supported in the build");
1958 return;
1959 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960#endif /* CONFIG_IBSS_RSN */
1961
1962 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1963 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1964#ifdef CONFIG_AP
1965 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1966 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1967 "mode");
1968 return;
1969 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001970 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1971 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001972 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1973 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001974 return;
1975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976 wpa_s->current_bss = bss;
1977#else /* CONFIG_AP */
1978 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1979 "the build");
1980#endif /* CONFIG_AP */
1981 return;
1982 }
1983
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001984 if (ssid->mode == WPAS_MODE_MESH) {
1985#ifdef CONFIG_MESH
1986 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1987 wpa_msg(wpa_s, MSG_INFO,
1988 "Driver does not support mesh mode");
1989 return;
1990 }
1991 if (bss)
1992 ssid->frequency = bss->freq;
1993 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1994 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1995 return;
1996 }
1997 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001998 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1999 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2000 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002001 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002002#else /* CONFIG_MESH */
2003 wpa_msg(wpa_s, MSG_ERROR,
2004 "mesh mode support not included in the build");
2005#endif /* CONFIG_MESH */
2006 return;
2007 }
2008
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009 /*
2010 * Set WPA state machine configuration to match the selected network now
2011 * so that the information is available before wpas_start_assoc_cb()
2012 * gets called. This is needed at least for RSN pre-authentication where
2013 * candidate APs are added to a list based on scan result processing
2014 * before completion of the first association.
2015 */
2016 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2017
2018#ifdef CONFIG_DPP
2019 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2020 return;
2021#endif /* CONFIG_DPP */
2022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023#ifdef CONFIG_TDLS
2024 if (bss)
2025 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2026 bss->ie_len);
2027#endif /* CONFIG_TDLS */
2028
2029 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2030 ssid->mode == IEEE80211_MODE_INFRA) {
2031 sme_authenticate(wpa_s, bss, ssid);
2032 return;
2033 }
2034
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002035 if (wpa_s->connect_work) {
2036 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2037 return;
2038 }
2039
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002040 if (radio_work_pending(wpa_s, "connect")) {
2041 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2042 return;
2043 }
2044
Dmitry Shmidt29333592017-01-09 12:27:11 -08002045#ifdef CONFIG_SME
2046 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2047 /* Clear possibly set auth_alg, if any, from last attempt. */
2048 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2049 }
2050#endif /* CONFIG_SME */
2051
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002052 wpas_abort_ongoing_scan(wpa_s);
2053
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002054 cwork = os_zalloc(sizeof(*cwork));
2055 if (cwork == NULL)
2056 return;
2057
2058 cwork->bss = bss;
2059 cwork->ssid = ssid;
2060
2061 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2062 wpas_start_assoc_cb, cwork) < 0) {
2063 os_free(cwork);
2064 }
2065}
2066
2067
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002068static int bss_is_ibss(struct wpa_bss *bss)
2069{
2070 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2071 IEEE80211_CAP_IBSS;
2072}
2073
2074
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002075static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2076 const struct wpa_ssid *ssid)
2077{
2078 enum hostapd_hw_mode hw_mode;
2079 struct hostapd_hw_modes *mode = NULL;
2080 u8 channel;
2081 int i;
2082
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002083 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2084 if (hw_mode == NUM_HOSTAPD_MODES)
2085 return 0;
2086 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2087 if (wpa_s->hw.modes[i].mode == hw_mode) {
2088 mode = &wpa_s->hw.modes[i];
2089 break;
2090 }
2091 }
2092
2093 if (!mode)
2094 return 0;
2095
2096 return mode->vht_capab != 0;
2097}
2098
2099
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002100void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2101 const struct wpa_ssid *ssid,
2102 struct hostapd_freq_params *freq)
2103{
2104 enum hostapd_hw_mode hw_mode;
2105 struct hostapd_hw_modes *mode = NULL;
2106 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2107 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002108 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002109 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2110 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002111 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002112 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002113 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002114 int chwidth, seg0, seg1;
2115 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002116
2117 freq->freq = ssid->frequency;
2118
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002119 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2120 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2121
2122 if (ssid->mode != WPAS_MODE_IBSS)
2123 break;
2124
2125 /* Don't adjust control freq in case of fixed_freq */
2126 if (ssid->fixed_freq)
2127 break;
2128
2129 if (!bss_is_ibss(bss))
2130 continue;
2131
2132 if (ssid->ssid_len == bss->ssid_len &&
2133 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2134 wpa_printf(MSG_DEBUG,
2135 "IBSS already found in scan results, adjust control freq: %d",
2136 bss->freq);
2137 freq->freq = bss->freq;
2138 obss_scan = 0;
2139 break;
2140 }
2141 }
2142
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002143 /* For IBSS check HT_IBSS flag */
2144 if (ssid->mode == WPAS_MODE_IBSS &&
2145 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2146 return;
2147
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002148 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2149 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2150 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2151 wpa_printf(MSG_DEBUG,
2152 "IBSS: WEP/TKIP detected, do not try to enable HT");
2153 return;
2154 }
2155
2156 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002157 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2158 if (wpa_s->hw.modes[i].mode == hw_mode) {
2159 mode = &wpa_s->hw.modes[i];
2160 break;
2161 }
2162 }
2163
2164 if (!mode)
2165 return;
2166
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002167#ifdef CONFIG_HT_OVERRIDES
2168 if (ssid->disable_ht) {
2169 freq->ht_enabled = 0;
2170 return;
2171 }
2172#endif /* CONFIG_HT_OVERRIDES */
2173
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002174 freq->ht_enabled = ht_supported(mode);
2175 if (!freq->ht_enabled)
2176 return;
2177
2178 /* Setup higher BW only for 5 GHz */
2179 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2180 return;
2181
2182 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2183 pri_chan = &mode->channels[chan_idx];
2184 if (pri_chan->chan == channel)
2185 break;
2186 pri_chan = NULL;
2187 }
2188 if (!pri_chan)
2189 return;
2190
2191 /* Check primary channel flags */
2192 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2193 return;
2194
Hai Shalom74f70d42019-02-11 14:42:39 -08002195 freq->channel = pri_chan->chan;
2196
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002197#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002198 if (ssid->disable_ht40) {
2199 if (ssid->disable_vht)
2200 return;
2201 goto skip_ht40;
2202 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002203#endif /* CONFIG_HT_OVERRIDES */
2204
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002205 /* Check/setup HT40+/HT40- */
2206 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2207 if (ht40plus[j] == channel) {
2208 ht40 = 1;
2209 break;
2210 }
2211 }
2212
2213 /* Find secondary channel */
2214 for (i = 0; i < mode->num_channels; i++) {
2215 sec_chan = &mode->channels[i];
2216 if (sec_chan->chan == channel + ht40 * 4)
2217 break;
2218 sec_chan = NULL;
2219 }
2220 if (!sec_chan)
2221 return;
2222
2223 /* Check secondary channel flags */
2224 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2225 return;
2226
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002227 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002228 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2229 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002230 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002231 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2232 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002233 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002234 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002235
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002236 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002237 struct wpa_scan_results *scan_res;
2238
2239 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2240 if (scan_res == NULL) {
2241 /* Back to HT20 */
2242 freq->sec_channel_offset = 0;
2243 return;
2244 }
2245
2246 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2247 sec_chan->chan);
2248 switch (res) {
2249 case 0:
2250 /* Back to HT20 */
2251 freq->sec_channel_offset = 0;
2252 break;
2253 case 1:
2254 /* Configuration allowed */
2255 break;
2256 case 2:
2257 /* Switch pri/sec channels */
2258 freq->freq = hw_get_freq(mode, sec_chan->chan);
2259 freq->sec_channel_offset = -freq->sec_channel_offset;
2260 freq->channel = sec_chan->chan;
2261 break;
2262 default:
2263 freq->sec_channel_offset = 0;
2264 break;
2265 }
2266
2267 wpa_scan_results_free(scan_res);
2268 }
2269
Hai Shalom74f70d42019-02-11 14:42:39 -08002270#ifdef CONFIG_HT_OVERRIDES
2271skip_ht40:
2272#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002273 wpa_printf(MSG_DEBUG,
2274 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2275 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002276
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002277 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002278 return;
2279
2280 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002281 if (ssid->mode == WPAS_MODE_IBSS &&
2282 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002283 return;
2284
2285 vht_freq = *freq;
2286
Paul Stewart092955c2017-02-06 09:13:09 -08002287#ifdef CONFIG_VHT_OVERRIDES
2288 if (ssid->disable_vht) {
2289 freq->vht_enabled = 0;
2290 return;
2291 }
2292#endif /* CONFIG_VHT_OVERRIDES */
2293
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002294 vht_freq.vht_enabled = vht_supported(mode);
2295 if (!vht_freq.vht_enabled)
2296 return;
2297
2298 /* setup center_freq1, bandwidth */
2299 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2300 if (freq->channel >= vht80[j] &&
2301 freq->channel < vht80[j] + 16)
2302 break;
2303 }
2304
2305 if (j == ARRAY_SIZE(vht80))
2306 return;
2307
2308 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2309 struct hostapd_channel_data *chan;
2310
2311 chan = hw_get_channel_chan(mode, i, NULL);
2312 if (!chan)
2313 return;
2314
2315 /* Back to HT configuration if channel not usable */
2316 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2317 return;
2318 }
2319
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002320 chwidth = VHT_CHANWIDTH_80MHZ;
2321 seg0 = vht80[j] + 6;
2322 seg1 = 0;
2323
2324 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2325 /* setup center_freq2, bandwidth */
2326 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2327 /* Only accept 80 MHz segments separated by a gap */
2328 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2329 continue;
2330 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2331 struct hostapd_channel_data *chan;
2332
2333 chan = hw_get_channel_chan(mode, i, NULL);
2334 if (!chan)
2335 continue;
2336
2337 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2338 HOSTAPD_CHAN_NO_IR |
2339 HOSTAPD_CHAN_RADAR))
2340 continue;
2341
2342 /* Found a suitable second segment for 80+80 */
2343 chwidth = VHT_CHANWIDTH_80P80MHZ;
2344 vht_caps |=
2345 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2346 seg1 = vht80[k] + 6;
2347 }
2348
2349 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2350 break;
2351 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002352 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2353 if (freq->freq == 5180) {
2354 chwidth = VHT_CHANWIDTH_160MHZ;
2355 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2356 seg0 = 50;
2357 } else if (freq->freq == 5520) {
2358 chwidth = VHT_CHANWIDTH_160MHZ;
2359 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2360 seg0 = 114;
2361 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002362 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_USE_HT) {
2363 chwidth = VHT_CHANWIDTH_USE_HT;
2364 seg0 = vht80[j] + 2;
2365#ifdef CONFIG_HT_OVERRIDES
2366 if (ssid->disable_ht40)
2367 seg0 = 0;
2368#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002369 }
2370
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002371 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2372 freq->channel, freq->ht_enabled,
2373 vht_freq.vht_enabled,
2374 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002375 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002376 return;
2377
2378 *freq = vht_freq;
2379
2380 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2381 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002382}
2383
2384
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002385#ifdef CONFIG_FILS
2386static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2387 size_t ie_buf_len)
2388{
2389 struct fils_hlp_req *req;
2390 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2391 const u8 *pos;
2392 u8 *buf = ie_buf;
2393
2394 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2395 list) {
2396 rem_len = ie_buf_len - ie_len;
2397 pos = wpabuf_head(req->pkt);
2398 hdr_len = 1 + 2 * ETH_ALEN + 6;
2399 hlp_len = wpabuf_len(req->pkt);
2400
2401 if (rem_len < 2 + hdr_len + hlp_len) {
2402 wpa_printf(MSG_ERROR,
2403 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2404 (unsigned long) rem_len,
2405 (unsigned long) (2 + hdr_len + hlp_len));
2406 break;
2407 }
2408
2409 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2410 /* Element ID */
2411 *buf++ = WLAN_EID_EXTENSION;
2412 /* Length */
2413 *buf++ = len;
2414 /* Element ID Extension */
2415 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2416 /* Destination MAC address */
2417 os_memcpy(buf, req->dst, ETH_ALEN);
2418 buf += ETH_ALEN;
2419 /* Source MAC address */
2420 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2421 buf += ETH_ALEN;
2422 /* LLC/SNAP Header */
2423 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2424 buf += 6;
2425 /* HLP Packet */
2426 os_memcpy(buf, pos, len - hdr_len);
2427 buf += len - hdr_len;
2428 pos += len - hdr_len;
2429
2430 hlp_len -= len - hdr_len;
2431 ie_len += 2 + len;
2432 rem_len -= 2 + len;
2433
2434 while (hlp_len) {
2435 len = (hlp_len > 255) ? 255 : hlp_len;
2436 if (rem_len < 2 + len)
2437 break;
2438 *buf++ = WLAN_EID_FRAGMENT;
2439 *buf++ = len;
2440 os_memcpy(buf, pos, len);
2441 buf += len;
2442 pos += len;
2443
2444 hlp_len -= len;
2445 ie_len += 2 + len;
2446 rem_len -= 2 + len;
2447 }
2448 }
2449
2450 return ie_len;
2451}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002452
2453
2454int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2455{
2456 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2457 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2458 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2459 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2460}
2461
2462
2463int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2464{
2465#ifdef CONFIG_FILS_SK_PFS
2466 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2467 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2468#else /* CONFIG_FILS_SK_PFS */
2469 return 0;
2470#endif /* CONFIG_FILS_SK_PFS */
2471}
2472
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002473#endif /* CONFIG_FILS */
2474
2475
2476static u8 * wpas_populate_assoc_ies(
2477 struct wpa_supplicant *wpa_s,
2478 struct wpa_bss *bss, struct wpa_ssid *ssid,
2479 struct wpa_driver_associate_params *params,
2480 enum wpa_drv_update_connect_params_mask *mask)
2481{
2482 u8 *wpa_ie;
2483 size_t max_wpa_ie_len = 500;
2484 size_t wpa_ie_len;
2485 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002486#ifdef CONFIG_MBO
2487 const u8 *mbo_ie;
2488#endif
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002489#ifdef CONFIG_FILS
2490 const u8 *realm, *username, *rrk;
2491 size_t realm_len, username_len, rrk_len;
2492 u16 next_seq_num;
2493 struct fils_hlp_req *req;
2494
2495 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2496 list) {
2497 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2498 2 + 2 * wpabuf_len(req->pkt) / 255;
2499 }
2500#endif /* CONFIG_FILS */
2501
2502 wpa_ie = os_malloc(max_wpa_ie_len);
2503 if (!wpa_ie) {
2504 wpa_printf(MSG_ERROR,
2505 "Failed to allocate connect IE buffer for %lu bytes",
2506 (unsigned long) max_wpa_ie_len);
2507 return NULL;
2508 }
2509
2510 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2511 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2512 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2513 int try_opportunistic;
2514 const u8 *cache_id = NULL;
2515
2516 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2517 wpa_s->conf->okc :
2518 ssid->proactive_key_caching) &&
2519 (ssid->proto & WPA_PROTO_RSN);
2520#ifdef CONFIG_FILS
2521 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2522 cache_id = wpa_bss_get_fils_cache_id(bss);
2523#endif /* CONFIG_FILS */
2524 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2525 ssid, try_opportunistic,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002526 cache_id, 0) == 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002527 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
2528 wpa_ie_len = max_wpa_ie_len;
2529 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2530 wpa_ie, &wpa_ie_len)) {
2531 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2532 "key management and encryption suites");
2533 os_free(wpa_ie);
2534 return NULL;
2535 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002536#ifdef CONFIG_HS20
2537 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2538 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2539 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2540 wpa_ie_len = max_wpa_ie_len;
2541 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2542 wpa_ie, &wpa_ie_len)) {
2543 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2544 "key management and encryption suites");
2545 os_free(wpa_ie);
2546 return NULL;
2547 }
2548#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002549 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2550 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2551 /*
2552 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2553 * use non-WPA since the scan results did not indicate that the
2554 * AP is using WPA or WPA2.
2555 */
2556 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2557 wpa_ie_len = 0;
2558 wpa_s->wpa_proto = 0;
2559 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2560 wpa_ie_len = max_wpa_ie_len;
2561 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2562 wpa_ie, &wpa_ie_len)) {
2563 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2564 "key management and encryption suites (no "
2565 "scan results)");
2566 os_free(wpa_ie);
2567 return NULL;
2568 }
2569#ifdef CONFIG_WPS
2570 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2571 struct wpabuf *wps_ie;
2572 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2573 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2574 wpa_ie_len = wpabuf_len(wps_ie);
2575 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2576 } else
2577 wpa_ie_len = 0;
2578 wpabuf_free(wps_ie);
2579 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2580 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2581 params->wps = WPS_MODE_PRIVACY;
2582 else
2583 params->wps = WPS_MODE_OPEN;
2584 wpa_s->wpa_proto = 0;
2585#endif /* CONFIG_WPS */
2586 } else {
2587 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2588 wpa_ie_len = 0;
2589 wpa_s->wpa_proto = 0;
2590 }
2591
2592#ifdef IEEE8021X_EAPOL
2593 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2594 if (ssid->leap) {
2595 if (ssid->non_leap == 0)
2596 algs = WPA_AUTH_ALG_LEAP;
2597 else
2598 algs |= WPA_AUTH_ALG_LEAP;
2599 }
2600 }
2601
2602#ifdef CONFIG_FILS
2603 /* Clear FILS association */
2604 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2605
2606 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2607 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2608 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2609 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002610 &next_seq_num, &rrk, &rrk_len) == 0 &&
2611 (!wpa_s->last_con_fail_realm ||
2612 wpa_s->last_con_fail_realm_len != realm_len ||
2613 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002614 algs = WPA_AUTH_ALG_FILS;
2615 params->fils_erp_username = username;
2616 params->fils_erp_username_len = username_len;
2617 params->fils_erp_realm = realm;
2618 params->fils_erp_realm_len = realm_len;
2619 params->fils_erp_next_seq_num = next_seq_num;
2620 params->fils_erp_rrk = rrk;
2621 params->fils_erp_rrk_len = rrk_len;
2622
2623 if (mask)
2624 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2625 }
2626#endif /* CONFIG_FILS */
2627#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002628#ifdef CONFIG_SAE
2629 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2630 algs = WPA_AUTH_ALG_SAE;
2631#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002632
2633 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2634 if (ssid->auth_alg) {
2635 algs = ssid->auth_alg;
2636 wpa_dbg(wpa_s, MSG_DEBUG,
2637 "Overriding auth_alg selection: 0x%x", algs);
2638 }
2639
2640#ifdef CONFIG_P2P
2641 if (wpa_s->global->p2p) {
2642 u8 *pos;
2643 size_t len;
2644 int res;
2645 pos = wpa_ie + wpa_ie_len;
2646 len = max_wpa_ie_len - wpa_ie_len;
2647 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2648 ssid->p2p_group);
2649 if (res >= 0)
2650 wpa_ie_len += res;
2651 }
2652
2653 wpa_s->cross_connect_disallowed = 0;
2654 if (bss) {
2655 struct wpabuf *p2p;
2656 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2657 if (p2p) {
2658 wpa_s->cross_connect_disallowed =
2659 p2p_get_cross_connect_disallowed(p2p);
2660 wpabuf_free(p2p);
2661 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2662 "connection",
2663 wpa_s->cross_connect_disallowed ?
2664 "disallows" : "allows");
2665 }
2666 }
2667
2668 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2669#endif /* CONFIG_P2P */
2670
2671 if (bss) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002672 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002673 wpa_ie + wpa_ie_len,
2674 max_wpa_ie_len -
2675 wpa_ie_len);
2676 }
2677
2678 /*
2679 * Workaround: Add Extended Capabilities element only if the AP
2680 * included this element in Beacon/Probe Response frames. Some older
2681 * APs seem to have interoperability issues if this element is
2682 * included, so while the standard may require us to include the
2683 * element in all cases, it is justifiable to skip it to avoid
2684 * interoperability issues.
2685 */
2686 if (ssid->p2p_group)
2687 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2688 else
2689 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2690
2691 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2692 u8 ext_capab[18];
2693 int ext_capab_len;
2694 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2695 sizeof(ext_capab));
2696 if (ext_capab_len > 0 &&
2697 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2698 u8 *pos = wpa_ie;
2699 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2700 pos += 2 + pos[1];
2701 os_memmove(pos + ext_capab_len, pos,
2702 wpa_ie_len - (pos - wpa_ie));
2703 wpa_ie_len += ext_capab_len;
2704 os_memcpy(pos, ext_capab, ext_capab_len);
2705 }
2706 }
2707
2708#ifdef CONFIG_HS20
2709 if (is_hs20_network(wpa_s, ssid, bss)) {
2710 struct wpabuf *hs20;
2711
Roshan Pius3a1667e2018-07-03 15:17:14 -07002712 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002713 if (hs20) {
2714 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2715 size_t len;
2716
Hai Shalom74f70d42019-02-11 14:42:39 -08002717 wpas_hs20_add_indication(hs20, pps_mo_id,
2718 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002719 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002720 len = max_wpa_ie_len - wpa_ie_len;
2721 if (wpabuf_len(hs20) <= len) {
2722 os_memcpy(wpa_ie + wpa_ie_len,
2723 wpabuf_head(hs20), wpabuf_len(hs20));
2724 wpa_ie_len += wpabuf_len(hs20);
2725 }
2726 wpabuf_free(hs20);
2727
2728 hs20_configure_frame_filters(wpa_s);
2729 }
2730 }
2731#endif /* CONFIG_HS20 */
2732
2733 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2734 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2735 size_t len;
2736
2737 len = max_wpa_ie_len - wpa_ie_len;
2738 if (wpabuf_len(buf) <= len) {
2739 os_memcpy(wpa_ie + wpa_ie_len,
2740 wpabuf_head(buf), wpabuf_len(buf));
2741 wpa_ie_len += wpabuf_len(buf);
2742 }
2743 }
2744
2745#ifdef CONFIG_FST
2746 if (wpa_s->fst_ies) {
2747 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2748
2749 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2750 os_memcpy(wpa_ie + wpa_ie_len,
2751 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2752 wpa_ie_len += fst_ies_len;
2753 }
2754 }
2755#endif /* CONFIG_FST */
2756
2757#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002758 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
2759 if (mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002760 int len;
2761
2762 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002763 max_wpa_ie_len - wpa_ie_len,
2764 !!mbo_attr_from_mbo_ie(mbo_ie,
2765 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002766 if (len >= 0)
2767 wpa_ie_len += len;
2768 }
2769#endif /* CONFIG_MBO */
2770
2771#ifdef CONFIG_FILS
2772 if (algs == WPA_AUTH_ALG_FILS) {
2773 size_t len;
2774
2775 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2776 max_wpa_ie_len - wpa_ie_len);
2777 wpa_ie_len += len;
2778 }
2779#endif /* CONFIG_FILS */
2780
2781#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002782#ifdef CONFIG_TESTING_OPTIONS
2783 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2784 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2785 } else
2786#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002787 if (algs == WPA_AUTH_ALG_OPEN &&
2788 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2789 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002790 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002791
Roshan Pius3a1667e2018-07-03 15:17:14 -07002792 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002793 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002794 } else if (wpa_s->assoc_status_code ==
2795 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002796 if (wpa_s->last_owe_group == 19)
2797 group = 20;
2798 else if (wpa_s->last_owe_group == 20)
2799 group = 21;
2800 else
2801 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002802 } else {
2803 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002804 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002805
Roshan Pius3a1667e2018-07-03 15:17:14 -07002806 wpa_s->last_owe_group = group;
2807 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002808 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2809 if (owe_ie &&
2810 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2811 os_memcpy(wpa_ie + wpa_ie_len,
2812 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2813 wpa_ie_len += wpabuf_len(owe_ie);
2814 wpabuf_free(owe_ie);
2815 }
2816 }
2817#endif /* CONFIG_OWE */
2818
Roshan Pius3a1667e2018-07-03 15:17:14 -07002819#ifdef CONFIG_IEEE80211R
2820 /*
2821 * Add MDIE under these conditions: the network profile allows FT,
2822 * the AP supports FT, and the mobility domain ID matches.
2823 */
2824 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2825 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2826
2827 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2828 size_t len = 0;
2829 const u8 *md = mdie + 2;
2830 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2831
2832 if (os_memcmp(md, wpa_md,
2833 MOBILITY_DOMAIN_ID_LEN) == 0) {
2834 /* Add mobility domain IE */
2835 len = wpa_ft_add_mdie(
2836 wpa_s->wpa, wpa_ie + wpa_ie_len,
2837 max_wpa_ie_len - wpa_ie_len, mdie);
2838 wpa_ie_len += len;
2839 }
2840#ifdef CONFIG_SME
2841 if (len > 0 && wpa_s->sme.ft_used &&
2842 wpa_sm_has_ptk(wpa_s->wpa)) {
2843 wpa_dbg(wpa_s, MSG_DEBUG,
2844 "SME: Trying to use FT over-the-air");
2845 algs |= WPA_AUTH_ALG_FT;
2846 }
2847#endif /* CONFIG_SME */
2848 }
2849 }
2850#endif /* CONFIG_IEEE80211R */
2851
Hai Shalom74f70d42019-02-11 14:42:39 -08002852 if (ssid->multi_ap_backhaul_sta) {
2853 size_t multi_ap_ie_len;
2854
2855 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
2856 max_wpa_ie_len - wpa_ie_len,
2857 MULTI_AP_BACKHAUL_STA);
2858 if (multi_ap_ie_len == 0) {
2859 wpa_printf(MSG_ERROR,
2860 "Multi-AP: Failed to build Multi-AP IE");
2861 os_free(wpa_ie);
2862 return NULL;
2863 }
2864 wpa_ie_len += multi_ap_ie_len;
2865 }
2866
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002867 params->wpa_ie = wpa_ie;
2868 params->wpa_ie_len = wpa_ie_len;
2869 params->auth_alg = algs;
2870 if (mask)
2871 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2872
2873 return wpa_ie;
2874}
2875
2876
2877#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2878static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2879{
2880 struct wpa_driver_associate_params params;
2881 enum wpa_drv_update_connect_params_mask mask = 0;
2882 u8 *wpa_ie;
2883
2884 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2885 return; /* nothing to do */
2886
2887 os_memset(&params, 0, sizeof(params));
2888 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2889 wpa_s->current_ssid, &params, &mask);
2890 if (!wpa_ie)
2891 return;
2892
2893 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2894 os_free(wpa_ie);
2895 return;
2896 }
2897
2898 wpa_s->auth_alg = params.auth_alg;
2899 wpa_drv_update_connect_params(wpa_s, &params, mask);
2900 os_free(wpa_ie);
2901}
2902#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2903
2904
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002905static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2906{
2907 struct wpa_connect_work *cwork = work->ctx;
2908 struct wpa_bss *bss = cwork->bss;
2909 struct wpa_ssid *ssid = cwork->ssid;
2910 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002911 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002912 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002913 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002914 struct wpa_driver_associate_params params;
2915 int wep_keys_set = 0;
2916 int assoc_failed = 0;
2917 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002918 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002919#ifdef CONFIG_HT_OVERRIDES
2920 struct ieee80211_ht_capabilities htcaps;
2921 struct ieee80211_ht_capabilities htcaps_mask;
2922#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002923#ifdef CONFIG_VHT_OVERRIDES
2924 struct ieee80211_vht_capabilities vhtcaps;
2925 struct ieee80211_vht_capabilities vhtcaps_mask;
2926#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002927
2928 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002929 if (work->started) {
2930 wpa_s->connect_work = NULL;
2931
2932 /* cancel possible auth. timeout */
2933 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2934 NULL);
2935 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002936 wpas_connect_work_free(cwork);
2937 return;
2938 }
2939
2940 wpa_s->connect_work = work;
2941
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002942 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2943 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002944 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2945 wpas_connect_work_done(wpa_s);
2946 return;
2947 }
2948
Dmitry Shmidte4663042016-04-04 10:07:49 -07002949 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002950 os_memset(&params, 0, sizeof(params));
2951 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002952 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002953 if (bss &&
2954 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955#ifdef CONFIG_IEEE80211R
2956 const u8 *ie, *md = NULL;
2957#endif /* CONFIG_IEEE80211R */
2958 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2959 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2960 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2961 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2962 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2963 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2964 if (bssid_changed)
2965 wpas_notify_bssid_changed(wpa_s);
2966#ifdef CONFIG_IEEE80211R
2967 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2968 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2969 md = ie + 2;
2970 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2971 if (md) {
2972 /* Prepare for the next transition */
2973 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2974 }
2975#endif /* CONFIG_IEEE80211R */
2976#ifdef CONFIG_WPS
2977 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2978 wpa_s->conf->ap_scan == 2 &&
2979 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2980 /* Use ap_scan==1 style network selection to find the network
2981 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002982 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002983 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 wpa_s->reassociate = 1;
2985 wpa_supplicant_req_scan(wpa_s, 0, 0);
2986 return;
2987#endif /* CONFIG_WPS */
2988 } else {
2989 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2990 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002991 if (bss)
2992 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2993 else
2994 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002996 if (!wpa_s->pno)
2997 wpa_supplicant_cancel_sched_scan(wpa_s);
2998
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999 wpa_supplicant_cancel_scan(wpa_s);
3000
3001 /* Starting new association, so clear the possibly used WPA IE from the
3002 * previous association. */
3003 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3004
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003005 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3006 if (!wpa_ie) {
3007 wpas_connect_work_done(wpa_s);
3008 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003009 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003010
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3012 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003013 cipher_pairwise = wpa_s->pairwise_cipher;
3014 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003015 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3017 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3018 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3019 use_crypt = 0;
3020 if (wpa_set_wep_keys(wpa_s, ssid)) {
3021 use_crypt = 1;
3022 wep_keys_set = 1;
3023 }
3024 }
3025 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3026 use_crypt = 0;
3027
3028#ifdef IEEE8021X_EAPOL
3029 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3030 if ((ssid->eapol_flags &
3031 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3032 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3033 !wep_keys_set) {
3034 use_crypt = 0;
3035 } else {
3036 /* Assume that dynamic WEP-104 keys will be used and
3037 * set cipher suites in order for drivers to expect
3038 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003039 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003040 }
3041 }
3042#endif /* IEEE8021X_EAPOL */
3043
3044 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3045 /* Set the key before (and later after) association */
3046 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3047 }
3048
3049 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3050 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 params.ssid = bss->ssid;
3052 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003053 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3054 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003055 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3056 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003057 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003058 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003059 ssid->bssid_set,
3060 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003061 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003062 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003063 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003064 params.bssid_hint = bss->bssid;
3065 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003066 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003068 if (ssid->bssid_hint_set)
3069 params.bssid_hint = ssid->bssid_hint;
3070
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003071 params.ssid = ssid->ssid;
3072 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003073 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003075
3076 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3077 wpa_s->conf->ap_scan == 2) {
3078 params.bssid = ssid->bssid;
3079 params.fixed_bssid = 1;
3080 }
3081
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003082 /* Initial frequency for IBSS/mesh */
3083 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003084 ssid->frequency > 0 && params.freq.freq == 0)
3085 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003086
3087 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003088 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003089 if (ssid->beacon_int)
3090 params.beacon_int = ssid->beacon_int;
3091 else
3092 params.beacon_int = wpa_s->conf->beacon_int;
3093 }
3094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003095 params.pairwise_suite = cipher_pairwise;
3096 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003097 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003098 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003099 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003100 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003101 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003102 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103 for (i = 0; i < NUM_WEP_KEYS; i++) {
3104 if (ssid->wep_key_len[i])
3105 params.wep_key[i] = ssid->wep_key[i];
3106 params.wep_key_len[i] = ssid->wep_key_len[i];
3107 }
3108 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3109
Hai Shalom74f70d42019-02-11 14:42:39 -08003110 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003111 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3112 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003113 params.passphrase = ssid->passphrase;
3114 if (ssid->psk_set)
3115 params.psk = ssid->psk;
3116 }
3117
Hai Shalom74f70d42019-02-11 14:42:39 -08003118 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3119 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3120 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3121 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3122 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
3123 params.req_key_mgmt_offload = 1;
3124
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003125 if (wpa_s->conf->key_mgmt_offload) {
3126 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3127 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003128 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3129 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003130 params.req_key_mgmt_offload =
3131 ssid->proactive_key_caching < 0 ?
3132 wpa_s->conf->okc : ssid->proactive_key_caching;
3133 else
3134 params.req_key_mgmt_offload = 1;
3135
3136 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3137 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3138 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3139 ssid->psk_set)
3140 params.psk = ssid->psk;
3141 }
3142
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003143 params.drop_unencrypted = use_crypt;
3144
3145#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003146 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003147 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003148 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3149 struct wpa_ie_data ie;
3150 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3151 ie.capabilities &
3152 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3153 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3154 "MFP: require MFP");
3155 params.mgmt_frame_protection =
3156 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003157#ifdef CONFIG_OWE
3158 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3159 !ssid->owe_only) {
3160 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3161#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003162 }
3163 }
3164#endif /* CONFIG_IEEE80211W */
3165
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003166 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003167
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003168 if (wpa_s->p2pdev->set_sta_uapsd)
3169 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170 else
3171 params.uapsd = -1;
3172
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003173#ifdef CONFIG_HT_OVERRIDES
3174 os_memset(&htcaps, 0, sizeof(htcaps));
3175 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3176 params.htcaps = (u8 *) &htcaps;
3177 params.htcaps_mask = (u8 *) &htcaps_mask;
3178 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3179#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003180#ifdef CONFIG_VHT_OVERRIDES
3181 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3182 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3183 params.vhtcaps = &vhtcaps;
3184 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003185 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003186#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003187
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003188#ifdef CONFIG_P2P
3189 /*
3190 * If multi-channel concurrency is not supported, check for any
3191 * frequency conflict. In case of any frequency conflict, remove the
3192 * least prioritized connection.
3193 */
3194 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003195 int freq, num;
3196 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003197 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003198 wpa_printf(MSG_DEBUG,
3199 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003200 freq, params.freq.freq);
3201 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003202 wpa_s, params.freq.freq, ssid) < 0) {
3203 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003204 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003205 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003206 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003207 }
3208 }
3209#endif /* CONFIG_P2P */
3210
Dmitry Shmidte4663042016-04-04 10:07:49 -07003211 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3212 wpa_s->current_ssid)
3213 params.prev_bssid = prev_bssid;
3214
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003215 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003216 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 if (ret < 0) {
3218 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3219 "failed");
3220 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3221 /*
3222 * The driver is known to mean what is saying, so we
3223 * can stop right here; the association will not
3224 * succeed.
3225 */
3226 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003227 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3229 return;
3230 }
3231 /* try to continue anyway; new association will be tried again
3232 * after timeout */
3233 assoc_failed = 1;
3234 }
3235
3236 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3237 /* Set the key after the association just in case association
3238 * cleared the previously configured key. */
3239 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3240 /* No need to timeout authentication since there is no key
3241 * management. */
3242 wpa_supplicant_cancel_auth_timeout(wpa_s);
3243 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3244#ifdef CONFIG_IBSS_RSN
3245 } else if (ssid->mode == WPAS_MODE_IBSS &&
3246 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3247 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3248 /*
3249 * RSN IBSS authentication is per-STA and we can disable the
3250 * per-BSSID authentication.
3251 */
3252 wpa_supplicant_cancel_auth_timeout(wpa_s);
3253#endif /* CONFIG_IBSS_RSN */
3254 } else {
3255 /* Timeout for IEEE 802.11 authentication and association */
3256 int timeout = 60;
3257
3258 if (assoc_failed) {
3259 /* give IBSS a bit more time */
3260 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3261 } else if (wpa_s->conf->ap_scan == 1) {
3262 /* give IBSS a bit more time */
3263 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3264 }
3265 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3266 }
3267
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003268 if (wep_keys_set &&
3269 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270 /* Set static WEP keys again */
3271 wpa_set_wep_keys(wpa_s, ssid);
3272 }
3273
3274 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3275 /*
3276 * Do not allow EAP session resumption between different
3277 * network configurations.
3278 */
3279 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3280 }
3281 old_ssid = wpa_s->current_ssid;
3282 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003283
3284 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003285 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003286#ifdef CONFIG_HS20
3287 hs20_configure_frame_filters(wpa_s);
3288#endif /* CONFIG_HS20 */
3289 }
3290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003291 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3292 wpa_supplicant_initiate_eapol(wpa_s);
3293 if (old_ssid != wpa_s->current_ssid)
3294 wpas_notify_network_changed(wpa_s);
3295}
3296
3297
3298static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3299 const u8 *addr)
3300{
3301 struct wpa_ssid *old_ssid;
3302
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003303 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003304 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003305 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003306 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 wpa_sm_set_config(wpa_s->wpa, NULL);
3308 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3309 if (old_ssid != wpa_s->current_ssid)
3310 wpas_notify_network_changed(wpa_s);
3311 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3312}
3313
3314
3315/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003316 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3317 * @wpa_s: Pointer to wpa_supplicant data
3318 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3319 *
3320 * This function is used to request %wpa_supplicant to deauthenticate from the
3321 * current AP.
3322 */
3323void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
3324 int reason_code)
3325{
3326 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003327 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003328 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003330 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
3331 " pending_bssid=" MACSTR " reason=%d state=%s",
3332 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
3333 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
3334
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003335 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3336 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3337 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003338 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003339 else if (!is_zero_ether_addr(wpa_s->bssid))
3340 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003341 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3342 /*
3343 * When using driver-based BSS selection, we may not know the
3344 * BSSID with which we are currently trying to associate. We
3345 * need to notify the driver of this disconnection even in such
3346 * a case, so use the all zeros address here.
3347 */
3348 addr = wpa_s->bssid;
3349 zero_addr = 1;
3350 }
3351
Hai Shalom74f70d42019-02-11 14:42:39 -08003352 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3353 wpa_s->enabled_4addr_mode = 0;
3354
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003355#ifdef CONFIG_TDLS
3356 wpa_tdls_teardown_peers(wpa_s->wpa);
3357#endif /* CONFIG_TDLS */
3358
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003359#ifdef CONFIG_MESH
3360 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003361 struct mesh_conf *mconf;
3362
3363 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003364 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3365 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003366 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3367 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003368 wpa_supplicant_leave_mesh(wpa_s);
3369 }
3370#endif /* CONFIG_MESH */
3371
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003372 if (addr) {
3373 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003374 os_memset(&event, 0, sizeof(event));
3375 event.deauth_info.reason_code = (u16) reason_code;
3376 event.deauth_info.locally_generated = 1;
3377 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003378 if (zero_addr)
3379 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380 }
3381
3382 wpa_supplicant_clear_connection(wpa_s, addr);
3383}
3384
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003385static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3386 struct wpa_ssid *ssid)
3387{
3388 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3389 return;
3390
3391 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003392 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003393 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3394 wpas_notify_network_enabled_changed(wpa_s, ssid);
3395
3396 /*
3397 * Try to reassociate since there is no current configuration and a new
3398 * network was made available.
3399 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003400 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003401 wpa_s->reassociate = 1;
3402}
3403
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003404
Roshan Pius950bec92016-07-19 09:49:24 -07003405/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003406 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003407 * @wpa_s: wpa_supplicant structure for a network interface
3408 * Returns: The new network configuration or %NULL if operation failed
3409 *
3410 * This function performs the following operations:
3411 * 1. Adds a new network.
3412 * 2. Send network addition notification.
3413 * 3. Marks the network disabled.
3414 * 4. Set network default parameters.
3415 */
3416struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3417{
3418 struct wpa_ssid *ssid;
3419
3420 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003421 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003422 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003423 wpas_notify_network_added(wpa_s, ssid);
3424 ssid->disabled = 1;
3425 wpa_config_set_network_defaults(ssid);
3426
3427 return ssid;
3428}
3429
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003430
Roshan Pius950bec92016-07-19 09:49:24 -07003431/**
3432 * wpa_supplicant_remove_network - Remove a configured network based on id
3433 * @wpa_s: wpa_supplicant structure for a network interface
3434 * @id: Unique network id to search for
3435 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3436 * could not be removed
3437 *
3438 * This function performs the following operations:
3439 * 1. Removes the network.
3440 * 2. Send network removal notification.
3441 * 3. Update internal state machines.
3442 * 4. Stop any running sched scans.
3443 */
3444int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3445{
3446 struct wpa_ssid *ssid;
3447 int was_disabled;
3448
3449 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003451 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003452 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003453
3454 if (wpa_s->last_ssid == ssid)
3455 wpa_s->last_ssid = NULL;
3456
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003457 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003458#ifdef CONFIG_SME
3459 wpa_s->sme.prev_bssid_set = 0;
3460#endif /* CONFIG_SME */
3461 /*
3462 * Invalidate the EAP session cache if the current or
3463 * previously used network is removed.
3464 */
3465 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3466 }
3467
3468 if (ssid == wpa_s->current_ssid) {
3469 wpa_sm_set_config(wpa_s->wpa, NULL);
3470 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3471
3472 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3473 wpa_s->own_disconnect_req = 1;
3474 wpa_supplicant_deauthenticate(wpa_s,
3475 WLAN_REASON_DEAUTH_LEAVING);
3476 }
3477
3478 was_disabled = ssid->disabled;
3479
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003480 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003481 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003482
3483 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003484 wpa_printf(MSG_DEBUG,
3485 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003486 wpa_supplicant_cancel_sched_scan(wpa_s);
3487 wpa_supplicant_req_scan(wpa_s, 0, 0);
3488 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003489
Roshan Pius950bec92016-07-19 09:49:24 -07003490 return 0;
3491}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003492
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003494/**
3495 * wpa_supplicant_enable_network - Mark a configured network as enabled
3496 * @wpa_s: wpa_supplicant structure for a network interface
3497 * @ssid: wpa_ssid structure for a configured network or %NULL
3498 *
3499 * Enables the specified network or all networks if no network specified.
3500 */
3501void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3502 struct wpa_ssid *ssid)
3503{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003505 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3506 wpa_supplicant_enable_one_network(wpa_s, ssid);
3507 } else
3508 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003510 if (wpa_s->reassociate && !wpa_s->disconnected &&
3511 (!wpa_s->current_ssid ||
3512 wpa_s->wpa_state == WPA_DISCONNECTED ||
3513 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003514 if (wpa_s->sched_scanning) {
3515 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3516 "new network to scan filters");
3517 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 }
3519
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003520 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3521 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003522 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003523 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524 }
3525}
3526
3527
3528/**
3529 * wpa_supplicant_disable_network - Mark a configured network as disabled
3530 * @wpa_s: wpa_supplicant structure for a network interface
3531 * @ssid: wpa_ssid structure for a configured network or %NULL
3532 *
3533 * Disables the specified network or all networks if no network specified.
3534 */
3535void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3536 struct wpa_ssid *ssid)
3537{
3538 struct wpa_ssid *other_ssid;
3539 int was_disabled;
3540
3541 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003542 if (wpa_s->sched_scanning)
3543 wpa_supplicant_cancel_sched_scan(wpa_s);
3544
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003545 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3546 other_ssid = other_ssid->next) {
3547 was_disabled = other_ssid->disabled;
3548 if (was_disabled == 2)
3549 continue; /* do not change persistent P2P group
3550 * data */
3551
3552 other_ssid->disabled = 1;
3553
3554 if (was_disabled != other_ssid->disabled)
3555 wpas_notify_network_enabled_changed(
3556 wpa_s, other_ssid);
3557 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003558 if (wpa_s->current_ssid) {
3559 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3560 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003561 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003563 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003565 if (ssid == wpa_s->current_ssid) {
3566 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3567 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003568 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003569 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003570 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571
3572 was_disabled = ssid->disabled;
3573
3574 ssid->disabled = 1;
3575
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003576 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003577 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003578 if (wpa_s->sched_scanning) {
3579 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3580 "to remove network from filters");
3581 wpa_supplicant_cancel_sched_scan(wpa_s);
3582 wpa_supplicant_req_scan(wpa_s, 0, 0);
3583 }
3584 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003585 }
3586}
3587
3588
3589/**
3590 * wpa_supplicant_select_network - Attempt association with a network
3591 * @wpa_s: wpa_supplicant structure for a network interface
3592 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3593 */
3594void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3595 struct wpa_ssid *ssid)
3596{
3597
3598 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003599 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003600
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003601 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003602 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3603 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003604 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003605 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003606 disconnected = 1;
3607 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003609 if (ssid)
3610 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612 /*
3613 * Mark all other networks disabled or mark all networks enabled if no
3614 * network specified.
3615 */
3616 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3617 other_ssid = other_ssid->next) {
3618 int was_disabled = other_ssid->disabled;
3619 if (was_disabled == 2)
3620 continue; /* do not change persistent P2P group data */
3621
3622 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003623 if (was_disabled && !other_ssid->disabled)
3624 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003625
3626 if (was_disabled != other_ssid->disabled)
3627 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3628 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003629
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003630 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3631 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003632 /* We are already associated with the selected network */
3633 wpa_printf(MSG_DEBUG, "Already associated with the "
3634 "selected network - do nothing");
3635 return;
3636 }
3637
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003638 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003639 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003640 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003641 wpa_s->connect_without_scan =
3642 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003643
3644 /*
3645 * Don't optimize next scan freqs since a new ESS has been
3646 * selected.
3647 */
3648 os_free(wpa_s->next_scan_freqs);
3649 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003650 } else {
3651 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003652 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 wpa_s->disconnected = 0;
3655 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003656 wpa_s->last_owe_group = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003657 if (ssid)
3658 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003659
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003660 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003661 wpa_supplicant_fast_associate(wpa_s) != 1) {
3662 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003663 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003664 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003665 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666
3667 if (ssid)
3668 wpas_notify_network_selected(wpa_s, ssid);
3669}
3670
3671
3672/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003673 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3674 * @wpa_s: wpa_supplicant structure for a network interface
3675 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3676 * @pkcs11_module_path: PKCS #11 module path or NULL
3677 * Returns: 0 on success; -1 on failure
3678 *
3679 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3680 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3681 * module path fails the paths will be reset to the default value (NULL).
3682 */
3683int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3684 const char *pkcs11_engine_path,
3685 const char *pkcs11_module_path)
3686{
3687 char *pkcs11_engine_path_copy = NULL;
3688 char *pkcs11_module_path_copy = NULL;
3689
3690 if (pkcs11_engine_path != NULL) {
3691 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3692 if (pkcs11_engine_path_copy == NULL)
3693 return -1;
3694 }
3695 if (pkcs11_module_path != NULL) {
3696 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003697 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003698 os_free(pkcs11_engine_path_copy);
3699 return -1;
3700 }
3701 }
3702
3703 os_free(wpa_s->conf->pkcs11_engine_path);
3704 os_free(wpa_s->conf->pkcs11_module_path);
3705 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3706 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3707
3708 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3709 eapol_sm_deinit(wpa_s->eapol);
3710 wpa_s->eapol = NULL;
3711 if (wpa_supplicant_init_eapol(wpa_s)) {
3712 /* Error -> Reset paths to the default value (NULL) once. */
3713 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3714 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3715 NULL);
3716
3717 return -1;
3718 }
3719 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3720
3721 return 0;
3722}
3723
3724
3725/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003726 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3727 * @wpa_s: wpa_supplicant structure for a network interface
3728 * @ap_scan: AP scan mode
3729 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3730 *
3731 */
3732int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3733{
3734
3735 int old_ap_scan;
3736
3737 if (ap_scan < 0 || ap_scan > 2)
3738 return -1;
3739
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003740 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3741 wpa_printf(MSG_INFO,
3742 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3743 }
3744
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003745#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003746 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3747 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3748 wpa_s->wpa_state < WPA_COMPLETED) {
3749 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3750 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003751 return 0;
3752 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003753#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003754
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755 old_ap_scan = wpa_s->conf->ap_scan;
3756 wpa_s->conf->ap_scan = ap_scan;
3757
3758 if (old_ap_scan != wpa_s->conf->ap_scan)
3759 wpas_notify_ap_scan_changed(wpa_s);
3760
3761 return 0;
3762}
3763
3764
3765/**
3766 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3767 * @wpa_s: wpa_supplicant structure for a network interface
3768 * @expire_age: Expiration age in seconds
3769 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3770 *
3771 */
3772int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3773 unsigned int bss_expire_age)
3774{
3775 if (bss_expire_age < 10) {
3776 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3777 bss_expire_age);
3778 return -1;
3779 }
3780 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3781 bss_expire_age);
3782 wpa_s->conf->bss_expiration_age = bss_expire_age;
3783
3784 return 0;
3785}
3786
3787
3788/**
3789 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3790 * @wpa_s: wpa_supplicant structure for a network interface
3791 * @expire_count: number of scans after which an unseen BSS is reclaimed
3792 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3793 *
3794 */
3795int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3796 unsigned int bss_expire_count)
3797{
3798 if (bss_expire_count < 1) {
3799 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3800 bss_expire_count);
3801 return -1;
3802 }
3803 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3804 bss_expire_count);
3805 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3806
3807 return 0;
3808}
3809
3810
3811/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003812 * wpa_supplicant_set_scan_interval - Set scan interval
3813 * @wpa_s: wpa_supplicant structure for a network interface
3814 * @scan_interval: scan interval in seconds
3815 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3816 *
3817 */
3818int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3819 int scan_interval)
3820{
3821 if (scan_interval < 0) {
3822 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3823 scan_interval);
3824 return -1;
3825 }
3826 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3827 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003828 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003829
3830 return 0;
3831}
3832
3833
3834/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003835 * wpa_supplicant_set_debug_params - Set global debug params
3836 * @global: wpa_global structure
3837 * @debug_level: debug level
3838 * @debug_timestamp: determines if show timestamp in debug data
3839 * @debug_show_keys: determines if show keys in debug data
3840 * Returns: 0 if succeed or -1 if debug_level has wrong value
3841 */
3842int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3843 int debug_timestamp, int debug_show_keys)
3844{
3845
3846 int old_level, old_timestamp, old_show_keys;
3847
3848 /* check for allowed debuglevels */
3849 if (debug_level != MSG_EXCESSIVE &&
3850 debug_level != MSG_MSGDUMP &&
3851 debug_level != MSG_DEBUG &&
3852 debug_level != MSG_INFO &&
3853 debug_level != MSG_WARNING &&
3854 debug_level != MSG_ERROR)
3855 return -1;
3856
3857 old_level = wpa_debug_level;
3858 old_timestamp = wpa_debug_timestamp;
3859 old_show_keys = wpa_debug_show_keys;
3860
3861 wpa_debug_level = debug_level;
3862 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3863 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3864
3865 if (wpa_debug_level != old_level)
3866 wpas_notify_debug_level_changed(global);
3867 if (wpa_debug_timestamp != old_timestamp)
3868 wpas_notify_debug_timestamp_changed(global);
3869 if (wpa_debug_show_keys != old_show_keys)
3870 wpas_notify_debug_show_keys_changed(global);
3871
3872 return 0;
3873}
3874
3875
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003876#ifdef CONFIG_OWE
3877static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3878 const u8 *entry_ssid, size_t entry_ssid_len)
3879{
3880 const u8 *owe, *pos, *end;
3881 u8 ssid_len;
3882 struct wpa_bss *bss;
3883
3884 /* Check network profile SSID aganst the SSID in the
3885 * OWE Transition Mode element. */
3886
3887 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3888 if (!bss)
3889 return 0;
3890
3891 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3892 if (!owe)
3893 return 0;
3894
3895 pos = owe + 6;
3896 end = owe + 2 + owe[1];
3897
3898 if (end - pos < ETH_ALEN + 1)
3899 return 0;
3900 pos += ETH_ALEN;
3901 ssid_len = *pos++;
3902 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
3903 return 0;
3904
3905 return entry_ssid_len == ssid_len &&
3906 os_memcmp(pos, entry_ssid, ssid_len) == 0;
3907}
3908#endif /* CONFIG_OWE */
3909
3910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003911/**
3912 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3913 * @wpa_s: Pointer to wpa_supplicant data
3914 * Returns: A pointer to the current network structure or %NULL on failure
3915 */
3916struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3917{
3918 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003919 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920 int res;
3921 size_t ssid_len;
3922 u8 bssid[ETH_ALEN];
3923 int wired;
3924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003925 res = wpa_drv_get_ssid(wpa_s, ssid);
3926 if (res < 0) {
3927 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3928 "driver");
3929 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003930 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003931 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003933 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3935 "driver");
3936 return NULL;
3937 }
3938
3939 wired = wpa_s->conf->ap_scan == 0 &&
3940 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3941
3942 entry = wpa_s->conf->ssid;
3943 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003944 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003945 ((ssid_len == entry->ssid_len &&
3946 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3947 (!entry->bssid_set ||
3948 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3949 return entry;
3950#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003951 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003952 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3953 (entry->ssid == NULL || entry->ssid_len == 0) &&
3954 (!entry->bssid_set ||
3955 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3956 return entry;
3957#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003958
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003959#ifdef CONFIG_OWE
3960 if (!wpas_network_disabled(wpa_s, entry) &&
3961 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
3962 entry->ssid_len) &&
3963 (!entry->bssid_set ||
3964 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3965 return entry;
3966#endif /* CONFIG_OWE */
3967
Dmitry Shmidt04949592012-07-19 12:16:46 -07003968 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003969 entry->ssid_len == 0 &&
3970 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3971 return entry;
3972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003973 entry = entry->next;
3974 }
3975
3976 return NULL;
3977}
3978
3979
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003980static int select_driver(struct wpa_supplicant *wpa_s, int i)
3981{
3982 struct wpa_global *global = wpa_s->global;
3983
3984 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003985 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003986 if (global->drv_priv[i] == NULL) {
3987 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3988 "'%s'", wpa_drivers[i]->name);
3989 return -1;
3990 }
3991 }
3992
3993 wpa_s->driver = wpa_drivers[i];
3994 wpa_s->global_drv_priv = global->drv_priv[i];
3995
3996 return 0;
3997}
3998
3999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4001 const char *name)
4002{
4003 int i;
4004 size_t len;
4005 const char *pos, *driver = name;
4006
4007 if (wpa_s == NULL)
4008 return -1;
4009
4010 if (wpa_drivers[0] == NULL) {
4011 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4012 "wpa_supplicant");
4013 return -1;
4014 }
4015
4016 if (name == NULL) {
4017 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004018 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004019 }
4020
4021 do {
4022 pos = os_strchr(driver, ',');
4023 if (pos)
4024 len = pos - driver;
4025 else
4026 len = os_strlen(driver);
4027
4028 for (i = 0; wpa_drivers[i]; i++) {
4029 if (os_strlen(wpa_drivers[i]->name) == len &&
4030 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004031 0) {
4032 /* First driver that succeeds wins */
4033 if (select_driver(wpa_s, i) == 0)
4034 return 0;
4035 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004036 }
4037
4038 driver = pos + 1;
4039 } while (pos);
4040
4041 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4042 return -1;
4043}
4044
4045
4046/**
4047 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4048 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4049 * with struct wpa_driver_ops::init()
4050 * @src_addr: Source address of the EAPOL frame
4051 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4052 * @len: Length of the EAPOL data
4053 *
4054 * This function is called for each received EAPOL frame. Most driver
4055 * interfaces rely on more generic OS mechanism for receiving frames through
4056 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4057 * take care of received EAPOL frames and deliver them to the core supplicant
4058 * code by calling this function.
4059 */
4060void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4061 const u8 *buf, size_t len)
4062{
4063 struct wpa_supplicant *wpa_s = ctx;
4064
4065 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4066 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4067
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004068#ifdef CONFIG_TESTING_OPTIONS
4069 if (wpa_s->ignore_auth_resp) {
4070 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4071 return;
4072 }
4073#endif /* CONFIG_TESTING_OPTIONS */
4074
Jouni Malinena05074c2012-12-21 21:35:35 +02004075 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4076 (wpa_s->last_eapol_matches_bssid &&
4077#ifdef CONFIG_AP
4078 !wpa_s->ap_iface &&
4079#endif /* CONFIG_AP */
4080 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004081 /*
4082 * There is possible race condition between receiving the
4083 * association event and the EAPOL frame since they are coming
4084 * through different paths from the driver. In order to avoid
4085 * issues in trying to process the EAPOL frame before receiving
4086 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004087 * the association event is received. This may also be needed in
4088 * driver-based roaming case, so also use src_addr != BSSID as a
4089 * trigger if we have previously confirmed that the
4090 * Authenticator uses BSSID as the src_addr (which is not the
4091 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 */
4093 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004094 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4095 wpa_supplicant_state_txt(wpa_s->wpa_state),
4096 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097 wpabuf_free(wpa_s->pending_eapol_rx);
4098 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4099 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004100 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4102 ETH_ALEN);
4103 }
4104 return;
4105 }
4106
Jouni Malinena05074c2012-12-21 21:35:35 +02004107 wpa_s->last_eapol_matches_bssid =
4108 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4109
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110#ifdef CONFIG_AP
4111 if (wpa_s->ap_iface) {
4112 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4113 return;
4114 }
4115#endif /* CONFIG_AP */
4116
4117 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4118 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4119 "no key management is configured");
4120 return;
4121 }
4122
4123 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004124 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004125 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4126 wpa_s->wpa_state != WPA_COMPLETED) &&
4127 (wpa_s->current_ssid == NULL ||
4128 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
4129 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004130 int timeout = 10;
4131
4132 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4133 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4134 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4135 /* Use longer timeout for IEEE 802.1X/EAP */
4136 timeout = 70;
4137 }
4138
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004139#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004140 if (wpa_s->current_ssid && wpa_s->current_bss &&
4141 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4142 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4143 /*
4144 * Use shorter timeout if going through WPS AP iteration
4145 * for PIN config method with an AP that does not
4146 * advertise Selected Registrar.
4147 */
4148 struct wpabuf *wps_ie;
4149
4150 wps_ie = wpa_bss_get_vendor_ie_multi(
4151 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4152 if (wps_ie &&
4153 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4154 timeout = 10;
4155 wpabuf_free(wps_ie);
4156 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004157#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004158
4159 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 }
4161 wpa_s->eapol_received++;
4162
4163 if (wpa_s->countermeasures) {
4164 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4165 "EAPOL packet");
4166 return;
4167 }
4168
4169#ifdef CONFIG_IBSS_RSN
4170 if (wpa_s->current_ssid &&
4171 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4172 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4173 return;
4174 }
4175#endif /* CONFIG_IBSS_RSN */
4176
4177 /* Source address of the incoming EAPOL frame could be compared to the
4178 * current BSSID. However, it is possible that a centralized
4179 * Authenticator could be using another MAC address than the BSSID of
4180 * an AP, so just allow any address to be used for now. The replies are
4181 * still sent to the current BSSID (if available), though. */
4182
4183 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4184 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004185 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4186 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004187 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4188 return;
4189 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004190 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4192 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4193 /*
4194 * Set portValid = TRUE here since we are going to skip 4-way
4195 * handshake processing which would normally set portValid. We
4196 * need this to allow the EAPOL state machines to be completed
4197 * without going through EAPOL-Key handshake.
4198 */
4199 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4200 }
4201}
4202
4203
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004204int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004205{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004206 if ((!wpa_s->p2p_mgmt ||
4207 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4208 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004209 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4211 wpa_drv_get_mac_addr(wpa_s),
4212 ETH_P_EAPOL,
4213 wpa_supplicant_rx_eapol, wpa_s, 0);
4214 if (wpa_s->l2 == NULL)
4215 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004216
4217 if (l2_packet_set_packet_filter(wpa_s->l2,
4218 L2_PACKET_FILTER_PKTTYPE))
4219 wpa_dbg(wpa_s, MSG_DEBUG,
4220 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004221 } else {
4222 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4223 if (addr)
4224 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4225 }
4226
4227 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4228 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4229 return -1;
4230 }
4231
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004232 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4233
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004234 return 0;
4235}
4236
4237
Dmitry Shmidt04949592012-07-19 12:16:46 -07004238static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4239 const u8 *buf, size_t len)
4240{
4241 struct wpa_supplicant *wpa_s = ctx;
4242 const struct l2_ethhdr *eth;
4243
4244 if (len < sizeof(*eth))
4245 return;
4246 eth = (const struct l2_ethhdr *) buf;
4247
4248 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4249 !(eth->h_dest[0] & 0x01)) {
4250 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4251 " (bridge - not for this interface - ignore)",
4252 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4253 return;
4254 }
4255
4256 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4257 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4258 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4259 len - sizeof(*eth));
4260}
4261
4262
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004263/**
4264 * wpa_supplicant_driver_init - Initialize driver interface parameters
4265 * @wpa_s: Pointer to wpa_supplicant data
4266 * Returns: 0 on success, -1 on failure
4267 *
4268 * This function is called to initialize driver interface parameters.
4269 * wpa_drv_init() must have been called before this function to initialize the
4270 * driver interface.
4271 */
4272int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4273{
4274 static int interface_count = 0;
4275
4276 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4277 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004278
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004279 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4280 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004281 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004282 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284 if (wpa_s->bridge_ifname[0]) {
4285 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4286 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004287 wpa_s->l2_br = l2_packet_init_bridge(
4288 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4289 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290 if (wpa_s->l2_br == NULL) {
4291 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4292 "connection for the bridge interface '%s'",
4293 wpa_s->bridge_ifname);
4294 return -1;
4295 }
4296 }
4297
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004298 if (wpa_s->conf->ap_scan == 2 &&
4299 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4300 wpa_printf(MSG_INFO,
4301 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4302 }
4303
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 wpa_clear_keys(wpa_s, NULL);
4305
4306 /* Make sure that TKIP countermeasures are not left enabled (could
4307 * happen if wpa_supplicant is killed during countermeasures. */
4308 wpa_drv_set_countermeasures(wpa_s, 0);
4309
4310 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4311 wpa_drv_flush_pmkid(wpa_s);
4312
4313 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004314 wpa_s->prev_scan_wildcard = 0;
4315
Dmitry Shmidt04949592012-07-19 12:16:46 -07004316 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004317 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4318 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4319 interface_count = 0;
4320 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004321#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004322 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004323 wpa_supplicant_delayed_sched_scan(wpa_s,
4324 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004325 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004326 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004327 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004328#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004329 interface_count++;
4330 } else
4331 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4332
4333 return 0;
4334}
4335
4336
4337static int wpa_supplicant_daemon(const char *pid_file)
4338{
4339 wpa_printf(MSG_DEBUG, "Daemonize..");
4340 return os_daemonize(pid_file);
4341}
4342
4343
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004344static struct wpa_supplicant *
4345wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004346{
4347 struct wpa_supplicant *wpa_s;
4348
4349 wpa_s = os_zalloc(sizeof(*wpa_s));
4350 if (wpa_s == NULL)
4351 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004352 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004353 wpa_s->scan_interval = 5;
4354 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004355 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004356 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004357 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004359 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004360 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004361
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 return wpa_s;
4363}
4364
4365
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004366#ifdef CONFIG_HT_OVERRIDES
4367
4368static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4369 struct ieee80211_ht_capabilities *htcaps,
4370 struct ieee80211_ht_capabilities *htcaps_mask,
4371 const char *ht_mcs)
4372{
4373 /* parse ht_mcs into hex array */
4374 int i;
4375 const char *tmp = ht_mcs;
4376 char *end = NULL;
4377
4378 /* If ht_mcs is null, do not set anything */
4379 if (!ht_mcs)
4380 return 0;
4381
4382 /* This is what we are setting in the kernel */
4383 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4384
4385 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4386
4387 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004388 long v;
4389
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004390 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004391 v = strtol(tmp, &end, 16);
4392
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004393 if (errno == 0) {
4394 wpa_msg(wpa_s, MSG_DEBUG,
4395 "htcap value[%i]: %ld end: %p tmp: %p",
4396 i, v, end, tmp);
4397 if (end == tmp)
4398 break;
4399
4400 htcaps->supported_mcs_set[i] = v;
4401 tmp = end;
4402 } else {
4403 wpa_msg(wpa_s, MSG_ERROR,
4404 "Failed to parse ht-mcs: %s, error: %s\n",
4405 ht_mcs, strerror(errno));
4406 return -1;
4407 }
4408 }
4409
4410 /*
4411 * If we were able to parse any values, then set mask for the MCS set.
4412 */
4413 if (i) {
4414 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4415 IEEE80211_HT_MCS_MASK_LEN - 1);
4416 /* skip the 3 reserved bits */
4417 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4418 0x1f;
4419 }
4420
4421 return 0;
4422}
4423
4424
4425static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4426 struct ieee80211_ht_capabilities *htcaps,
4427 struct ieee80211_ht_capabilities *htcaps_mask,
4428 int disabled)
4429{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004430 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004431
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004432 if (disabled == -1)
4433 return 0;
4434
Hai Shalom74f70d42019-02-11 14:42:39 -08004435 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4436
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004437 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4438 htcaps_mask->ht_capabilities_info |= msk;
4439 if (disabled)
4440 htcaps->ht_capabilities_info &= msk;
4441 else
4442 htcaps->ht_capabilities_info |= msk;
4443
4444 return 0;
4445}
4446
4447
4448static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4449 struct ieee80211_ht_capabilities *htcaps,
4450 struct ieee80211_ht_capabilities *htcaps_mask,
4451 int factor)
4452{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004453 if (factor == -1)
4454 return 0;
4455
Hai Shalom74f70d42019-02-11 14:42:39 -08004456 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4457
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004458 if (factor < 0 || factor > 3) {
4459 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4460 "Must be 0-3 or -1", factor);
4461 return -EINVAL;
4462 }
4463
4464 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4465 htcaps->a_mpdu_params &= ~0x3;
4466 htcaps->a_mpdu_params |= factor & 0x3;
4467
4468 return 0;
4469}
4470
4471
4472static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4473 struct ieee80211_ht_capabilities *htcaps,
4474 struct ieee80211_ht_capabilities *htcaps_mask,
4475 int density)
4476{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004477 if (density == -1)
4478 return 0;
4479
Hai Shalom74f70d42019-02-11 14:42:39 -08004480 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4481
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004482 if (density < 0 || density > 7) {
4483 wpa_msg(wpa_s, MSG_ERROR,
4484 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4485 density);
4486 return -EINVAL;
4487 }
4488
4489 htcaps_mask->a_mpdu_params |= 0x1C;
4490 htcaps->a_mpdu_params &= ~(0x1C);
4491 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4492
4493 return 0;
4494}
4495
4496
4497static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4498 struct ieee80211_ht_capabilities *htcaps,
4499 struct ieee80211_ht_capabilities *htcaps_mask,
4500 int disabled)
4501{
Hai Shalom74f70d42019-02-11 14:42:39 -08004502 if (disabled)
4503 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004504
Paul Stewart092955c2017-02-06 09:13:09 -08004505 set_disable_ht40(htcaps, disabled);
4506 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004507
4508 return 0;
4509}
4510
4511
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004512static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4513 struct ieee80211_ht_capabilities *htcaps,
4514 struct ieee80211_ht_capabilities *htcaps_mask,
4515 int disabled)
4516{
4517 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004518 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4519 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004520
Hai Shalom74f70d42019-02-11 14:42:39 -08004521 if (disabled)
4522 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004523
4524 if (disabled)
4525 htcaps->ht_capabilities_info &= ~msk;
4526 else
4527 htcaps->ht_capabilities_info |= msk;
4528
4529 htcaps_mask->ht_capabilities_info |= msk;
4530
4531 return 0;
4532}
4533
4534
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004535static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4536 struct ieee80211_ht_capabilities *htcaps,
4537 struct ieee80211_ht_capabilities *htcaps_mask,
4538 int disabled)
4539{
4540 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004541 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004542
Hai Shalom74f70d42019-02-11 14:42:39 -08004543 if (disabled)
4544 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004545
4546 if (disabled)
4547 htcaps->ht_capabilities_info &= ~msk;
4548 else
4549 htcaps->ht_capabilities_info |= msk;
4550
4551 htcaps_mask->ht_capabilities_info |= msk;
4552
4553 return 0;
4554}
4555
4556
Hai Shalom74f70d42019-02-11 14:42:39 -08004557static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
4558 struct ieee80211_ht_capabilities *htcaps,
4559 struct ieee80211_ht_capabilities *htcaps_mask,
4560 int tx_stbc)
4561{
4562 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
4563
4564 if (tx_stbc == -1)
4565 return 0;
4566
4567 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
4568
4569 if (tx_stbc < 0 || tx_stbc > 1) {
4570 wpa_msg(wpa_s, MSG_ERROR,
4571 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
4572 return -EINVAL;
4573 }
4574
4575 htcaps_mask->ht_capabilities_info |= msk;
4576 htcaps->ht_capabilities_info &= ~msk;
4577 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
4578
4579 return 0;
4580}
4581
4582
4583static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
4584 struct ieee80211_ht_capabilities *htcaps,
4585 struct ieee80211_ht_capabilities *htcaps_mask,
4586 int rx_stbc)
4587{
4588 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
4589
4590 if (rx_stbc == -1)
4591 return 0;
4592
4593 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
4594
4595 if (rx_stbc < 0 || rx_stbc > 3) {
4596 wpa_msg(wpa_s, MSG_ERROR,
4597 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
4598 return -EINVAL;
4599 }
4600
4601 htcaps_mask->ht_capabilities_info |= msk;
4602 htcaps->ht_capabilities_info &= ~msk;
4603 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
4604
4605 return 0;
4606}
4607
4608
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004609void wpa_supplicant_apply_ht_overrides(
4610 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4611 struct wpa_driver_associate_params *params)
4612{
4613 struct ieee80211_ht_capabilities *htcaps;
4614 struct ieee80211_ht_capabilities *htcaps_mask;
4615
4616 if (!ssid)
4617 return;
4618
4619 params->disable_ht = ssid->disable_ht;
4620 if (!params->htcaps || !params->htcaps_mask)
4621 return;
4622
4623 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4624 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4625 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4626 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4627 ssid->disable_max_amsdu);
4628 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4629 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4630 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004631 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004632 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08004633 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
4634 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004635
4636 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004637 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004638 htcaps->ht_capabilities_info |= bit;
4639 htcaps_mask->ht_capabilities_info |= bit;
4640 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004641}
4642
4643#endif /* CONFIG_HT_OVERRIDES */
4644
4645
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004646#ifdef CONFIG_VHT_OVERRIDES
4647void wpa_supplicant_apply_vht_overrides(
4648 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4649 struct wpa_driver_associate_params *params)
4650{
4651 struct ieee80211_vht_capabilities *vhtcaps;
4652 struct ieee80211_vht_capabilities *vhtcaps_mask;
4653
4654 if (!ssid)
4655 return;
4656
4657 params->disable_vht = ssid->disable_vht;
4658
4659 vhtcaps = (void *) params->vhtcaps;
4660 vhtcaps_mask = (void *) params->vhtcaps_mask;
4661
4662 if (!vhtcaps || !vhtcaps_mask)
4663 return;
4664
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004665 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4666 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004667
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004668#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08004669 if (ssid->disable_sgi) {
4670 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
4671 VHT_CAP_SHORT_GI_160);
4672 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
4673 VHT_CAP_SHORT_GI_160);
4674 wpa_msg(wpa_s, MSG_DEBUG,
4675 "disable-sgi override specified, vht-caps: 0x%x",
4676 vhtcaps->vht_capabilities_info);
4677 }
4678
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004679 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004680 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4681 int max_ampdu;
4682
4683 max_ampdu = (ssid->vht_capa &
4684 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4685 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004686
4687 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4688 wpa_set_ampdu_factor(wpa_s,
4689 (void *) params->htcaps,
4690 (void *) params->htcaps_mask,
4691 max_ampdu);
4692 }
4693#endif /* CONFIG_HT_OVERRIDES */
4694
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004695#define OVERRIDE_MCS(i) \
4696 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4697 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004698 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004699 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004700 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4701 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004702 } \
4703 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4704 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004705 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004706 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004707 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4708 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004709 }
4710
4711 OVERRIDE_MCS(1);
4712 OVERRIDE_MCS(2);
4713 OVERRIDE_MCS(3);
4714 OVERRIDE_MCS(4);
4715 OVERRIDE_MCS(5);
4716 OVERRIDE_MCS(6);
4717 OVERRIDE_MCS(7);
4718 OVERRIDE_MCS(8);
4719}
4720#endif /* CONFIG_VHT_OVERRIDES */
4721
4722
Dmitry Shmidt04949592012-07-19 12:16:46 -07004723static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4724{
4725#ifdef PCSC_FUNCS
4726 size_t len;
4727
4728 if (!wpa_s->conf->pcsc_reader)
4729 return 0;
4730
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004731 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004732 if (!wpa_s->scard)
4733 return 1;
4734
4735 if (wpa_s->conf->pcsc_pin &&
4736 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4737 scard_deinit(wpa_s->scard);
4738 wpa_s->scard = NULL;
4739 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4740 return -1;
4741 }
4742
4743 len = sizeof(wpa_s->imsi) - 1;
4744 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4745 scard_deinit(wpa_s->scard);
4746 wpa_s->scard = NULL;
4747 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4748 return -1;
4749 }
4750 wpa_s->imsi[len] = '\0';
4751
4752 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4753
4754 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4755 wpa_s->imsi, wpa_s->mnc_len);
4756
4757 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4758 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4759#endif /* PCSC_FUNCS */
4760
4761 return 0;
4762}
4763
4764
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004765int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4766{
4767 char *val, *pos;
4768
4769 ext_password_deinit(wpa_s->ext_pw);
4770 wpa_s->ext_pw = NULL;
4771 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4772
4773 if (!wpa_s->conf->ext_password_backend)
4774 return 0;
4775
4776 val = os_strdup(wpa_s->conf->ext_password_backend);
4777 if (val == NULL)
4778 return -1;
4779 pos = os_strchr(val, ':');
4780 if (pos)
4781 *pos++ = '\0';
4782
4783 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4784
4785 wpa_s->ext_pw = ext_password_init(val, pos);
4786 os_free(val);
4787 if (wpa_s->ext_pw == NULL) {
4788 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4789 return -1;
4790 }
4791 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4792
4793 return 0;
4794}
4795
4796
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004797#ifdef CONFIG_FST
4798
4799static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4800{
4801 struct wpa_supplicant *wpa_s = ctx;
4802
4803 return (is_zero_ether_addr(wpa_s->bssid) ||
4804 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4805}
4806
4807
4808static void wpas_fst_get_channel_info_cb(void *ctx,
4809 enum hostapd_hw_mode *hw_mode,
4810 u8 *channel)
4811{
4812 struct wpa_supplicant *wpa_s = ctx;
4813
4814 if (wpa_s->current_bss) {
4815 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4816 channel);
4817 } else if (wpa_s->hw.num_modes) {
4818 *hw_mode = wpa_s->hw.modes[0].mode;
4819 } else {
4820 WPA_ASSERT(0);
4821 *hw_mode = 0;
4822 }
4823}
4824
4825
4826static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4827{
4828 struct wpa_supplicant *wpa_s = ctx;
4829
4830 *modes = wpa_s->hw.modes;
4831 return wpa_s->hw.num_modes;
4832}
4833
4834
4835static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4836{
4837 struct wpa_supplicant *wpa_s = ctx;
4838
4839 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4840 wpa_s->fst_ies = fst_ies;
4841}
4842
4843
4844static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4845{
4846 struct wpa_supplicant *wpa_s = ctx;
4847
Paul Stewart092955c2017-02-06 09:13:09 -08004848 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4849 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4850 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4851 return -1;
4852 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004853 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004854 wpa_s->own_addr, wpa_s->bssid,
4855 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004856 0);
4857}
4858
4859
4860static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4861{
4862 struct wpa_supplicant *wpa_s = ctx;
4863
4864 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4865 return wpa_s->received_mb_ies;
4866}
4867
4868
4869static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4870 const u8 *buf, size_t size)
4871{
4872 struct wpa_supplicant *wpa_s = ctx;
4873 struct mb_ies_info info;
4874
4875 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4876
4877 if (!mb_ies_info_by_ies(&info, buf, size)) {
4878 wpabuf_free(wpa_s->received_mb_ies);
4879 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4880 }
4881}
4882
4883
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004884static const u8 * wpas_fst_get_peer_first(void *ctx,
4885 struct fst_get_peer_ctx **get_ctx,
4886 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004887{
4888 struct wpa_supplicant *wpa_s = ctx;
4889
4890 *get_ctx = NULL;
4891 if (!is_zero_ether_addr(wpa_s->bssid))
4892 return (wpa_s->received_mb_ies || !mb_only) ?
4893 wpa_s->bssid : NULL;
4894 return NULL;
4895}
4896
4897
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004898static const u8 * wpas_fst_get_peer_next(void *ctx,
4899 struct fst_get_peer_ctx **get_ctx,
4900 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004901{
4902 return NULL;
4903}
4904
4905void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4906 struct fst_wpa_obj *iface_obj)
4907{
4908 iface_obj->ctx = wpa_s;
4909 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4910 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4911 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4912 iface_obj->set_ies = wpas_fst_set_ies_cb;
4913 iface_obj->send_action = wpas_fst_send_action_cb;
4914 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4915 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4916 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4917 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4918}
4919#endif /* CONFIG_FST */
4920
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004921static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004922 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004923{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004924 struct wowlan_triggers *triggers;
4925 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004926
4927 if (!wpa_s->conf->wowlan_triggers)
4928 return 0;
4929
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004930 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4931 if (triggers) {
4932 ret = wpa_drv_wowlan(wpa_s, triggers);
4933 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004934 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004935 return ret;
4936}
4937
4938
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004939enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004940{
4941 if (freq < 3000)
4942 return BAND_2_4_GHZ;
4943 if (freq > 50000)
4944 return BAND_60_GHZ;
4945 return BAND_5_GHZ;
4946}
4947
4948
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004949unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004950{
4951 int i;
4952 unsigned int band = 0;
4953
4954 if (freqs) {
4955 /* freqs are specified for the radio work */
4956 for (i = 0; freqs[i]; i++)
4957 band |= wpas_freq_to_band(freqs[i]);
4958 } else {
4959 /*
4960 * freqs are not specified, implies all
4961 * the supported freqs by HW
4962 */
4963 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4964 if (wpa_s->hw.modes[i].num_channels != 0) {
4965 if (wpa_s->hw.modes[i].mode ==
4966 HOSTAPD_MODE_IEEE80211B ||
4967 wpa_s->hw.modes[i].mode ==
4968 HOSTAPD_MODE_IEEE80211G)
4969 band |= BAND_2_4_GHZ;
4970 else if (wpa_s->hw.modes[i].mode ==
4971 HOSTAPD_MODE_IEEE80211A)
4972 band |= BAND_5_GHZ;
4973 else if (wpa_s->hw.modes[i].mode ==
4974 HOSTAPD_MODE_IEEE80211AD)
4975 band |= BAND_60_GHZ;
4976 else if (wpa_s->hw.modes[i].mode ==
4977 HOSTAPD_MODE_IEEE80211ANY)
4978 band = BAND_2_4_GHZ | BAND_5_GHZ |
4979 BAND_60_GHZ;
4980 }
4981 }
4982 }
4983
4984 return band;
4985}
4986
4987
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004988static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4989 const char *rn)
4990{
4991 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4992 struct wpa_radio *radio;
4993
4994 while (rn && iface) {
4995 radio = iface->radio;
4996 if (radio && os_strcmp(rn, radio->name) == 0) {
4997 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4998 wpa_s->ifname, rn);
4999 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5000 return radio;
5001 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005002
5003 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005004 }
5005
5006 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5007 wpa_s->ifname, rn ? rn : "N/A");
5008 radio = os_zalloc(sizeof(*radio));
5009 if (radio == NULL)
5010 return NULL;
5011
5012 if (rn)
5013 os_strlcpy(radio->name, rn, sizeof(radio->name));
5014 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005015 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005016 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5017
5018 return radio;
5019}
5020
5021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005022static void radio_work_free(struct wpa_radio_work *work)
5023{
5024 if (work->wpa_s->scan_work == work) {
5025 /* This should not really happen. */
5026 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5027 work->type, work, work->started);
5028 work->wpa_s->scan_work = NULL;
5029 }
5030
5031#ifdef CONFIG_P2P
5032 if (work->wpa_s->p2p_scan_work == work) {
5033 /* This should not really happen. */
5034 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5035 work->type, work, work->started);
5036 work->wpa_s->p2p_scan_work = NULL;
5037 }
5038#endif /* CONFIG_P2P */
5039
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005040 if (work->started) {
5041 work->wpa_s->radio->num_active_works--;
5042 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005043 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005044 work->type, work,
5045 work->wpa_s->radio->num_active_works);
5046 }
5047
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005048 dl_list_del(&work->list);
5049 os_free(work);
5050}
5051
5052
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005053static int radio_work_is_connect(struct wpa_radio_work *work)
5054{
5055 return os_strcmp(work->type, "sme-connect") == 0 ||
5056 os_strcmp(work->type, "connect") == 0;
5057}
5058
5059
5060static int radio_work_is_scan(struct wpa_radio_work *work)
5061{
5062 return os_strcmp(work->type, "scan") == 0 ||
5063 os_strcmp(work->type, "p2p-scan") == 0;
5064}
5065
5066
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005067static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5068{
5069 struct wpa_radio_work *active_work = NULL;
5070 struct wpa_radio_work *tmp;
5071
5072 /* Get the active work to know the type and band. */
5073 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5074 if (tmp->started) {
5075 active_work = tmp;
5076 break;
5077 }
5078 }
5079
5080 if (!active_work) {
5081 /* No active work, start one */
5082 radio->num_active_works = 0;
5083 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5084 list) {
5085 if (os_strcmp(tmp->type, "scan") == 0 &&
5086 radio->external_scan_running &&
5087 (((struct wpa_driver_scan_params *)
5088 tmp->ctx)->only_new_results ||
5089 tmp->wpa_s->clear_driver_scan_cache))
5090 continue;
5091 return tmp;
5092 }
5093 return NULL;
5094 }
5095
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005096 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005097 /*
5098 * If the active work is either connect or sme-connect,
5099 * do not parallelize them with other radio works.
5100 */
5101 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5102 "Do not parallelize radio work with %s",
5103 active_work->type);
5104 return NULL;
5105 }
5106
5107 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5108 if (tmp->started)
5109 continue;
5110
5111 /*
5112 * If connect or sme-connect are enqueued, parallelize only
5113 * those operations ahead of them in the queue.
5114 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005115 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005116 break;
5117
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005118 /* Serialize parallel scan and p2p_scan operations on the same
5119 * interface since the driver_nl80211 mechanism for tracking
5120 * scan cookies does not yet have support for this. */
5121 if (active_work->wpa_s == tmp->wpa_s &&
5122 radio_work_is_scan(active_work) &&
5123 radio_work_is_scan(tmp)) {
5124 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5125 "Do not start work '%s' when another work '%s' is already scheduled",
5126 tmp->type, active_work->type);
5127 continue;
5128 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005129 /*
5130 * Check that the radio works are distinct and
5131 * on different bands.
5132 */
5133 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5134 (active_work->bands != tmp->bands)) {
5135 /*
5136 * If a scan has to be scheduled through nl80211 scan
5137 * interface and if an external scan is already running,
5138 * do not schedule the scan since it is likely to get
5139 * rejected by kernel.
5140 */
5141 if (os_strcmp(tmp->type, "scan") == 0 &&
5142 radio->external_scan_running &&
5143 (((struct wpa_driver_scan_params *)
5144 tmp->ctx)->only_new_results ||
5145 tmp->wpa_s->clear_driver_scan_cache))
5146 continue;
5147
5148 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5149 "active_work:%s new_work:%s",
5150 active_work->type, tmp->type);
5151 return tmp;
5152 }
5153 }
5154
5155 /* Did not find a radio work to schedule in parallel. */
5156 return NULL;
5157}
5158
5159
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005160static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5161{
5162 struct wpa_radio *radio = eloop_ctx;
5163 struct wpa_radio_work *work;
5164 struct os_reltime now, diff;
5165 struct wpa_supplicant *wpa_s;
5166
5167 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005168 if (work == NULL) {
5169 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005170 return;
5171 }
5172
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005173 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5174 radio_list);
5175
5176 if (!(wpa_s &&
5177 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5178 if (work->started)
5179 return; /* already started and still in progress */
5180
5181 if (wpa_s && wpa_s->radio->external_scan_running) {
5182 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5183 return;
5184 }
5185 } else {
5186 work = NULL;
5187 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5188 /* get the work to schedule next */
5189 work = radio_work_get_next_work(radio);
5190 }
5191 if (!work)
5192 return;
5193 }
5194
5195 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005196 os_get_reltime(&now);
5197 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005198 wpa_dbg(wpa_s, MSG_DEBUG,
5199 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005200 work->type, work, diff.sec, diff.usec);
5201 work->started = 1;
5202 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005203 radio->num_active_works++;
5204
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005205 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005206
5207 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5208 radio->num_active_works < MAX_ACTIVE_WORKS)
5209 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005210}
5211
5212
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005213/*
5214 * This function removes both started and pending radio works running on
5215 * the provided interface's radio.
5216 * Prior to the removal of the radio work, its callback (cb) is called with
5217 * deinit set to be 1. Each work's callback is responsible for clearing its
5218 * internal data and restoring to a correct state.
5219 * @wpa_s: wpa_supplicant data
5220 * @type: type of works to be removed
5221 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5222 * this interface's works.
5223 */
5224void radio_remove_works(struct wpa_supplicant *wpa_s,
5225 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005226{
5227 struct wpa_radio_work *work, *tmp;
5228 struct wpa_radio *radio = wpa_s->radio;
5229
5230 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5231 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005232 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005233 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005234
5235 /* skip other ifaces' works */
5236 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005237 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005238
5239 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5240 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005241 work->cb(work, 1);
5242 radio_work_free(work);
5243 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005244
5245 /* in case we removed the started work */
5246 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005247}
5248
5249
Roshan Pius3a1667e2018-07-03 15:17:14 -07005250void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5251{
5252 struct wpa_radio_work *work;
5253 struct wpa_radio *radio = wpa_s->radio;
5254
5255 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5256 if (work->ctx != ctx)
5257 continue;
5258 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5259 work->type, work, work->started ? " (started)" : "");
5260 radio_work_free(work);
5261 break;
5262 }
5263}
5264
5265
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005266static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5267{
5268 struct wpa_radio *radio = wpa_s->radio;
5269
5270 if (!radio)
5271 return;
5272
5273 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5274 wpa_s->ifname, radio->name);
5275 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005276 radio_remove_works(wpa_s, NULL, 0);
5277 wpa_s->radio = NULL;
5278 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005279 return; /* Interfaces remain for this radio */
5280
5281 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005282 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005283 os_free(radio);
5284}
5285
5286
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005287void radio_work_check_next(struct wpa_supplicant *wpa_s)
5288{
5289 struct wpa_radio *radio = wpa_s->radio;
5290
5291 if (dl_list_empty(&radio->work))
5292 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005293 if (wpa_s->ext_work_in_progress) {
5294 wpa_printf(MSG_DEBUG,
5295 "External radio work in progress - delay start of pending item");
5296 return;
5297 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005298 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5299 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5300}
5301
5302
5303/**
5304 * radio_add_work - Add a radio work item
5305 * @wpa_s: Pointer to wpa_supplicant data
5306 * @freq: Frequency of the offchannel operation in MHz or 0
5307 * @type: Unique identifier for each type of work
5308 * @next: Force as the next work to be executed
5309 * @cb: Callback function for indicating when radio is available
5310 * @ctx: Context pointer for the work (work->ctx in cb())
5311 * Returns: 0 on success, -1 on failure
5312 *
5313 * This function is used to request time for an operation that requires
5314 * exclusive radio control. Once the radio is available, the registered callback
5315 * function will be called. radio_work_done() must be called once the exclusive
5316 * radio operation has been completed, so that the radio is freed for other
5317 * operations. The special case of deinit=1 is used to free the context data
5318 * during interface removal. That does not allow the callback function to start
5319 * the radio operation, i.e., it must free any resources allocated for the radio
5320 * work and return.
5321 *
5322 * The @freq parameter can be used to indicate a single channel on which the
5323 * offchannel operation will occur. This may allow multiple radio work
5324 * operations to be performed in parallel if they apply for the same channel.
5325 * Setting this to 0 indicates that the work item may use multiple channels or
5326 * requires exclusive control of the radio.
5327 */
5328int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5329 const char *type, int next,
5330 void (*cb)(struct wpa_radio_work *work, int deinit),
5331 void *ctx)
5332{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005333 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005334 struct wpa_radio_work *work;
5335 int was_empty;
5336
5337 work = os_zalloc(sizeof(*work));
5338 if (work == NULL)
5339 return -1;
5340 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5341 os_get_reltime(&work->time);
5342 work->freq = freq;
5343 work->type = type;
5344 work->wpa_s = wpa_s;
5345 work->cb = cb;
5346 work->ctx = ctx;
5347
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005348 if (freq)
5349 work->bands = wpas_freq_to_band(freq);
5350 else if (os_strcmp(type, "scan") == 0 ||
5351 os_strcmp(type, "p2p-scan") == 0)
5352 work->bands = wpas_get_bands(wpa_s,
5353 ((struct wpa_driver_scan_params *)
5354 ctx)->freqs);
5355 else
5356 work->bands = wpas_get_bands(wpa_s, NULL);
5357
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005358 was_empty = dl_list_empty(&wpa_s->radio->work);
5359 if (next)
5360 dl_list_add(&wpa_s->radio->work, &work->list);
5361 else
5362 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5363 if (was_empty) {
5364 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5365 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005366 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5367 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5368 wpa_dbg(wpa_s, MSG_DEBUG,
5369 "Try to schedule a radio work (num_active_works=%u)",
5370 radio->num_active_works);
5371 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005372 }
5373
5374 return 0;
5375}
5376
5377
5378/**
5379 * radio_work_done - Indicate that a radio work item has been completed
5380 * @work: Completed work
5381 *
5382 * This function is called once the callback function registered with
5383 * radio_add_work() has completed its work.
5384 */
5385void radio_work_done(struct wpa_radio_work *work)
5386{
5387 struct wpa_supplicant *wpa_s = work->wpa_s;
5388 struct os_reltime now, diff;
5389 unsigned int started = work->started;
5390
5391 os_get_reltime(&now);
5392 os_reltime_sub(&now, &work->time, &diff);
5393 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5394 work->type, work, started ? "done" : "canceled",
5395 diff.sec, diff.usec);
5396 radio_work_free(work);
5397 if (started)
5398 radio_work_check_next(wpa_s);
5399}
5400
5401
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005402struct wpa_radio_work *
5403radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005404{
5405 struct wpa_radio_work *work;
5406 struct wpa_radio *radio = wpa_s->radio;
5407
5408 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5409 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005410 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005411 }
5412
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005413 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005414}
5415
5416
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005417static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005418 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005419{
5420 const char *ifname, *driver, *rn;
5421
5422 driver = iface->driver;
5423next_driver:
5424 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5425 return -1;
5426
5427 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5428 if (wpa_s->drv_priv == NULL) {
5429 const char *pos;
5430 pos = driver ? os_strchr(driver, ',') : NULL;
5431 if (pos) {
5432 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5433 "driver interface - try next driver wrapper");
5434 driver = pos + 1;
5435 goto next_driver;
5436 }
5437 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5438 "interface");
5439 return -1;
5440 }
5441 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5442 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5443 "driver_param '%s'", wpa_s->conf->driver_param);
5444 return -1;
5445 }
5446
5447 ifname = wpa_drv_get_ifname(wpa_s);
5448 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5449 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5450 "interface name with '%s'", ifname);
5451 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5452 }
5453
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005454 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005455 if (rn && rn[0] == '\0')
5456 rn = NULL;
5457
5458 wpa_s->radio = radio_add_interface(wpa_s, rn);
5459 if (wpa_s->radio == NULL)
5460 return -1;
5461
5462 return 0;
5463}
5464
5465
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005466#ifdef CONFIG_GAS_SERVER
5467
5468static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5469 unsigned int freq, const u8 *dst,
5470 const u8 *src, const u8 *bssid,
5471 const u8 *data, size_t data_len,
5472 enum offchannel_send_action_result result)
5473{
5474 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5475 " result=%s",
5476 freq, MAC2STR(dst),
5477 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5478 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5479 "FAILED"));
5480 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5481 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5482}
5483
5484
5485static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5486 struct wpabuf *buf, unsigned int wait_time)
5487{
5488 struct wpa_supplicant *wpa_s = ctx;
5489 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5490
5491 if (wait_time > wpa_s->max_remain_on_chan)
5492 wait_time = wpa_s->max_remain_on_chan;
5493
5494 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5495 wpabuf_head(buf), wpabuf_len(buf),
5496 wait_time, wpas_gas_server_tx_status, 0);
5497}
5498
5499#endif /* CONFIG_GAS_SERVER */
5500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005501static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005502 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005503{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005504 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005505 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005506 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507
5508 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5509 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5510 iface->confname ? iface->confname : "N/A",
5511 iface->driver ? iface->driver : "default",
5512 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5513 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5514
5515 if (iface->confname) {
5516#ifdef CONFIG_BACKEND_FILE
5517 wpa_s->confname = os_rel2abs_path(iface->confname);
5518 if (wpa_s->confname == NULL) {
5519 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5520 "for configuration file '%s'.",
5521 iface->confname);
5522 return -1;
5523 }
5524 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5525 iface->confname, wpa_s->confname);
5526#else /* CONFIG_BACKEND_FILE */
5527 wpa_s->confname = os_strdup(iface->confname);
5528#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005529 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005530 if (wpa_s->conf == NULL) {
5531 wpa_printf(MSG_ERROR, "Failed to read or parse "
5532 "configuration '%s'.", wpa_s->confname);
5533 return -1;
5534 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005535 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005536 if (wpa_s->confanother &&
5537 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5538 wpa_printf(MSG_ERROR,
5539 "Failed to read or parse configuration '%s'.",
5540 wpa_s->confanother);
5541 return -1;
5542 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005543
5544 /*
5545 * Override ctrl_interface and driver_param if set on command
5546 * line.
5547 */
5548 if (iface->ctrl_interface) {
5549 os_free(wpa_s->conf->ctrl_interface);
5550 wpa_s->conf->ctrl_interface =
5551 os_strdup(iface->ctrl_interface);
5552 }
5553
5554 if (iface->driver_param) {
5555 os_free(wpa_s->conf->driver_param);
5556 wpa_s->conf->driver_param =
5557 os_strdup(iface->driver_param);
5558 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005559
5560 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5561 os_free(wpa_s->conf->ctrl_interface);
5562 wpa_s->conf->ctrl_interface = NULL;
5563 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005564 } else
5565 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5566 iface->driver_param);
5567
5568 if (wpa_s->conf == NULL) {
5569 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5570 return -1;
5571 }
5572
5573 if (iface->ifname == NULL) {
5574 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5575 return -1;
5576 }
5577 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5578 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5579 iface->ifname);
5580 return -1;
5581 }
5582 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5583
5584 if (iface->bridge_ifname) {
5585 if (os_strlen(iface->bridge_ifname) >=
5586 sizeof(wpa_s->bridge_ifname)) {
5587 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5588 "name '%s'.", iface->bridge_ifname);
5589 return -1;
5590 }
5591 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5592 sizeof(wpa_s->bridge_ifname));
5593 }
5594
5595 /* RSNA Supplicant Key Management - INITIALIZE */
5596 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5597 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5598
5599 /* Initialize driver interface and register driver event handler before
5600 * L2 receive handler so that association events are processed before
5601 * EAPOL-Key packets if both become available for the same select()
5602 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005603 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005604 return -1;
5605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005606 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5607 return -1;
5608
5609 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5610 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5611 NULL);
5612 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5613
5614 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5615 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5616 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5617 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5618 "dot11RSNAConfigPMKLifetime");
5619 return -1;
5620 }
5621
5622 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5623 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5624 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5625 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5626 "dot11RSNAConfigPMKReauthThreshold");
5627 return -1;
5628 }
5629
5630 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5631 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5632 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5633 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5634 "dot11RSNAConfigSATimeout");
5635 return -1;
5636 }
5637
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005638 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5639 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005640 &wpa_s->hw.flags,
5641 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005642 if (wpa_s->hw.modes) {
5643 u16 i;
5644
5645 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5646 if (wpa_s->hw.modes[i].vht_capab) {
5647 wpa_s->hw_capab = CAPAB_VHT;
5648 break;
5649 }
5650
5651 if (wpa_s->hw.modes[i].ht_capab &
5652 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5653 wpa_s->hw_capab = CAPAB_HT40;
5654 else if (wpa_s->hw.modes[i].ht_capab &&
5655 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5656 wpa_s->hw_capab = CAPAB_HT;
5657 }
5658 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005659
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005660 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5661 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005662 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005663 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005664 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005665 wpa_s->drv_smps_modes = capa.smps_modes;
5666 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005667 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005668 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005669 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005670 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5671 wpa_s->max_sched_scan_plan_interval =
5672 capa.max_sched_scan_plan_interval;
5673 wpa_s->max_sched_scan_plan_iterations =
5674 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005675 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5676 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005677 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5678 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005679 wpa_s->extended_capa = capa.extended_capa;
5680 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5681 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005682 wpa_s->num_multichan_concurrent =
5683 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005684 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5685
5686 if (capa.mac_addr_rand_scan_supported)
5687 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5688 if (wpa_s->sched_scan_supported &&
5689 capa.mac_addr_rand_sched_scan_supported)
5690 wpa_s->mac_addr_rand_supported |=
5691 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08005692
5693 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
5694 if (wpa_s->extended_capa &&
5695 wpa_s->extended_capa_len >= 3 &&
5696 wpa_s->extended_capa[2] & 0x40)
5697 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005698 }
5699 if (wpa_s->max_remain_on_chan == 0)
5700 wpa_s->max_remain_on_chan = 1000;
5701
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005702 /*
5703 * Only take p2p_mgmt parameters when P2P Device is supported.
5704 * Doing it here as it determines whether l2_packet_init() will be done
5705 * during wpa_supplicant_driver_init().
5706 */
5707 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5708 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005709
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005710 if (wpa_s->num_multichan_concurrent == 0)
5711 wpa_s->num_multichan_concurrent = 1;
5712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713 if (wpa_supplicant_driver_init(wpa_s) < 0)
5714 return -1;
5715
5716#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005717 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005718 return -1;
5719#endif /* CONFIG_TDLS */
5720
5721 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5722 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5723 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5724 return -1;
5725 }
5726
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005727#ifdef CONFIG_FST
5728 if (wpa_s->conf->fst_group_id) {
5729 struct fst_iface_cfg cfg;
5730 struct fst_wpa_obj iface_obj;
5731
5732 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5733 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5734 sizeof(cfg.group_id));
5735 cfg.priority = wpa_s->conf->fst_priority;
5736 cfg.llt = wpa_s->conf->fst_llt;
5737
5738 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5739 &iface_obj, &cfg);
5740 if (!wpa_s->fst) {
5741 wpa_msg(wpa_s, MSG_ERROR,
5742 "FST: Cannot attach iface %s to group %s",
5743 wpa_s->ifname, cfg.group_id);
5744 return -1;
5745 }
5746 }
5747#endif /* CONFIG_FST */
5748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005749 if (wpas_wps_init(wpa_s))
5750 return -1;
5751
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005752#ifdef CONFIG_GAS_SERVER
5753 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5754 if (!wpa_s->gas_server) {
5755 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5756 return -1;
5757 }
5758#endif /* CONFIG_GAS_SERVER */
5759
5760#ifdef CONFIG_DPP
5761 if (wpas_dpp_init(wpa_s) < 0)
5762 return -1;
5763#endif /* CONFIG_DPP */
5764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005765 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5766 return -1;
5767 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5768
5769 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5770 if (wpa_s->ctrl_iface == NULL) {
5771 wpa_printf(MSG_ERROR,
5772 "Failed to initialize control interface '%s'.\n"
5773 "You may have another wpa_supplicant process "
5774 "already running or the file was\n"
5775 "left by an unclean termination of wpa_supplicant "
5776 "in which case you will need\n"
5777 "to manually remove this file before starting "
5778 "wpa_supplicant again.\n",
5779 wpa_s->conf->ctrl_interface);
5780 return -1;
5781 }
5782
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005783 wpa_s->gas = gas_query_init(wpa_s);
5784 if (wpa_s->gas == NULL) {
5785 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5786 return -1;
5787 }
5788
Roshan Pius3a1667e2018-07-03 15:17:14 -07005789 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5790 wpa_s->p2p_mgmt) &&
5791 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005792 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5793 return -1;
5794 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005795
5796 if (wpa_bss_init(wpa_s) < 0)
5797 return -1;
5798
Paul Stewart092955c2017-02-06 09:13:09 -08005799#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5800#ifdef CONFIG_MESH
5801 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5802#endif /* CONFIG_MESH */
5803#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5804
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005805 /*
5806 * Set Wake-on-WLAN triggers, if configured.
5807 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5808 * have effect anyway when the interface is down).
5809 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005810 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005811 return -1;
5812
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005813#ifdef CONFIG_EAP_PROXY
5814{
5815 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005816 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5817 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005818 if (wpa_s->mnc_len > 0) {
5819 wpa_s->imsi[len] = '\0';
5820 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5821 wpa_s->imsi, wpa_s->mnc_len);
5822 } else {
5823 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5824 }
5825}
5826#endif /* CONFIG_EAP_PROXY */
5827
Dmitry Shmidt04949592012-07-19 12:16:46 -07005828 if (pcsc_reader_init(wpa_s) < 0)
5829 return -1;
5830
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005831 if (wpas_init_ext_pw(wpa_s) < 0)
5832 return -1;
5833
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005834 wpas_rrm_reset(wpa_s);
5835
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005836 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5837
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005838#ifdef CONFIG_HS20
5839 hs20_init(wpa_s);
5840#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005841#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005842 if (wpa_s->conf->oce) {
5843 if ((wpa_s->conf->oce & OCE_STA) &&
5844 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5845 wpa_s->enable_oce = OCE_STA;
5846 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5847 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5848 /* TODO: Need to add STA-CFON support */
5849 wpa_printf(MSG_ERROR,
5850 "OCE STA-CFON feature is not yet supported");
5851 }
5852 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005853 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5854#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005855
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005856 wpa_supplicant_set_default_scan_ies(wpa_s);
5857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005858 return 0;
5859}
5860
5861
5862static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005863 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005864{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005865 struct wpa_global *global = wpa_s->global;
5866 struct wpa_supplicant *iface, *prev;
5867
5868 if (wpa_s == wpa_s->parent)
5869 wpas_p2p_group_remove(wpa_s, "*");
5870
5871 iface = global->ifaces;
5872 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005873 if (iface->p2pdev == wpa_s)
5874 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005875 if (iface == wpa_s || iface->parent != wpa_s) {
5876 iface = iface->next;
5877 continue;
5878 }
5879 wpa_printf(MSG_DEBUG,
5880 "Remove remaining child interface %s from parent %s",
5881 iface->ifname, wpa_s->ifname);
5882 prev = iface;
5883 iface = iface->next;
5884 wpa_supplicant_remove_iface(global, prev, terminate);
5885 }
5886
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005887 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005888 if (wpa_s->drv_priv) {
5889 wpa_supplicant_deauthenticate(wpa_s,
5890 WLAN_REASON_DEAUTH_LEAVING);
5891
5892 wpa_drv_set_countermeasures(wpa_s, 0);
5893 wpa_clear_keys(wpa_s, NULL);
5894 }
5895
5896 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005897 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005898
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005899 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005900 radio_remove_interface(wpa_s);
5901
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005902#ifdef CONFIG_FST
5903 if (wpa_s->fst) {
5904 fst_detach(wpa_s->fst);
5905 wpa_s->fst = NULL;
5906 }
5907 if (wpa_s->received_mb_ies) {
5908 wpabuf_free(wpa_s->received_mb_ies);
5909 wpa_s->received_mb_ies = NULL;
5910 }
5911#endif /* CONFIG_FST */
5912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005913 if (wpa_s->drv_priv)
5914 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005915
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005916 if (notify)
5917 wpas_notify_iface_removed(wpa_s);
5918
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005919 if (terminate)
5920 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005921
5922 if (wpa_s->ctrl_iface) {
5923 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5924 wpa_s->ctrl_iface = NULL;
5925 }
5926
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005927#ifdef CONFIG_MESH
5928 if (wpa_s->ifmsh) {
5929 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5930 wpa_s->ifmsh = NULL;
5931 }
5932#endif /* CONFIG_MESH */
5933
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005934 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005935 wpa_config_free(wpa_s->conf);
5936 wpa_s->conf = NULL;
5937 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005938
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005939 os_free(wpa_s->ssids_from_scan_req);
5940
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005941 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005942}
5943
5944
Dmitry Shmidte4663042016-04-04 10:07:49 -07005945#ifdef CONFIG_MATCH_IFACE
5946
5947/**
5948 * wpa_supplicant_match_iface - Match an interface description to a name
5949 * @global: Pointer to global data from wpa_supplicant_init()
5950 * @ifname: Name of the interface to match
5951 * Returns: Pointer to the created interface description or %NULL on failure
5952 */
5953struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5954 const char *ifname)
5955{
5956 int i;
5957 struct wpa_interface *iface, *miface;
5958
5959 for (i = 0; i < global->params.match_iface_count; i++) {
5960 miface = &global->params.match_ifaces[i];
5961 if (!miface->ifname ||
5962 fnmatch(miface->ifname, ifname, 0) == 0) {
5963 iface = os_zalloc(sizeof(*iface));
5964 if (!iface)
5965 return NULL;
5966 *iface = *miface;
5967 iface->ifname = ifname;
5968 return iface;
5969 }
5970 }
5971
5972 return NULL;
5973}
5974
5975
5976/**
5977 * wpa_supplicant_match_existing - Match existing interfaces
5978 * @global: Pointer to global data from wpa_supplicant_init()
5979 * Returns: 0 on success, -1 on failure
5980 */
5981static int wpa_supplicant_match_existing(struct wpa_global *global)
5982{
5983 struct if_nameindex *ifi, *ifp;
5984 struct wpa_supplicant *wpa_s;
5985 struct wpa_interface *iface;
5986
5987 ifp = if_nameindex();
5988 if (!ifp) {
5989 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5990 return -1;
5991 }
5992
5993 for (ifi = ifp; ifi->if_name; ifi++) {
5994 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5995 if (wpa_s)
5996 continue;
5997 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5998 if (iface) {
5999 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6000 os_free(iface);
6001 if (wpa_s)
6002 wpa_s->matched = 1;
6003 }
6004 }
6005
6006 if_freenameindex(ifp);
6007 return 0;
6008}
6009
6010#endif /* CONFIG_MATCH_IFACE */
6011
6012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006013/**
6014 * wpa_supplicant_add_iface - Add a new network interface
6015 * @global: Pointer to global data from wpa_supplicant_init()
6016 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006017 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006018 * Returns: Pointer to the created interface or %NULL on failure
6019 *
6020 * This function is used to add new network interfaces for %wpa_supplicant.
6021 * This can be called before wpa_supplicant_run() to add interfaces before the
6022 * main event loop has been started. In addition, new interfaces can be added
6023 * dynamically while %wpa_supplicant is already running. This could happen,
6024 * e.g., when a hotplug network adapter is inserted.
6025 */
6026struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006027 struct wpa_interface *iface,
6028 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006029{
6030 struct wpa_supplicant *wpa_s;
6031 struct wpa_interface t_iface;
6032 struct wpa_ssid *ssid;
6033
6034 if (global == NULL || iface == NULL)
6035 return NULL;
6036
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006037 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006038 if (wpa_s == NULL)
6039 return NULL;
6040
6041 wpa_s->global = global;
6042
6043 t_iface = *iface;
6044 if (global->params.override_driver) {
6045 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6046 "('%s' -> '%s')",
6047 iface->driver, global->params.override_driver);
6048 t_iface.driver = global->params.override_driver;
6049 }
6050 if (global->params.override_ctrl_interface) {
6051 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6052 "ctrl_interface ('%s' -> '%s')",
6053 iface->ctrl_interface,
6054 global->params.override_ctrl_interface);
6055 t_iface.ctrl_interface =
6056 global->params.override_ctrl_interface;
6057 }
6058 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6059 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6060 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006061 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006062 return NULL;
6063 }
6064
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006065 /* Notify the control interfaces about new iface */
6066 if (wpas_notify_iface_added(wpa_s)) {
6067 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6068 return NULL;
6069 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006070
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006071 /* Notify the control interfaces about new networks for non p2p mgmt
6072 * ifaces. */
6073 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006074 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6075 wpas_notify_network_added(wpa_s, ssid);
6076 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006077
6078 wpa_s->next = global->ifaces;
6079 global->ifaces = wpa_s;
6080
6081 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006082 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006083
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006084#ifdef CONFIG_P2P
6085 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006086 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006087 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006088 wpas_p2p_add_p2pdev_interface(
6089 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006090 wpa_printf(MSG_INFO,
6091 "P2P: Failed to enable P2P Device interface");
6092 /* Try to continue without. P2P will be disabled. */
6093 }
6094#endif /* CONFIG_P2P */
6095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006096 return wpa_s;
6097}
6098
6099
6100/**
6101 * wpa_supplicant_remove_iface - Remove a network interface
6102 * @global: Pointer to global data from wpa_supplicant_init()
6103 * @wpa_s: Pointer to the network interface to be removed
6104 * Returns: 0 if interface was removed, -1 if interface was not found
6105 *
6106 * This function can be used to dynamically remove network interfaces from
6107 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6108 * addition, this function is used to remove all remaining interfaces when
6109 * %wpa_supplicant is terminated.
6110 */
6111int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006112 struct wpa_supplicant *wpa_s,
6113 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006114{
6115 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006116#ifdef CONFIG_MESH
6117 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6118 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006119 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006120#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006121
6122 /* Remove interface from the global list of interfaces */
6123 prev = global->ifaces;
6124 if (prev == wpa_s) {
6125 global->ifaces = wpa_s->next;
6126 } else {
6127 while (prev && prev->next != wpa_s)
6128 prev = prev->next;
6129 if (prev == NULL)
6130 return -1;
6131 prev->next = wpa_s->next;
6132 }
6133
6134 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6135
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006136#ifdef CONFIG_MESH
6137 if (mesh_if_created) {
6138 ifname = os_strdup(wpa_s->ifname);
6139 if (ifname == NULL) {
6140 wpa_dbg(wpa_s, MSG_ERROR,
6141 "mesh: Failed to malloc ifname");
6142 return -1;
6143 }
6144 }
6145#endif /* CONFIG_MESH */
6146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006147 if (global->p2p_group_formation == wpa_s)
6148 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006149 if (global->p2p_invite_group == wpa_s)
6150 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006151 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006152
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006153#ifdef CONFIG_MESH
6154 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006155 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006156 os_free(ifname);
6157 }
6158#endif /* CONFIG_MESH */
6159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006160 return 0;
6161}
6162
6163
6164/**
6165 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6166 * @wpa_s: Pointer to the network interface
6167 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6168 */
6169const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6170{
6171 const char *eapol_method;
6172
6173 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6174 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6175 return "NO-EAP";
6176 }
6177
6178 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6179 if (eapol_method == NULL)
6180 return "UNKNOWN-EAP";
6181
6182 return eapol_method;
6183}
6184
6185
6186/**
6187 * wpa_supplicant_get_iface - Get a new network interface
6188 * @global: Pointer to global data from wpa_supplicant_init()
6189 * @ifname: Interface name
6190 * Returns: Pointer to the interface or %NULL if not found
6191 */
6192struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6193 const char *ifname)
6194{
6195 struct wpa_supplicant *wpa_s;
6196
6197 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6198 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6199 return wpa_s;
6200 }
6201 return NULL;
6202}
6203
6204
6205#ifndef CONFIG_NO_WPA_MSG
6206static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6207{
6208 struct wpa_supplicant *wpa_s = ctx;
6209 if (wpa_s == NULL)
6210 return NULL;
6211 return wpa_s->ifname;
6212}
6213#endif /* CONFIG_NO_WPA_MSG */
6214
6215
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006216#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6217#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6218#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6219
6220/* Periodic cleanup tasks */
6221static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6222{
6223 struct wpa_global *global = eloop_ctx;
6224 struct wpa_supplicant *wpa_s;
6225
6226 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6227 wpas_periodic, global, NULL);
6228
6229#ifdef CONFIG_P2P
6230 if (global->p2p)
6231 p2p_expire_peers(global->p2p);
6232#endif /* CONFIG_P2P */
6233
6234 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6235 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6236#ifdef CONFIG_AP
6237 ap_periodic(wpa_s);
6238#endif /* CONFIG_AP */
6239 }
6240}
6241
6242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006243/**
6244 * wpa_supplicant_init - Initialize %wpa_supplicant
6245 * @params: Parameters for %wpa_supplicant
6246 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6247 *
6248 * This function is used to initialize %wpa_supplicant. After successful
6249 * initialization, the returned data pointer can be used to add and remove
6250 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6251 */
6252struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6253{
6254 struct wpa_global *global;
6255 int ret, i;
6256
6257 if (params == NULL)
6258 return NULL;
6259
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006260#ifdef CONFIG_DRIVER_NDIS
6261 {
6262 void driver_ndis_init_ops(void);
6263 driver_ndis_init_ops();
6264 }
6265#endif /* CONFIG_DRIVER_NDIS */
6266
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006267#ifndef CONFIG_NO_WPA_MSG
6268 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6269#endif /* CONFIG_NO_WPA_MSG */
6270
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006271 if (params->wpa_debug_file_path)
6272 wpa_debug_open_file(params->wpa_debug_file_path);
6273 else
6274 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006275 if (params->wpa_debug_syslog)
6276 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006277 if (params->wpa_debug_tracing) {
6278 ret = wpa_debug_open_linux_tracing();
6279 if (ret) {
6280 wpa_printf(MSG_ERROR,
6281 "Failed to enable trace logging");
6282 return NULL;
6283 }
6284 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006285
6286 ret = eap_register_methods();
6287 if (ret) {
6288 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6289 if (ret == -2)
6290 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6291 "the same EAP type.");
6292 return NULL;
6293 }
6294
6295 global = os_zalloc(sizeof(*global));
6296 if (global == NULL)
6297 return NULL;
6298 dl_list_init(&global->p2p_srv_bonjour);
6299 dl_list_init(&global->p2p_srv_upnp);
6300 global->params.daemonize = params->daemonize;
6301 global->params.wait_for_monitor = params->wait_for_monitor;
6302 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6303 if (params->pid_file)
6304 global->params.pid_file = os_strdup(params->pid_file);
6305 if (params->ctrl_interface)
6306 global->params.ctrl_interface =
6307 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006308 if (params->ctrl_interface_group)
6309 global->params.ctrl_interface_group =
6310 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006311 if (params->override_driver)
6312 global->params.override_driver =
6313 os_strdup(params->override_driver);
6314 if (params->override_ctrl_interface)
6315 global->params.override_ctrl_interface =
6316 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006317#ifdef CONFIG_MATCH_IFACE
6318 global->params.match_iface_count = params->match_iface_count;
6319 if (params->match_iface_count) {
6320 global->params.match_ifaces =
6321 os_calloc(params->match_iface_count,
6322 sizeof(struct wpa_interface));
6323 os_memcpy(global->params.match_ifaces,
6324 params->match_ifaces,
6325 params->match_iface_count *
6326 sizeof(struct wpa_interface));
6327 }
6328#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006329#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006330 if (params->conf_p2p_dev)
6331 global->params.conf_p2p_dev =
6332 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006333#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006334 wpa_debug_level = global->params.wpa_debug_level =
6335 params->wpa_debug_level;
6336 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6337 params->wpa_debug_show_keys;
6338 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6339 params->wpa_debug_timestamp;
6340
6341 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6342
6343 if (eloop_init()) {
6344 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6345 wpa_supplicant_deinit(global);
6346 return NULL;
6347 }
6348
Jouni Malinen75ecf522011-06-27 15:19:46 -07006349 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006350
6351 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6352 if (global->ctrl_iface == NULL) {
6353 wpa_supplicant_deinit(global);
6354 return NULL;
6355 }
6356
6357 if (wpas_notify_supplicant_initialized(global)) {
6358 wpa_supplicant_deinit(global);
6359 return NULL;
6360 }
6361
6362 for (i = 0; wpa_drivers[i]; i++)
6363 global->drv_count++;
6364 if (global->drv_count == 0) {
6365 wpa_printf(MSG_ERROR, "No drivers enabled");
6366 wpa_supplicant_deinit(global);
6367 return NULL;
6368 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006369 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006370 if (global->drv_priv == NULL) {
6371 wpa_supplicant_deinit(global);
6372 return NULL;
6373 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006374
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006375#ifdef CONFIG_WIFI_DISPLAY
6376 if (wifi_display_init(global) < 0) {
6377 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6378 wpa_supplicant_deinit(global);
6379 return NULL;
6380 }
6381#endif /* CONFIG_WIFI_DISPLAY */
6382
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006383 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6384 wpas_periodic, global, NULL);
6385
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006386 return global;
6387}
6388
6389
6390/**
6391 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6392 * @global: Pointer to global data from wpa_supplicant_init()
6393 * Returns: 0 after successful event loop run, -1 on failure
6394 *
6395 * This function starts the main event loop and continues running as long as
6396 * there are any remaining events. In most cases, this function is running as
6397 * long as the %wpa_supplicant process in still in use.
6398 */
6399int wpa_supplicant_run(struct wpa_global *global)
6400{
6401 struct wpa_supplicant *wpa_s;
6402
6403 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006404 (wpa_supplicant_daemon(global->params.pid_file) ||
6405 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006406 return -1;
6407
Dmitry Shmidte4663042016-04-04 10:07:49 -07006408#ifdef CONFIG_MATCH_IFACE
6409 if (wpa_supplicant_match_existing(global))
6410 return -1;
6411#endif
6412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006413 if (global->params.wait_for_monitor) {
6414 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006415 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006416 wpa_supplicant_ctrl_iface_wait(
6417 wpa_s->ctrl_iface);
6418 }
6419
6420 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6421 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6422
6423 eloop_run();
6424
6425 return 0;
6426}
6427
6428
6429/**
6430 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6431 * @global: Pointer to global data from wpa_supplicant_init()
6432 *
6433 * This function is called to deinitialize %wpa_supplicant and to free all
6434 * allocated resources. Remaining network interfaces will also be removed.
6435 */
6436void wpa_supplicant_deinit(struct wpa_global *global)
6437{
6438 int i;
6439
6440 if (global == NULL)
6441 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006442
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006443 eloop_cancel_timeout(wpas_periodic, global, NULL);
6444
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006445#ifdef CONFIG_WIFI_DISPLAY
6446 wifi_display_deinit(global);
6447#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006448
6449 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006450 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006451
6452 if (global->ctrl_iface)
6453 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6454
6455 wpas_notify_supplicant_deinitialized(global);
6456
6457 eap_peer_unregister_methods();
6458#ifdef CONFIG_AP
6459 eap_server_unregister_methods();
6460#endif /* CONFIG_AP */
6461
6462 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6463 if (!global->drv_priv[i])
6464 continue;
6465 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6466 }
6467 os_free(global->drv_priv);
6468
6469 random_deinit();
6470
6471 eloop_destroy();
6472
6473 if (global->params.pid_file) {
6474 os_daemonize_terminate(global->params.pid_file);
6475 os_free(global->params.pid_file);
6476 }
6477 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006478 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006479 os_free(global->params.override_driver);
6480 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006481#ifdef CONFIG_MATCH_IFACE
6482 os_free(global->params.match_ifaces);
6483#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006484#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006485 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006486#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006487
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006488 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006489 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006490 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006491
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006492 os_free(global);
6493 wpa_debug_close_syslog();
6494 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006495 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496}
6497
6498
6499void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6500{
6501 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6502 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6503 char country[3];
6504 country[0] = wpa_s->conf->country[0];
6505 country[1] = wpa_s->conf->country[1];
6506 country[2] = '\0';
6507 if (wpa_drv_set_country(wpa_s, country) < 0) {
6508 wpa_printf(MSG_ERROR, "Failed to set country code "
6509 "'%s'", country);
6510 }
6511 }
6512
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006513 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6514 wpas_init_ext_pw(wpa_s);
6515
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006516 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6517 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6518
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006519 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6520 struct wpa_driver_capa capa;
6521 int res = wpa_drv_get_capa(wpa_s, &capa);
6522
6523 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6524 wpa_printf(MSG_ERROR,
6525 "Failed to update wowlan_triggers to '%s'",
6526 wpa_s->conf->wowlan_triggers);
6527 }
6528
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529#ifdef CONFIG_WPS
6530 wpas_wps_update_config(wpa_s);
6531#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006532 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006533 wpa_s->conf->changed_parameters = 0;
6534}
6535
6536
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006537void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006538{
6539 int i;
6540
6541 for (i = 0; i < *num_freqs; i++) {
6542 if (freqs[i] == freq)
6543 return;
6544 }
6545
6546 freqs[*num_freqs] = freq;
6547 (*num_freqs)++;
6548}
6549
6550
6551static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6552{
6553 struct wpa_bss *bss, *cbss;
6554 const int max_freqs = 10;
6555 int *freqs;
6556 int num_freqs = 0;
6557
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006558 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006559 if (freqs == NULL)
6560 return NULL;
6561
6562 cbss = wpa_s->current_bss;
6563
6564 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6565 if (bss == cbss)
6566 continue;
6567 if (bss->ssid_len == cbss->ssid_len &&
6568 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6569 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6570 add_freq(freqs, &num_freqs, bss->freq);
6571 if (num_freqs == max_freqs)
6572 break;
6573 }
6574 }
6575
6576 if (num_freqs == 0) {
6577 os_free(freqs);
6578 freqs = NULL;
6579 }
6580
6581 return freqs;
6582}
6583
6584
6585void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6586{
6587 int timeout;
6588 int count;
6589 int *freqs = NULL;
6590
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006591 wpas_connect_work_done(wpa_s);
6592
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006593 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006594 * Remove possible authentication timeout since the connection failed.
6595 */
6596 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6597
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006598 /*
6599 * There is no point in blacklisting the AP if this event is
6600 * generated based on local request to disconnect.
6601 */
6602 if (wpa_s->own_disconnect_req) {
6603 wpa_s->own_disconnect_req = 0;
6604 wpa_dbg(wpa_s, MSG_DEBUG,
6605 "Ignore connection failure due to local request to disconnect");
6606 return;
6607 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006608 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006609 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6610 "indication since interface has been put into "
6611 "disconnected state");
6612 return;
6613 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08006614 if (wpa_s->auto_reconnect_disabled) {
6615 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6616 "indication since auto connect is disabled");
6617 return;
6618 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006619
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006620 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006621 * Add the failed BSSID into the blacklist and speed up next scan
6622 * attempt if there could be other APs that could accept association.
6623 * The current blacklist count indicates how many times we have tried
6624 * connecting to this AP and multiple attempts mean that other APs are
6625 * either not available or has already been tried, so that we can start
6626 * increasing the delay here to avoid constant scanning.
6627 */
6628 count = wpa_blacklist_add(wpa_s, bssid);
6629 if (count == 1 && wpa_s->current_bss) {
6630 /*
6631 * This BSS was not in the blacklist before. If there is
6632 * another BSS available for the same ESS, we should try that
6633 * next. Otherwise, we may as well try this one once more
6634 * before allowing other, likely worse, ESSes to be considered.
6635 */
6636 freqs = get_bss_freqs_in_ess(wpa_s);
6637 if (freqs) {
6638 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6639 "has been seen; try it next");
6640 wpa_blacklist_add(wpa_s, bssid);
6641 /*
6642 * On the next scan, go through only the known channels
6643 * used in this ESS based on previous scans to speed up
6644 * common load balancing use case.
6645 */
6646 os_free(wpa_s->next_scan_freqs);
6647 wpa_s->next_scan_freqs = freqs;
6648 }
6649 }
6650
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006651 /*
6652 * Add previous failure count in case the temporary blacklist was
6653 * cleared due to no other BSSes being available.
6654 */
6655 count += wpa_s->extra_blacklist_count;
6656
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006657 if (count > 3 && wpa_s->current_ssid) {
6658 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6659 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006660 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006661 }
6662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006663 switch (count) {
6664 case 1:
6665 timeout = 100;
6666 break;
6667 case 2:
6668 timeout = 500;
6669 break;
6670 case 3:
6671 timeout = 1000;
6672 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006673 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006674 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006675 break;
6676 default:
6677 timeout = 10000;
6678 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006679 }
6680
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006681 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6682 "ms", count, timeout);
6683
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006684 /*
6685 * TODO: if more than one possible AP is available in scan results,
6686 * could try the other ones before requesting a new scan.
6687 */
6688 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6689 1000 * (timeout % 1000));
6690}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006691
6692
Hai Shalomce48b4a2018-09-05 11:41:35 -07006693#ifdef CONFIG_FILS
6694void fils_connection_failure(struct wpa_supplicant *wpa_s)
6695{
6696 struct wpa_ssid *ssid = wpa_s->current_ssid;
6697 const u8 *realm, *username, *rrk;
6698 size_t realm_len, username_len, rrk_len;
6699 u16 next_seq_num;
6700
6701 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
6702 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
6703 &username, &username_len,
6704 &realm, &realm_len, &next_seq_num,
6705 &rrk, &rrk_len) != 0 ||
6706 !realm)
6707 return;
6708
6709 wpa_hexdump_ascii(MSG_DEBUG,
6710 "FILS: Store last connection failure realm",
6711 realm, realm_len);
6712 os_free(wpa_s->last_con_fail_realm);
6713 wpa_s->last_con_fail_realm = os_malloc(realm_len);
6714 if (wpa_s->last_con_fail_realm) {
6715 wpa_s->last_con_fail_realm_len = realm_len;
6716 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
6717 }
6718}
6719#endif /* CONFIG_FILS */
6720
6721
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006722int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6723{
6724 return wpa_s->conf->ap_scan == 2 ||
6725 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6726}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006727
Dmitry Shmidt04949592012-07-19 12:16:46 -07006728
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006729#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006730int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6731 struct wpa_ssid *ssid,
6732 const char *field,
6733 const char *value)
6734{
6735#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006736 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006737
6738 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6739 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6740 (const u8 *) value, os_strlen(value));
6741
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006742 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006743 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006744#else /* IEEE8021X_EAPOL */
6745 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6746 return -1;
6747#endif /* IEEE8021X_EAPOL */
6748}
6749
6750int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6751 struct wpa_ssid *ssid,
6752 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006753 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006754{
6755#ifdef IEEE8021X_EAPOL
6756 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006757 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006758
6759 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006760 case WPA_CTRL_REQ_EAP_IDENTITY:
6761 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006762 os_free(eap->imsi_identity);
6763 if (value == NULL)
6764 return -1;
6765 identity = os_strchr(value, ':');
6766 if (identity == NULL) {
6767 /* plain identity */
6768 eap->identity = (u8 *)os_strdup(value);
6769 eap->identity_len = os_strlen(value);
6770 } else {
6771 /* have both plain identity and encrypted identity */
6772 imsi_identity = value;
6773 *identity++ = '\0';
6774 /* plain identity */
6775 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6776 eap->imsi_identity_len = strlen(imsi_identity);
6777 /* encrypted identity */
6778 eap->identity = (u8 *)dup_binstr(identity,
6779 value_len - strlen(imsi_identity) - 1);
6780 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6781 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006782 eap->pending_req_identity = 0;
6783 if (ssid == wpa_s->current_ssid)
6784 wpa_s->reassociate = 1;
6785 break;
6786 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006787 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006788 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006789 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006790 eap->pending_req_password = 0;
6791 if (ssid == wpa_s->current_ssid)
6792 wpa_s->reassociate = 1;
6793 break;
6794 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006795 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006796 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006797 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006798 eap->pending_req_new_password = 0;
6799 if (ssid == wpa_s->current_ssid)
6800 wpa_s->reassociate = 1;
6801 break;
6802 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006803 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006804 eap->pin = os_strdup(value);
6805 eap->pending_req_pin = 0;
6806 if (ssid == wpa_s->current_ssid)
6807 wpa_s->reassociate = 1;
6808 break;
6809 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006810 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006811 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006812 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006813 os_free(eap->pending_req_otp);
6814 eap->pending_req_otp = NULL;
6815 eap->pending_req_otp_len = 0;
6816 break;
6817 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006818 str_clear_free(eap->private_key_passwd);
6819 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006820 eap->pending_req_passphrase = 0;
6821 if (ssid == wpa_s->current_ssid)
6822 wpa_s->reassociate = 1;
6823 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006824 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006825 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006826 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006827 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006828 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006829 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6830 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6831 return -1;
6832 ssid->mem_only_psk = 1;
6833 if (ssid->passphrase)
6834 wpa_config_update_psk(ssid);
6835 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6836 wpa_supplicant_req_scan(wpa_s, 0, 0);
6837 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006838 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6839 if (eap->pending_ext_cert_check != PENDING_CHECK)
6840 return -1;
6841 if (os_strcmp(value, "good") == 0)
6842 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6843 else if (os_strcmp(value, "bad") == 0)
6844 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6845 else
6846 return -1;
6847 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006848 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006849 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006850 return -1;
6851 }
6852
6853 return 0;
6854#else /* IEEE8021X_EAPOL */
6855 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6856 return -1;
6857#endif /* IEEE8021X_EAPOL */
6858}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006859#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006860
6861
6862int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6863{
6864 int i;
6865 unsigned int drv_enc;
6866
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006867 if (wpa_s->p2p_mgmt)
6868 return 1; /* no normal network profiles on p2p_mgmt interface */
6869
Dmitry Shmidt04949592012-07-19 12:16:46 -07006870 if (ssid == NULL)
6871 return 1;
6872
6873 if (ssid->disabled)
6874 return 1;
6875
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006876 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006877 drv_enc = wpa_s->drv_enc;
6878 else
6879 drv_enc = (unsigned int) -1;
6880
6881 for (i = 0; i < NUM_WEP_KEYS; i++) {
6882 size_t len = ssid->wep_key_len[i];
6883 if (len == 0)
6884 continue;
6885 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6886 continue;
6887 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6888 continue;
6889 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6890 continue;
6891 return 1; /* invalid WEP key */
6892 }
6893
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006894 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006895 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006896 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006897 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006898 return 1;
6899
Dmitry Shmidt04949592012-07-19 12:16:46 -07006900 return 0;
6901}
6902
6903
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006904int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6905{
6906#ifdef CONFIG_IEEE80211W
6907 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6908 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6909 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6910 /*
6911 * Driver does not support BIP -- ignore pmf=1 default
6912 * since the connection with PMF would fail and the
6913 * configuration does not require PMF to be enabled.
6914 */
6915 return NO_MGMT_FRAME_PROTECTION;
6916 }
6917
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006918 if (ssid &&
6919 (ssid->key_mgmt &
6920 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6921 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6922 /*
6923 * Do not use the default PMF value for non-RSN networks
6924 * since PMF is available only with RSN and pmf=2
6925 * configuration would otherwise prevent connections to
6926 * all open networks.
6927 */
6928 return NO_MGMT_FRAME_PROTECTION;
6929 }
6930
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006931 return wpa_s->conf->pmf;
6932 }
6933
6934 return ssid->ieee80211w;
6935#else /* CONFIG_IEEE80211W */
6936 return NO_MGMT_FRAME_PROTECTION;
6937#endif /* CONFIG_IEEE80211W */
6938}
6939
6940
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006941int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006942{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006943 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006944 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006945 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006946 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006947 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006948}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006949
6950
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006951void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006952{
6953 struct wpa_ssid *ssid = wpa_s->current_ssid;
6954 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006955 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006956
6957 if (ssid == NULL) {
6958 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6959 "SSID block");
6960 return;
6961 }
6962
6963 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6964 return;
6965
6966 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006967
6968#ifdef CONFIG_P2P
6969 if (ssid->p2p_group &&
6970 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6971 /*
6972 * Skip the wait time since there is a short timeout on the
6973 * connection to a P2P group.
6974 */
6975 return;
6976 }
6977#endif /* CONFIG_P2P */
6978
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006979 if (ssid->auth_failures > 50)
6980 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006981 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006982 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006983 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006984 dur = 90;
6985 else if (ssid->auth_failures > 3)
6986 dur = 60;
6987 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006988 dur = 30;
6989 else if (ssid->auth_failures > 1)
6990 dur = 20;
6991 else
6992 dur = 10;
6993
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006994 if (ssid->auth_failures > 1 &&
6995 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6996 dur += os_random() % (ssid->auth_failures * 10);
6997
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006998 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006999 if (now.sec + dur <= ssid->disabled_until.sec)
7000 return;
7001
7002 ssid->disabled_until.sec = now.sec + dur;
7003
7004 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007005 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007006 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007007 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007008}
7009
7010
7011void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7012 struct wpa_ssid *ssid, int clear_failures)
7013{
7014 if (ssid == NULL)
7015 return;
7016
7017 if (ssid->disabled_until.sec) {
7018 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7019 "id=%d ssid=\"%s\"",
7020 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7021 }
7022 ssid->disabled_until.sec = 0;
7023 ssid->disabled_until.usec = 0;
7024 if (clear_failures)
7025 ssid->auth_failures = 0;
7026}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007027
7028
7029int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7030{
7031 size_t i;
7032
7033 if (wpa_s->disallow_aps_bssid == NULL)
7034 return 0;
7035
7036 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7037 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7038 bssid, ETH_ALEN) == 0)
7039 return 1;
7040 }
7041
7042 return 0;
7043}
7044
7045
7046int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7047 size_t ssid_len)
7048{
7049 size_t i;
7050
7051 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7052 return 0;
7053
7054 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7055 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7056 if (ssid_len == s->ssid_len &&
7057 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7058 return 1;
7059 }
7060
7061 return 0;
7062}
7063
7064
7065/**
7066 * wpas_request_connection - Request a new connection
7067 * @wpa_s: Pointer to the network interface
7068 *
7069 * This function is used to request a new connection to be found. It will mark
7070 * the interface to allow reassociation and request a new scan to find a
7071 * suitable network to connect to.
7072 */
7073void wpas_request_connection(struct wpa_supplicant *wpa_s)
7074{
7075 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007076 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007077 wpa_supplicant_reinit_autoscan(wpa_s);
7078 wpa_s->extra_blacklist_count = 0;
7079 wpa_s->disconnected = 0;
7080 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007081 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007082
7083 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7084 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007085 else
7086 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007087}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007088
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007089
Roshan Pius02242d72016-08-09 15:31:48 -07007090/**
7091 * wpas_request_disconnection - Request disconnection
7092 * @wpa_s: Pointer to the network interface
7093 *
7094 * This function is used to request disconnection from the currently connected
7095 * network. This will stop any ongoing scans and initiate deauthentication.
7096 */
7097void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7098{
7099#ifdef CONFIG_SME
7100 wpa_s->sme.prev_bssid_set = 0;
7101#endif /* CONFIG_SME */
7102 wpa_s->reassociate = 0;
7103 wpa_s->disconnected = 1;
7104 wpa_supplicant_cancel_sched_scan(wpa_s);
7105 wpa_supplicant_cancel_scan(wpa_s);
7106 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7107 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
7108}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007109
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007110
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007111void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7112 struct wpa_used_freq_data *freqs_data,
7113 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007114{
7115 unsigned int i;
7116
7117 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7118 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007119 for (i = 0; i < len; i++) {
7120 struct wpa_used_freq_data *cur = &freqs_data[i];
7121 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7122 i, cur->freq, cur->flags);
7123 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007124}
7125
7126
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007127/*
7128 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007129 * are using the same radio as the current interface, and in addition, get
7130 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007131 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007132int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7133 struct wpa_used_freq_data *freqs_data,
7134 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007135{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007136 struct wpa_supplicant *ifs;
7137 u8 bssid[ETH_ALEN];
7138 int freq;
7139 unsigned int idx = 0, i;
7140
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007141 wpa_dbg(wpa_s, MSG_DEBUG,
7142 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007143 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007144
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007145 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7146 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007147 if (idx == len)
7148 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007149
7150 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7151 continue;
7152
7153 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007154 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7155 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007156 freq = ifs->current_ssid->frequency;
7157 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7158 freq = ifs->assoc_freq;
7159 else
7160 continue;
7161
7162 /* Hold only distinct freqs */
7163 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007164 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007165 break;
7166
7167 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007168 freqs_data[idx++].freq = freq;
7169
7170 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007171 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007172 WPA_FREQ_USED_BY_P2P_CLIENT :
7173 WPA_FREQ_USED_BY_INFRA_STATION;
7174 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007175 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007176
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007177 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007178 return idx;
7179}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007180
7181
7182/*
7183 * Find the operating frequencies of any of the virtual interfaces that
7184 * are using the same radio as the current interface.
7185 */
7186int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7187 int *freq_array, unsigned int len)
7188{
7189 struct wpa_used_freq_data *freqs_data;
7190 int num, i;
7191
7192 os_memset(freq_array, 0, sizeof(int) * len);
7193
7194 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7195 if (!freqs_data)
7196 return -1;
7197
7198 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7199 for (i = 0; i < num; i++)
7200 freq_array[i] = freqs_data[i].freq;
7201
7202 os_free(freqs_data);
7203
7204 return num;
7205}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007206
7207
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007208struct wpa_supplicant *
7209wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7210{
7211 switch (frame) {
7212#ifdef CONFIG_P2P
7213 case VENDOR_ELEM_PROBE_REQ_P2P:
7214 case VENDOR_ELEM_PROBE_RESP_P2P:
7215 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7216 case VENDOR_ELEM_BEACON_P2P_GO:
7217 case VENDOR_ELEM_P2P_PD_REQ:
7218 case VENDOR_ELEM_P2P_PD_RESP:
7219 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7220 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7221 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7222 case VENDOR_ELEM_P2P_INV_REQ:
7223 case VENDOR_ELEM_P2P_INV_RESP:
7224 case VENDOR_ELEM_P2P_ASSOC_REQ:
7225 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007226 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007227#endif /* CONFIG_P2P */
7228 default:
7229 return wpa_s;
7230 }
7231}
7232
7233
7234void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7235{
7236 unsigned int i;
7237 char buf[30];
7238
7239 wpa_printf(MSG_DEBUG, "Update vendor elements");
7240
7241 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7242 if (wpa_s->vendor_elem[i]) {
7243 int res;
7244
7245 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7246 if (!os_snprintf_error(sizeof(buf), res)) {
7247 wpa_hexdump_buf(MSG_DEBUG, buf,
7248 wpa_s->vendor_elem[i]);
7249 }
7250 }
7251 }
7252
7253#ifdef CONFIG_P2P
7254 if (wpa_s->parent == wpa_s &&
7255 wpa_s->global->p2p &&
7256 !wpa_s->global->p2p_disabled)
7257 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7258#endif /* CONFIG_P2P */
7259}
7260
7261
7262int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7263 const u8 *elem, size_t len)
7264{
7265 u8 *ie, *end;
7266
7267 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7268 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7269
7270 for (; ie + 1 < end; ie += 2 + ie[1]) {
7271 if (ie + len > end)
7272 break;
7273 if (os_memcmp(ie, elem, len) != 0)
7274 continue;
7275
7276 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7277 wpabuf_free(wpa_s->vendor_elem[frame]);
7278 wpa_s->vendor_elem[frame] = NULL;
7279 } else {
7280 os_memmove(ie, ie + len, end - (ie + len));
7281 wpa_s->vendor_elem[frame]->used -= len;
7282 }
7283 wpas_vendor_elem_update(wpa_s);
7284 return 0;
7285 }
7286
7287 return -1;
7288}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007289
7290
7291struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7292 u16 num_modes, enum hostapd_hw_mode mode)
7293{
7294 u16 i;
7295
7296 for (i = 0; i < num_modes; i++) {
7297 if (modes[i].mode == mode)
7298 return &modes[i];
7299 }
7300
7301 return NULL;
7302}
7303
7304
7305static struct
7306wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7307 const u8 *bssid)
7308{
7309 struct wpa_bss_tmp_disallowed *bss;
7310
7311 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7312 struct wpa_bss_tmp_disallowed, list) {
7313 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7314 return bss;
7315 }
7316
7317 return NULL;
7318}
7319
7320
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007321static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7322{
7323 struct wpa_bss_tmp_disallowed *tmp;
7324 unsigned int num_bssid = 0;
7325 u8 *bssids;
7326 int ret;
7327
7328 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7329 if (!bssids)
7330 return -1;
7331 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7332 struct wpa_bss_tmp_disallowed, list) {
7333 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7334 ETH_ALEN);
7335 num_bssid++;
7336 }
7337 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7338 os_free(bssids);
7339 return ret;
7340}
7341
7342
7343static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7344{
7345 struct wpa_supplicant *wpa_s = eloop_ctx;
7346 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7347
7348 /* Make sure the bss is not already freed */
7349 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7350 struct wpa_bss_tmp_disallowed, list) {
7351 if (bss == tmp) {
7352 dl_list_del(&tmp->list);
7353 os_free(tmp);
7354 wpa_set_driver_tmp_disallow_list(wpa_s);
7355 break;
7356 }
7357 }
7358}
7359
7360
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007361void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007362 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007363{
7364 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007365
7366 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7367 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007368 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007369 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007370 }
7371
7372 bss = os_malloc(sizeof(*bss));
7373 if (!bss) {
7374 wpa_printf(MSG_DEBUG,
7375 "Failed to allocate memory for temp disallow BSS");
7376 return;
7377 }
7378
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007379 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7380 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007381 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007382
7383finish:
7384 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007385 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7386 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007387}
7388
7389
Hai Shalom74f70d42019-02-11 14:42:39 -08007390int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7391 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007392{
Hai Shalom74f70d42019-02-11 14:42:39 -08007393 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007394
7395 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7396 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007397 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7398 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007399 break;
7400 }
7401 }
Hai Shalom74f70d42019-02-11 14:42:39 -08007402 if (!disallowed)
7403 return 0;
7404
7405 if (disallowed->rssi_threshold != 0 &&
7406 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007407 return 0;
7408
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007409 return 1;
7410}