blob: 3471b99536a73e0d2d4ed0af97f6a369a6296c35 [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"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080044#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080046#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080047#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "wpas_glue.h"
49#include "wps_supplicant.h"
50#include "ibss_rsn.h"
51#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "ap.h"
54#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070055#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "notify.h"
57#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059#include "bss.h"
60#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080061#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070062#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070063#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070064#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080065#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066#include "dpp_supplicant.h"
67#ifdef CONFIG_MESH
68#include "ap/ap_config.h"
69#include "ap/hostapd.h"
70#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070072const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073"wpa_supplicant v" VERSION_STR "\n"
Hai Shalom74f70d42019-02-11 14:42:39 -080074"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070076const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080077"This software may be distributed under the terms of the BSD license.\n"
78"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079#ifdef EAP_TLS_OPENSSL
80"\nThis product includes software developed by the OpenSSL Project\n"
81"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
82#endif /* EAP_TLS_OPENSSL */
83;
84
85#ifndef CONFIG_NO_STDOUT_DEBUG
86/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080088"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091"\n"
92"Redistribution and use in source and binary forms, with or without\n"
93"modification, are permitted provided that the following conditions are\n"
94"met:\n"
95"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070096const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097"1. Redistributions of source code must retain the above copyright\n"
98" notice, this list of conditions and the following disclaimer.\n"
99"\n"
100"2. Redistributions in binary form must reproduce the above copyright\n"
101" notice, this list of conditions and the following disclaimer in the\n"
102" documentation and/or other materials provided with the distribution.\n"
103"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
106" names of its contributors may be used to endorse or promote products\n"
107" derived from this software without specific prior written permission.\n"
108"\n"
109"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
110"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
111"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
112"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700113const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
115"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
116"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
117"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
118"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
119"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
120"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
121"\n";
122#endif /* CONFIG_NO_STDOUT_DEBUG */
123
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700124
125static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
126#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
127static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
128#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700129#ifdef CONFIG_OWE
130static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
131#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700132
133
Hai Shalomfdcde762020-04-02 11:19:20 -0700134#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700135/* Configure default/group WEP keys for static WEP */
136int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
137{
138 int i, set = 0;
139
140 for (i = 0; i < NUM_WEP_KEYS; i++) {
141 if (ssid->wep_key_len[i] == 0)
142 continue;
143
144 set = 1;
145 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
146 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700147 ssid->wep_key[i], ssid->wep_key_len[i],
148 i == ssid->wep_tx_keyidx ?
149 KEY_FLAG_GROUP_RX_TX_DEFAULT :
150 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151 }
152
153 return set;
154}
Hai Shalomfdcde762020-04-02 11:19:20 -0700155#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156
157
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700158int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
159 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160{
161 u8 key[32];
162 size_t keylen;
163 enum wpa_alg alg;
164 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800165 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166
167 /* IBSS/WPA-None uses only one key (Group) for both receiving and
168 * sending unicast and multicast packets. */
169
170 if (ssid->mode != WPAS_MODE_IBSS) {
171 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
172 "IBSS/ad-hoc) for WPA-None", ssid->mode);
173 return -1;
174 }
175
176 if (!ssid->psk_set) {
177 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
178 "WPA-None");
179 return -1;
180 }
181
182 switch (wpa_s->group_cipher) {
183 case WPA_CIPHER_CCMP:
184 os_memcpy(key, ssid->psk, 16);
185 keylen = 16;
186 alg = WPA_ALG_CCMP;
187 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700188 case WPA_CIPHER_GCMP:
189 os_memcpy(key, ssid->psk, 16);
190 keylen = 16;
191 alg = WPA_ALG_GCMP;
192 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 case WPA_CIPHER_TKIP:
194 /* WPA-None uses the same Michael MIC key for both TX and RX */
195 os_memcpy(key, ssid->psk, 16 + 8);
196 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
197 keylen = 32;
198 alg = WPA_ALG_TKIP;
199 break;
200 default:
201 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
202 "WPA-None", wpa_s->group_cipher);
203 return -1;
204 }
205
206 /* TODO: should actually remember the previously used seq#, both for TX
207 * and RX from each STA.. */
208
Hai Shalomfdcde762020-04-02 11:19:20 -0700209 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
210 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800211 os_memset(key, 0, sizeof(key));
212 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213}
214
215
216static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
217{
218 struct wpa_supplicant *wpa_s = eloop_ctx;
219 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700220 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
221 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
222 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223 bssid = wpa_s->pending_bssid;
224 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
225 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800226 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700227 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800229 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_s->reassociate = 1;
231
232 /*
233 * If we timed out, the AP or the local radio may be busy.
234 * So, wait a second until scanning again.
235 */
236 wpa_supplicant_req_scan(wpa_s, 1, 0);
237}
238
239
240/**
241 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
242 * @wpa_s: Pointer to wpa_supplicant data
243 * @sec: Number of seconds after which to time out authentication
244 * @usec: Number of microseconds after which to time out authentication
245 *
246 * This function is used to schedule a timeout for the current authentication
247 * attempt.
248 */
249void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
250 int sec, int usec)
251{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700252 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
254 return;
255
256 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
257 "%d usec", sec, usec);
258 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700259 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700260 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
261}
262
263
Roshan Pius3a1667e2018-07-03 15:17:14 -0700264/*
265 * wpas_auth_timeout_restart - Restart and change timeout for authentication
266 * @wpa_s: Pointer to wpa_supplicant data
267 * @sec_diff: difference in seconds applied to original timeout value
268 */
269void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
270{
271 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
272
273 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
274 wpa_dbg(wpa_s, MSG_DEBUG,
275 "Authentication timeout restart: %d sec", new_sec);
276 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
277 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
278 wpa_s, NULL);
279 }
280}
281
282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283/**
284 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
285 * @wpa_s: Pointer to wpa_supplicant data
286 *
287 * This function is used to cancel authentication timeout scheduled with
288 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
289 * been completed.
290 */
291void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
292{
293 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
294 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800295 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700296 os_free(wpa_s->last_con_fail_realm);
297 wpa_s->last_con_fail_realm = NULL;
298 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299}
300
301
302/**
303 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
304 * @wpa_s: Pointer to wpa_supplicant data
305 *
306 * This function is used to configure EAPOL state machine based on the selected
307 * authentication mode.
308 */
309void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
310{
311#ifdef IEEE8021X_EAPOL
312 struct eapol_config eapol_conf;
313 struct wpa_ssid *ssid = wpa_s->current_ssid;
314
315#ifdef CONFIG_IBSS_RSN
316 if (ssid->mode == WPAS_MODE_IBSS &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
319 /*
320 * RSN IBSS authentication is per-STA and we can disable the
321 * per-BSSID EAPOL authentication.
322 */
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700324 eapol_sm_notify_eap_success(wpa_s->eapol, true);
325 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 return;
327 }
328#endif /* CONFIG_IBSS_RSN */
329
Hai Shalome21d4e82020-04-29 16:34:06 -0700330 eapol_sm_notify_eap_success(wpa_s->eapol, false);
331 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
334 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
335 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
336 else
337 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
338
339 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
340 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
341 eapol_conf.accept_802_1x_keys = 1;
342 eapol_conf.required_keys = 0;
343 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
344 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
345 }
346 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
347 eapol_conf.required_keys |=
348 EAPOL_REQUIRE_KEY_BROADCAST;
349 }
350
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 eapol_conf.required_keys = 0;
353 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700354 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 eapol_conf.workaround = ssid->eap_workaround;
356 eapol_conf.eap_disabled =
357 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700360 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800361
362#ifdef CONFIG_WPS
363 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
364 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
365 if (wpa_s->current_bss) {
366 struct wpabuf *ie;
367 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
368 WPS_IE_VENDOR_TYPE);
369 if (ie) {
370 if (wps_is_20(ie))
371 eapol_conf.wps |=
372 EAPOL_PEER_IS_WPS20_AP;
373 wpabuf_free(ie);
374 }
375 }
376 }
377#endif /* CONFIG_WPS */
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700380
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800381#ifdef CONFIG_MACSEC
382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
383 ieee802_1x_create_preshared_mka(wpa_s, ssid);
384 else
385 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
386#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800387#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
391/**
392 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
393 * @wpa_s: Pointer to wpa_supplicant data
394 * @ssid: Configuration data for the network
395 *
396 * This function is used to configure WPA state machine and related parameters
397 * to a mode where WPA is not enabled. This is called as part of the
398 * authentication configuration when the selected network does not use WPA.
399 */
400void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
401 struct wpa_ssid *ssid)
402{
Hai Shalomfdcde762020-04-02 11:19:20 -0700403#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406
407 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
408 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
409 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
410 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
411 else
412 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
413 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
414 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700415 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700417 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
418 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
420 wpa_s->group_cipher = WPA_CIPHER_NONE;
421 wpa_s->mgmt_group_cipher = 0;
422
Hai Shalomfdcde762020-04-02 11:19:20 -0700423#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 for (i = 0; i < NUM_WEP_KEYS; i++) {
425 if (ssid->wep_key_len[i] > 5) {
426 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
427 wpa_s->group_cipher = WPA_CIPHER_WEP104;
428 break;
429 } else if (ssid->wep_key_len[i] > 0) {
430 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
431 wpa_s->group_cipher = WPA_CIPHER_WEP40;
432 break;
433 }
434 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700435#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
440 wpa_s->pairwise_cipher);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
443 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
445 pmksa_cache_clear_current(wpa_s->wpa);
446}
447
448
Dmitry Shmidt04949592012-07-19 12:16:46 -0700449void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800450{
451 int i;
452 if (wpa_s->hw.modes == NULL)
453 return;
454
455 for (i = 0; i < wpa_s->hw.num_modes; i++) {
456 os_free(wpa_s->hw.modes[i].channels);
457 os_free(wpa_s->hw.modes[i].rates);
458 }
459
460 os_free(wpa_s->hw.modes);
461 wpa_s->hw.modes = NULL;
462}
463
464
Hai Shalom74f70d42019-02-11 14:42:39 -0800465void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800466{
467 struct wpa_bss_tmp_disallowed *bss, *prev;
468
469 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
470 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700471 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800472 dl_list_del(&bss->list);
473 os_free(bss);
474 }
475}
476
477
Paul Stewart092955c2017-02-06 09:13:09 -0800478void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
479{
480 struct fils_hlp_req *req;
481
482 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
483 list)) != NULL) {
484 dl_list_del(&req->list);
485 wpabuf_free(req->pkt);
486 os_free(req);
487 }
488}
489
490
Hai Shalomfdcde762020-04-02 11:19:20 -0700491void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
492{
493 struct wpa_supplicant *wpa_s = eloop_ctx;
494
495 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
496 return;
497 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
498 wpa_bss_flush(wpa_s);
499}
500
501
502#ifdef CONFIG_TESTING_OPTIONS
503void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
504{
505 struct driver_signal_override *dso;
506
507 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
508 struct driver_signal_override, list))) {
509 dl_list_del(&dso->list);
510 os_free(dso);
511 }
512}
513#endif /* CONFIG_TESTING_OPTIONS */
514
515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
517{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700518 int i;
519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700521 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522 scard_deinit(wpa_s->scard);
523 wpa_s->scard = NULL;
524 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
525 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
526 l2_packet_deinit(wpa_s->l2);
527 wpa_s->l2 = NULL;
528 if (wpa_s->l2_br) {
529 l2_packet_deinit(wpa_s->l2_br);
530 wpa_s->l2_br = NULL;
531 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800532#ifdef CONFIG_TESTING_OPTIONS
533 l2_packet_deinit(wpa_s->l2_test);
534 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800535 os_free(wpa_s->get_pref_freq_list_override);
536 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700537 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
538 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800539 os_free(wpa_s->extra_sae_rejected_groups);
540 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700541 wpabuf_free(wpa_s->rsne_override_eapol);
542 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800543 wpabuf_free(wpa_s->rsnxe_override_assoc);
544 wpa_s->rsnxe_override_assoc = NULL;
545 wpabuf_free(wpa_s->rsnxe_override_eapol);
546 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700547 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800548#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 if (wpa_s->conf != NULL) {
551 struct wpa_ssid *ssid;
552 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
553 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554 }
555
556 os_free(wpa_s->confname);
557 wpa_s->confname = NULL;
558
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700559 os_free(wpa_s->confanother);
560 wpa_s->confanother = NULL;
561
Hai Shalomce48b4a2018-09-05 11:41:35 -0700562 os_free(wpa_s->last_con_fail_realm);
563 wpa_s->last_con_fail_realm = NULL;
564 wpa_s->last_con_fail_realm_len = 0;
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566 wpa_sm_set_eapol(wpa_s->wpa, NULL);
567 eapol_sm_deinit(wpa_s->eapol);
568 wpa_s->eapol = NULL;
569
570 rsn_preauth_deinit(wpa_s->wpa);
571
572#ifdef CONFIG_TDLS
573 wpa_tdls_deinit(wpa_s->wpa);
574#endif /* CONFIG_TDLS */
575
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800576 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800578 ptksa_cache_deinit(wpa_s->ptksa);
579 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 wpa_sm_deinit(wpa_s->wpa);
581 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800582 wpa_bssid_ignore_clear(wpa_s);
583
584#ifdef CONFIG_PASN
585 wpas_pasn_auth_stop(wpa_s);
586#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587
588 wpa_bss_deinit(wpa_s);
589
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700590 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_supplicant_cancel_scan(wpa_s);
592 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800593 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
594#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
595 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
596 wpa_s, NULL);
597#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700599 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700600 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpas_wps_deinit(wpa_s);
603
604 wpabuf_free(wpa_s->pending_eapol_rx);
605 wpa_s->pending_eapol_rx = NULL;
606
607#ifdef CONFIG_IBSS_RSN
608 ibss_rsn_deinit(wpa_s->ibss_rsn);
609 wpa_s->ibss_rsn = NULL;
610#endif /* CONFIG_IBSS_RSN */
611
612 sme_deinit(wpa_s);
613
614#ifdef CONFIG_AP
615 wpa_supplicant_ap_deinit(wpa_s);
616#endif /* CONFIG_AP */
617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800620#ifdef CONFIG_OFFCHANNEL
621 offchannel_deinit(wpa_s);
622#endif /* CONFIG_OFFCHANNEL */
623
624 wpa_supplicant_cancel_sched_scan(wpa_s);
625
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 os_free(wpa_s->next_scan_freqs);
627 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800628
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800629 os_free(wpa_s->manual_scan_freqs);
630 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700631 os_free(wpa_s->select_network_scan_freqs);
632 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800633
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700634 os_free(wpa_s->manual_sched_scan_freqs);
635 wpa_s->manual_sched_scan_freqs = NULL;
636
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800637 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
638
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700639 /*
640 * Need to remove any pending gas-query radio work before the
641 * gas_query_deinit() call because gas_query::work has not yet been set
642 * for works that have not been started. gas_query_free() will be unable
643 * to cancel such pending radio works and once the pending gas-query
644 * radio work eventually gets removed, the deinit notification call to
645 * gas_query_start_cb() would result in dereferencing freed memory.
646 */
647 if (wpa_s->radio)
648 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800649 gas_query_deinit(wpa_s->gas);
650 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 gas_server_deinit(wpa_s->gas_server);
652 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800653
654 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700655
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700656 ieee802_1x_dealloc_kay_sm(wpa_s);
657
Dmitry Shmidt04949592012-07-19 12:16:46 -0700658 os_free(wpa_s->bssid_filter);
659 wpa_s->bssid_filter = NULL;
660
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800661 os_free(wpa_s->disallow_aps_bssid);
662 wpa_s->disallow_aps_bssid = NULL;
663 os_free(wpa_s->disallow_aps_ssid);
664 wpa_s->disallow_aps_ssid = NULL;
665
Dmitry Shmidt04949592012-07-19 12:16:46 -0700666 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700667#ifdef CONFIG_WNM
668 wnm_deallocate_memory(wpa_s);
669#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670
671 ext_password_deinit(wpa_s->ext_pw);
672 wpa_s->ext_pw = NULL;
673
674 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800675 wpa_s->last_gas_resp = NULL;
676 wpabuf_free(wpa_s->prev_gas_resp);
677 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700678
679 os_free(wpa_s->last_scan_res);
680 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800681
682#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700683 if (wpa_s->drv_priv)
684 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700685 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800686#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700687
688 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
689 wpabuf_free(wpa_s->vendor_elem[i]);
690 wpa_s->vendor_elem[i] = NULL;
691 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800692
693 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800694
695 wpa_s->sched_scan_plans_num = 0;
696 os_free(wpa_s->sched_scan_plans);
697 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800698
699#ifdef CONFIG_MBO
700 wpa_s->non_pref_chan_num = 0;
701 os_free(wpa_s->non_pref_chan);
702 wpa_s->non_pref_chan = NULL;
703#endif /* CONFIG_MBO */
704
705 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700706
707 wpabuf_free(wpa_s->lci);
708 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800709 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800710
711#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
712#ifdef CONFIG_MESH
713 {
714 struct external_pmksa_cache *entry;
715
716 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
717 struct external_pmksa_cache,
718 list)) != NULL) {
719 dl_list_del(&entry->list);
720 os_free(entry->pmksa_cache);
721 os_free(entry);
722 }
723 }
724#endif /* CONFIG_MESH */
725#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
726
727 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800728
729 wpabuf_free(wpa_s->ric_ies);
730 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700731
732#ifdef CONFIG_DPP
733 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700734 dpp_global_deinit(wpa_s->dpp);
735 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700736#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800737
738#ifdef CONFIG_PASN
739 wpas_pasn_auth_stop(wpa_s);
740#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741}
742
743
744/**
745 * wpa_clear_keys - Clear keys configured for the driver
746 * @wpa_s: Pointer to wpa_supplicant data
747 * @addr: Previously used BSSID or %NULL if not available
748 *
749 * This function clears the encryption keys that has been previously configured
750 * for the driver.
751 */
752void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
753{
Hai Shalomc3565922019-10-28 11:58:20 -0700754 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755
756 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800757 for (i = 0; i < max; i++) {
758 if (wpa_s->keys_cleared & BIT(i))
759 continue;
760 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700761 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700763 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
764 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700766 if (!(wpa_s->keys_cleared & BIT(0)))
767 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
768 0, NULL, 0, KEY_FLAG_PAIRWISE);
769 if (!(wpa_s->keys_cleared & BIT(15)))
770 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
771 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 /* MLME-SETPROTECTION.request(None) */
773 wpa_drv_mlme_setprotection(
774 wpa_s, addr,
775 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
776 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
777 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800778 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779}
780
781
782/**
783 * wpa_supplicant_state_txt - Get the connection state name as a text string
784 * @state: State (wpa_state; WPA_*)
785 * Returns: The state name as a printable text string
786 */
787const char * wpa_supplicant_state_txt(enum wpa_states state)
788{
789 switch (state) {
790 case WPA_DISCONNECTED:
791 return "DISCONNECTED";
792 case WPA_INACTIVE:
793 return "INACTIVE";
794 case WPA_INTERFACE_DISABLED:
795 return "INTERFACE_DISABLED";
796 case WPA_SCANNING:
797 return "SCANNING";
798 case WPA_AUTHENTICATING:
799 return "AUTHENTICATING";
800 case WPA_ASSOCIATING:
801 return "ASSOCIATING";
802 case WPA_ASSOCIATED:
803 return "ASSOCIATED";
804 case WPA_4WAY_HANDSHAKE:
805 return "4WAY_HANDSHAKE";
806 case WPA_GROUP_HANDSHAKE:
807 return "GROUP_HANDSHAKE";
808 case WPA_COMPLETED:
809 return "COMPLETED";
810 default:
811 return "UNKNOWN";
812 }
813}
814
815
816#ifdef CONFIG_BGSCAN
817
Hai Shalom899fcc72020-10-19 14:38:18 -0700818static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
819{
820 if (wpa_s->bgscan_ssid) {
821 bgscan_deinit(wpa_s);
822 wpa_s->bgscan_ssid = NULL;
823 }
824}
825
826
827/**
828 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
829 * @wpa_s: Pointer to the wpa_supplicant data
830 *
831 * Stop, start, or reconfigure the scan parameters depending on the method.
832 */
833void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800835 const char *name;
836
837 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
838 name = wpa_s->current_ssid->bgscan;
839 else
840 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700841 if (!name || name[0] == '\0') {
842 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800843 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700844 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800845 if (wpas_driver_bss_selection(wpa_s))
846 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800847#ifdef CONFIG_P2P
848 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
849 return;
850#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851
852 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800853 if (wpa_s->current_ssid) {
854 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
856 "bgscan");
857 /*
858 * Live without bgscan; it is only used as a roaming
859 * optimization, so the initial connection is not
860 * affected.
861 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700862 } else {
863 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700865 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
866 0);
867 if (scan_res) {
868 bgscan_notify_scan(wpa_s, scan_res);
869 wpa_scan_results_free(scan_res);
870 }
871 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 } else
873 wpa_s->bgscan_ssid = NULL;
874}
875
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876#endif /* CONFIG_BGSCAN */
877
878
Dmitry Shmidt04949592012-07-19 12:16:46 -0700879static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
880{
881 if (autoscan_init(wpa_s, 0))
882 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
883}
884
885
886static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
887{
888 autoscan_deinit(wpa_s);
889}
890
891
892void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
893{
894 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
895 wpa_s->wpa_state == WPA_SCANNING) {
896 autoscan_deinit(wpa_s);
897 wpa_supplicant_start_autoscan(wpa_s);
898 }
899}
900
901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902/**
903 * wpa_supplicant_set_state - Set current connection state
904 * @wpa_s: Pointer to wpa_supplicant data
905 * @state: The new connection state
906 *
907 * This function is called whenever the connection state changes, e.g.,
908 * association is completed for WPA/WPA2 4-Way Handshake is started.
909 */
910void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
911 enum wpa_states state)
912{
913 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700914#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700915 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700916#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917
918 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
919 wpa_supplicant_state_txt(wpa_s->wpa_state),
920 wpa_supplicant_state_txt(state));
921
Hai Shalom74f70d42019-02-11 14:42:39 -0800922 if (state == WPA_COMPLETED &&
923 os_reltime_initialized(&wpa_s->roam_start)) {
924 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
925 wpa_s->roam_start.sec = 0;
926 wpa_s->roam_start.usec = 0;
927 wpas_notify_auth_changed(wpa_s);
928 wpas_notify_roam_time(wpa_s);
929 wpas_notify_roam_complete(wpa_s);
930 } else if (state == WPA_DISCONNECTED &&
931 os_reltime_initialized(&wpa_s->roam_start)) {
932 wpa_s->roam_start.sec = 0;
933 wpa_s->roam_start.usec = 0;
934 wpa_s->roam_time.sec = 0;
935 wpa_s->roam_time.usec = 0;
936 wpas_notify_roam_complete(wpa_s);
937 }
938
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800939 if (state == WPA_INTERFACE_DISABLED) {
940 /* Assure normal scan when interface is restored */
941 wpa_s->normal_scans = 0;
942 }
943
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700944 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800945 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700946 /* Reinitialize normal_scan counter */
947 wpa_s->normal_scans = 0;
948 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800949
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700950#ifdef CONFIG_P2P
951 /*
952 * P2PS client has to reply to Probe Request frames received on the
953 * group operating channel. Enable Probe Request frame reporting for
954 * P2P connected client in case p2p_cli_probe configuration property is
955 * set to 1.
956 */
957 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
958 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
959 wpa_s->current_ssid->p2p_group) {
960 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
961 wpa_dbg(wpa_s, MSG_DEBUG,
962 "P2P: Enable CLI Probe Request RX reporting");
963 wpa_s->p2p_cli_probe =
964 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
965 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
966 wpa_dbg(wpa_s, MSG_DEBUG,
967 "P2P: Disable CLI Probe Request RX reporting");
968 wpa_s->p2p_cli_probe = 0;
969 wpa_drv_probe_req_report(wpa_s, 0);
970 }
971 }
972#endif /* CONFIG_P2P */
973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 if (state != WPA_SCANNING)
975 wpa_supplicant_notify_scanning(wpa_s, 0);
976
977 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700979 int fils_hlp_sent = 0;
980
981#ifdef CONFIG_SME
982 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
983 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
984 fils_hlp_sent = 1;
985#endif /* CONFIG_SME */
986 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
987 wpa_auth_alg_fils(wpa_s->auth_alg))
988 fils_hlp_sent = 1;
989
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700990#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700992 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800993 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700995 ssid && ssid->id_str ? ssid->id_str : "",
996 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700997#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700998 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -0700999 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001 wpa_drv_set_operstate(wpa_s, 1);
1002#ifndef IEEE8021X_EAPOL
1003 wpa_drv_set_supp_port(wpa_s, 1);
1004#endif /* IEEE8021X_EAPOL */
1005 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001006 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001008
1009 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001010
1011#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1012 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001013 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001014#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001015#ifdef CONFIG_OWE
1016 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1017 wpas_update_owe_connect_params(wpa_s);
1018#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001019#ifdef CONFIG_HS20
1020 hs20_configure_frame_filters(wpa_s);
1021#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1023 state == WPA_ASSOCIATED) {
1024 wpa_s->new_connection = 1;
1025 wpa_drv_set_operstate(wpa_s, 0);
1026#ifndef IEEE8021X_EAPOL
1027 wpa_drv_set_supp_port(wpa_s, 0);
1028#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001029 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 }
1031 wpa_s->wpa_state = state;
1032
1033#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001034 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1035 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001036 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 wpa_supplicant_stop_bgscan(wpa_s);
1038#endif /* CONFIG_BGSCAN */
1039
Hai Shalom5f92bc92019-04-18 11:54:11 -07001040 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001041 wpa_supplicant_stop_autoscan(wpa_s);
1042
1043 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1044 wpa_supplicant_start_autoscan(wpa_s);
1045
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001046 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1047 wmm_ac_notify_disassoc(wpa_s);
1048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 if (wpa_s->wpa_state != old_state) {
1050 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1051
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001052 /*
1053 * Notify the P2P Device interface about a state change in one
1054 * of the interfaces.
1055 */
1056 wpas_p2p_indicate_state_change(wpa_s);
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 if (wpa_s->wpa_state == WPA_COMPLETED ||
1059 old_state == WPA_COMPLETED)
1060 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001061#ifdef CONFIG_DPP2
1062 if (wpa_s->wpa_state == WPA_COMPLETED)
1063 wpas_dpp_connected(wpa_s);
1064#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065 }
Hai Shalomc3565922019-10-28 11:58:20 -07001066#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1067 if (update_fils_connect_params)
1068 wpas_update_fils_connect_params(wpa_s);
1069#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070}
1071
1072
1073void wpa_supplicant_terminate_proc(struct wpa_global *global)
1074{
1075 int pending = 0;
1076#ifdef CONFIG_WPS
1077 struct wpa_supplicant *wpa_s = global->ifaces;
1078 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001079 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001080 if (wpas_wps_terminate_pending(wpa_s) == 1)
1081 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001082#ifdef CONFIG_P2P
1083 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1084 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1085 wpas_p2p_disconnect(wpa_s);
1086#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088 }
1089#endif /* CONFIG_WPS */
1090 if (pending)
1091 return;
1092 eloop_terminate();
1093}
1094
1095
1096static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1097{
1098 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 wpa_supplicant_terminate_proc(global);
1100}
1101
1102
1103void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1104{
1105 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001106 enum wpa_states new_state;
1107
1108 if (old_state == WPA_SCANNING)
1109 new_state = WPA_SCANNING;
1110 else
1111 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112
1113 wpa_s->pairwise_cipher = 0;
1114 wpa_s->group_cipher = 0;
1115 wpa_s->mgmt_group_cipher = 0;
1116 wpa_s->key_mgmt = 0;
1117 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001118 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119
1120 if (wpa_s->wpa_state != old_state)
1121 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1122}
1123
1124
1125/**
1126 * wpa_supplicant_reload_configuration - Reload configuration data
1127 * @wpa_s: Pointer to wpa_supplicant data
1128 * Returns: 0 on success or -1 if configuration parsing failed
1129 *
1130 * This function can be used to request that the configuration data is reloaded
1131 * (e.g., after configuration file change). This function is reloading
1132 * configuration only for one interface, so this may need to be called multiple
1133 * times if %wpa_supplicant is controlling multiple interfaces and all
1134 * interfaces need reconfiguration.
1135 */
1136int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1137{
1138 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 int reconf_ctrl;
1140 int old_ap_scan;
1141
1142 if (wpa_s->confname == NULL)
1143 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001144 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145 if (conf == NULL) {
1146 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1147 "file '%s' - exiting", wpa_s->confname);
1148 return -1;
1149 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001150 if (wpa_s->confanother &&
1151 !wpa_config_read(wpa_s->confanother, conf)) {
1152 wpa_msg(wpa_s, MSG_ERROR,
1153 "Failed to parse the configuration file '%s' - exiting",
1154 wpa_s->confanother);
1155 return -1;
1156 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001157
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 conf->changed_parameters = (unsigned int) -1;
1159
1160 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1161 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1162 os_strcmp(conf->ctrl_interface,
1163 wpa_s->conf->ctrl_interface) != 0);
1164
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001165 if (reconf_ctrl) {
1166 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 wpa_s->ctrl_iface = NULL;
1168 }
1169
1170 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001171 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001172 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1173 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001174 wpa_supplicant_deauthenticate(wpa_s,
1175 WLAN_REASON_DEAUTH_LEAVING);
1176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177
1178 /*
1179 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001182 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1183 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1184 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 /*
1186 * Clear forced success to clear EAP state for next
1187 * authentication.
1188 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001189 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 }
1191 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1192 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001193 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1195 rsn_preauth_deinit(wpa_s->wpa);
1196
1197 old_ap_scan = wpa_s->conf->ap_scan;
1198 wpa_config_free(wpa_s->conf);
1199 wpa_s->conf = conf;
1200 if (old_ap_scan != wpa_s->conf->ap_scan)
1201 wpas_notify_ap_scan_changed(wpa_s);
1202
1203 if (reconf_ctrl)
1204 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1205
1206 wpa_supplicant_update_config(wpa_s);
1207
1208 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001209 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_s->reassociate = 1;
1211 wpa_supplicant_req_scan(wpa_s, 0, 0);
1212 }
Hai Shalom60840252021-02-19 19:02:11 -08001213 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1215 return 0;
1216}
1217
1218
1219static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1220{
1221 struct wpa_global *global = signal_ctx;
1222 struct wpa_supplicant *wpa_s;
1223 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1224 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1225 sig);
1226 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1227 wpa_supplicant_terminate_proc(global);
1228 }
1229 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001230
1231 if (wpa_debug_reopen_file() < 0) {
1232 /* Ignore errors since we cannot really do much to fix this */
1233 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235}
1236
1237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1239 struct wpa_ssid *ssid,
1240 struct wpa_ie_data *ie)
1241{
1242 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1243 if (ret) {
1244 if (ret == -2) {
1245 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1246 "from association info");
1247 }
1248 return -1;
1249 }
1250
1251 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1252 "cipher suites");
1253 if (!(ie->group_cipher & ssid->group_cipher)) {
1254 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1255 "cipher 0x%x (mask 0x%x) - reject",
1256 ie->group_cipher, ssid->group_cipher);
1257 return -1;
1258 }
1259 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1260 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1261 "cipher 0x%x (mask 0x%x) - reject",
1262 ie->pairwise_cipher, ssid->pairwise_cipher);
1263 return -1;
1264 }
1265 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1266 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1267 "management 0x%x (mask 0x%x) - reject",
1268 ie->key_mgmt, ssid->key_mgmt);
1269 return -1;
1270 }
1271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001272 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001273 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1275 "that does not support management frame protection - "
1276 "reject");
1277 return -1;
1278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279
1280 return 0;
1281}
1282
1283
Hai Shalom021b0b52019-04-10 11:17:58 -07001284static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1285 int freq)
1286{
1287 if (!ie->has_group)
1288 ie->group_cipher = wpa_default_rsn_cipher(freq);
1289 if (!ie->has_pairwise)
1290 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1291 return (ie->group_cipher & ssid->group_cipher) &&
1292 (ie->pairwise_cipher & ssid->pairwise_cipher);
1293}
1294
1295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296/**
1297 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1298 * @wpa_s: Pointer to wpa_supplicant data
1299 * @bss: Scan results for the selected BSS, or %NULL if not available
1300 * @ssid: Configuration data for the selected network
1301 * @wpa_ie: Buffer for the WPA/RSN IE
1302 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1303 * used buffer length in case the functions returns success.
1304 * Returns: 0 on success or -1 on failure
1305 *
1306 * This function is used to configure authentication and encryption parameters
1307 * based on the network configuration and scan result for the selected BSS (if
1308 * available).
1309 */
1310int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1311 struct wpa_bss *bss, struct wpa_ssid *ssid,
1312 u8 *wpa_ie, size_t *wpa_ie_len)
1313{
1314 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001315 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001316 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317
1318 if (bss) {
1319 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1320 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001321 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001322 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001323 } else {
1324 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1325 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001326
1327 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1328 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001329 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 (ie.key_mgmt & ssid->key_mgmt)) {
1331 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1332 proto = WPA_PROTO_RSN;
1333 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001334 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335 (ie.group_cipher & ssid->group_cipher) &&
1336 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1337 (ie.key_mgmt & ssid->key_mgmt)) {
1338 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1339 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001340#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001341 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1342 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1343 (ie.group_cipher & ssid->group_cipher) &&
1344 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1345 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001346 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001347 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001348 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1349 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1350 (ie.group_cipher & ssid->group_cipher) &&
1351 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1352 (ie.key_mgmt & ssid->key_mgmt)) {
1353 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1354 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001355#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356 } else if (bss) {
1357 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001358 wpa_dbg(wpa_s, MSG_DEBUG,
1359 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1360 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1361 ssid->key_mgmt);
1362 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1363 MAC2STR(bss->bssid),
1364 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1365 bss_wpa ? " WPA" : "",
1366 bss_rsn ? " RSN" : "",
1367 bss_osen ? " OSEN" : "");
1368 if (bss_rsn) {
1369 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1370 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1371 wpa_dbg(wpa_s, MSG_DEBUG,
1372 "Could not parse RSN element");
1373 } else {
1374 wpa_dbg(wpa_s, MSG_DEBUG,
1375 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1376 ie.pairwise_cipher, ie.group_cipher,
1377 ie.key_mgmt);
1378 }
1379 }
1380 if (bss_wpa) {
1381 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1382 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1383 wpa_dbg(wpa_s, MSG_DEBUG,
1384 "Could not parse WPA element");
1385 } else {
1386 wpa_dbg(wpa_s, MSG_DEBUG,
1387 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1388 ie.pairwise_cipher, ie.group_cipher,
1389 ie.key_mgmt);
1390 }
1391 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 return -1;
1393 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001394 if (ssid->proto & WPA_PROTO_OSEN)
1395 proto = WPA_PROTO_OSEN;
1396 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 proto = WPA_PROTO_RSN;
1398 else
1399 proto = WPA_PROTO_WPA;
1400 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1401 os_memset(&ie, 0, sizeof(ie));
1402 ie.group_cipher = ssid->group_cipher;
1403 ie.pairwise_cipher = ssid->pairwise_cipher;
1404 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405 ie.mgmt_group_cipher = 0;
1406 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1407 if (ssid->group_mgmt_cipher &
1408 WPA_CIPHER_BIP_GMAC_256)
1409 ie.mgmt_group_cipher =
1410 WPA_CIPHER_BIP_GMAC_256;
1411 else if (ssid->group_mgmt_cipher &
1412 WPA_CIPHER_BIP_CMAC_256)
1413 ie.mgmt_group_cipher =
1414 WPA_CIPHER_BIP_CMAC_256;
1415 else if (ssid->group_mgmt_cipher &
1416 WPA_CIPHER_BIP_GMAC_128)
1417 ie.mgmt_group_cipher =
1418 WPA_CIPHER_BIP_GMAC_128;
1419 else
1420 ie.mgmt_group_cipher =
1421 WPA_CIPHER_AES_128_CMAC;
1422 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001423#ifdef CONFIG_OWE
1424 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1425 !ssid->owe_only &&
1426 !bss_wpa && !bss_rsn && !bss_osen) {
1427 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1428 wpa_s->wpa_proto = 0;
1429 *wpa_ie_len = 0;
1430 return 0;
1431 }
1432#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1434 "based on configuration");
1435 } else
1436 proto = ie.proto;
1437 }
1438
1439 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1440 "pairwise %d key_mgmt %d proto %d",
1441 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 if (ssid->ieee80211w) {
1443 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1444 ie.mgmt_group_cipher);
1445 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001447 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001450 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451
1452 if (bss || !wpa_s->ap_ies_from_associnfo) {
1453 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1454 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1455 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001456 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1457 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1458 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 return -1;
1460 }
1461
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001462#ifdef CONFIG_NO_WPA
1463 wpa_s->group_cipher = WPA_CIPHER_NONE;
1464 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1465#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001467 wpa_dbg(wpa_s, MSG_DEBUG,
1468 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1469 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001470 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1471 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1473 "cipher");
1474 return -1;
1475 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001476 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1477 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478
1479 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001480 wpa_dbg(wpa_s, MSG_DEBUG,
1481 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1482 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001483 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1484 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1486 "cipher");
1487 return -1;
1488 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001489 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1490 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001491#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492
1493 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001494#ifdef CONFIG_SAE
1495 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1496 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1497#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001498#ifdef CONFIG_IEEE80211R
1499 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1500 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1501 sel &= ~WPA_KEY_MGMT_FT;
1502#endif /* CONFIG_IEEE80211R */
1503 wpa_dbg(wpa_s, MSG_DEBUG,
1504 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1505 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001507#ifdef CONFIG_IEEE80211R
1508#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001509 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1510 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1512 wpa_dbg(wpa_s, MSG_DEBUG,
1513 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001514 if (!ssid->ft_eap_pmksa_caching &&
1515 pmksa_cache_get_current(wpa_s->wpa)) {
1516 /* PMKSA caching with FT may have interoperability
1517 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001518 wpa_dbg(wpa_s, MSG_DEBUG,
1519 "WPA: Disable PMKSA caching for FT/802.1X connection");
1520 pmksa_cache_clear_current(wpa_s->wpa);
1521 }
1522#endif /* CONFIG_SHA384 */
1523#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001524#ifdef CONFIG_SUITEB192
1525 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1526 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1527 wpa_dbg(wpa_s, MSG_DEBUG,
1528 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1529#endif /* CONFIG_SUITEB192 */
1530#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001531 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1532 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1533 wpa_dbg(wpa_s, MSG_DEBUG,
1534 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001535#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001536#ifdef CONFIG_FILS
1537#ifdef CONFIG_IEEE80211R
1538 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1539 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1540 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1541 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1544#endif /* CONFIG_IEEE80211R */
1545 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1546 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1547 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1548 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1549 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1550 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1551#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001553 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1554 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001557 if (!ssid->ft_eap_pmksa_caching &&
1558 pmksa_cache_get_current(wpa_s->wpa)) {
1559 /* PMKSA caching with FT may have interoperability
1560 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001561 wpa_dbg(wpa_s, MSG_DEBUG,
1562 "WPA: Disable PMKSA caching for FT/802.1X connection");
1563 pmksa_cache_clear_current(wpa_s->wpa);
1564 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001565#endif /* CONFIG_IEEE80211R */
1566#ifdef CONFIG_DPP
1567 } else if (sel & WPA_KEY_MGMT_DPP) {
1568 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1569 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1570#endif /* CONFIG_DPP */
1571#ifdef CONFIG_SAE
1572 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1575 } else if (sel & WPA_KEY_MGMT_SAE) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1577 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1578#endif /* CONFIG_SAE */
1579#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1581 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1582 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1583#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1585 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1586 wpa_dbg(wpa_s, MSG_DEBUG,
1587 "WPA: using KEY_MGMT 802.1X with SHA256");
1588 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1589 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1590 wpa_dbg(wpa_s, MSG_DEBUG,
1591 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1593 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1594 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1595 } else if (sel & WPA_KEY_MGMT_PSK) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1598 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1599 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1600 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001601#ifdef CONFIG_HS20
1602 } else if (sel & WPA_KEY_MGMT_OSEN) {
1603 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1604 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1605#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001606#ifdef CONFIG_OWE
1607 } else if (sel & WPA_KEY_MGMT_OWE) {
1608 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1609 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1610#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 } else {
1612 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1613 "authenticated key management type");
1614 return -1;
1615 }
1616
1617 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1618 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1619 wpa_s->pairwise_cipher);
1620 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1621
Hai Shalomc3565922019-10-28 11:58:20 -07001622 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1623 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1624 wpa_msg(wpa_s, MSG_INFO,
1625 "RSN: Management frame protection required but the selected AP does not enable it");
1626 return -1;
1627 }
1628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001630 if (ssid->group_mgmt_cipher)
1631 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001632 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1634 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001635 wpa_dbg(wpa_s, MSG_DEBUG,
1636 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1637 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001638 if (sel & WPA_CIPHER_AES_128_CMAC) {
1639 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1640 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1641 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001642 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1643 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1644 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1645 "BIP-GMAC-128");
1646 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1647 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1648 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1649 "BIP-GMAC-256");
1650 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1651 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1652 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1653 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 } else {
1655 wpa_s->mgmt_group_cipher = 0;
1656 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1657 }
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1659 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001660 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001661 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001662#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001663 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1664 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001666#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001667 sae_pwe = wpa_s->conf->sae_pwe;
1668 if (ssid->sae_password_id && sae_pwe != 3)
1669 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001670 if (bss && is_6ghz_freq(bss->freq)) {
1671 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1672 sae_pwe = 1;
1673 }
1674#ifdef CONFIG_TESTING_OPTIONS
1675 if (wpa_s->force_hunting_and_pecking_pwe) {
1676 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1677 sae_pwe = 0;
1678 }
1679#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001680 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001681#ifdef CONFIG_SAE_PK
1682 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1683 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1684 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1685 ((ssid->sae_password &&
1686 sae_pk_valid_password(ssid->sae_password)) ||
1687 (!ssid->sae_password && ssid->passphrase &&
1688 sae_pk_valid_password(ssid->passphrase))));
1689#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001690#ifdef CONFIG_TESTING_OPTIONS
1691 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1692 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001693 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1694 wpa_s->oci_freq_override_eapol);
1695 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1696 wpa_s->oci_freq_override_eapol_g2);
1697 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1698 wpa_s->oci_freq_override_ft_assoc);
1699 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1700 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001701#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001702
1703 /* Extended Key ID is only supported in infrastructure BSS so far */
1704 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1705 (ssid->proto & WPA_PROTO_RSN) &&
1706 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1707 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1708 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1709 int use_ext_key_id = 0;
1710
1711 wpa_msg(wpa_s, MSG_DEBUG,
1712 "WPA: Enable Extended Key ID support");
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1714 wpa_s->conf->extended_key_id);
1715 if (bss_rsn &&
1716 wpa_s->conf->extended_key_id &&
1717 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1718 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1719 use_ext_key_id = 1;
1720 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1721 use_ext_key_id);
1722 } else {
1723 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1724 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1725 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726
1727 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1728 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1729 return -1;
1730 }
1731
Hai Shalomc3565922019-10-28 11:58:20 -07001732 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1733 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1734 &wpa_s->rsnxe_len)) {
1735 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1736 return -1;
1737 }
1738
Hai Shalom021b0b52019-04-10 11:17:58 -07001739 if (0) {
1740#ifdef CONFIG_DPP
1741 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1742 /* Use PMK from DPP network introduction (PMKSA entry) */
1743 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001744#ifdef CONFIG_DPP2
1745 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1746#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001747#endif /* CONFIG_DPP */
1748 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001749 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001750 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001751
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1753 WPA_KEY_MGMT_FT_PSK |
1754 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1755
1756 if (ssid->psk_set && !sae_only) {
1757 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1758 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001759 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1760 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001761 psk_set = 1;
1762 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001763
Roshan Pius3a1667e2018-07-03 15:17:14 -07001764 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1765 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001766 psk_set = 1;
1767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001768#ifndef CONFIG_NO_PBKDF2
1769 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001771 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001772 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1773 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001774 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1775 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001776 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001777 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001778 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001779 }
1780#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001781#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001782 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001783 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1784 ssid->ext_psk);
1785 char pw_str[64 + 1];
1786 u8 psk[PMK_LEN];
1787
1788 if (pw == NULL) {
1789 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1790 "found from external storage");
1791 return -1;
1792 }
1793
1794 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1795 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1796 "PSK length %d in external storage",
1797 (int) wpabuf_len(pw));
1798 ext_password_free(pw);
1799 return -1;
1800 }
1801
1802 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1803 pw_str[wpabuf_len(pw)] = '\0';
1804
1805#ifndef CONFIG_NO_PBKDF2
1806 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1807 {
1808 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1809 4096, psk, PMK_LEN);
1810 os_memset(pw_str, 0, sizeof(pw_str));
1811 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1812 "external passphrase)",
1813 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001814 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1815 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001816 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001817 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001818 } else
1819#endif /* CONFIG_NO_PBKDF2 */
1820 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1821 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1822 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1823 "Invalid PSK hex string");
1824 os_memset(pw_str, 0, sizeof(pw_str));
1825 ext_password_free(pw);
1826 return -1;
1827 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001828 wpa_hexdump_key(MSG_MSGDUMP,
1829 "PSK (from external PSK)",
1830 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001831 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1832 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001833 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001834 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001835 } else {
1836 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1837 "PSK available");
1838 os_memset(pw_str, 0, sizeof(pw_str));
1839 ext_password_free(pw);
1840 return -1;
1841 }
1842
1843 os_memset(pw_str, 0, sizeof(pw_str));
1844 ext_password_free(pw);
1845 }
1846#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001847
1848 if (!psk_set) {
1849 wpa_msg(wpa_s, MSG_INFO,
1850 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001851 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001852 return -1;
1853 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001854#ifdef CONFIG_OWE
1855 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1856 /* OWE Diffie-Hellman exchange in (Re)Association
1857 * Request/Response frames set the PMK, so do not override it
1858 * here. */
1859#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001860 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1862
Hai Shalomfdcde762020-04-02 11:19:20 -07001863 if (ssid->mode != WPAS_MODE_IBSS &&
1864 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1865 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1866 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1867 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1868 wpa_msg(wpa_s, MSG_INFO,
1869 "Disable PTK0 rekey support - replaced with reconnect");
1870 wpa_s->deny_ptk0_rekey = 1;
1871 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1872 } else {
1873 wpa_s->deny_ptk0_rekey = 0;
1874 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1875 }
1876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 return 0;
1878}
1879
1880
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001881static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1882{
1883 *pos = 0x00;
1884
1885 switch (idx) {
1886 case 0: /* Bits 0-7 */
1887 break;
1888 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001889 if (wpa_s->conf->coloc_intf_reporting) {
1890 /* Bit 13 - Collocated Interference Reporting */
1891 *pos |= 0x20;
1892 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001893 break;
1894 case 2: /* Bits 16-23 */
1895#ifdef CONFIG_WNM
1896 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001897 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001898 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001899#endif /* CONFIG_WNM */
1900 break;
1901 case 3: /* Bits 24-31 */
1902#ifdef CONFIG_WNM
1903 *pos |= 0x02; /* Bit 25 - SSID List */
1904#endif /* CONFIG_WNM */
1905#ifdef CONFIG_INTERWORKING
1906 if (wpa_s->conf->interworking)
1907 *pos |= 0x80; /* Bit 31 - Interworking */
1908#endif /* CONFIG_INTERWORKING */
1909 break;
1910 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001911#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001912 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001913 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001914#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001915 break;
1916 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001917#ifdef CONFIG_HS20
1918 if (wpa_s->conf->hs20)
1919 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1920#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001921#ifdef CONFIG_MBO
1922 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1923#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001924 break;
1925 case 6: /* Bits 48-55 */
1926 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001927 case 7: /* Bits 56-63 */
1928 break;
1929 case 8: /* Bits 64-71 */
1930 if (wpa_s->conf->ftm_responder)
1931 *pos |= 0x40; /* Bit 70 - FTM responder */
1932 if (wpa_s->conf->ftm_initiator)
1933 *pos |= 0x80; /* Bit 71 - FTM initiator */
1934 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001935 case 9: /* Bits 72-79 */
1936#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001937 if (!wpa_s->disable_fils)
1938 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001939#endif /* CONFIG_FILS */
1940 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001941 case 10: /* Bits 80-87 */
1942 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
1943 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001944 }
1945}
1946
1947
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001948int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001949{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001950 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001951 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001952
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001953 if (len < wpa_s->extended_capa_len)
1954 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001955 if (buflen < (size_t) len + 2) {
1956 wpa_printf(MSG_INFO,
1957 "Not enough room for building extended capabilities element");
1958 return -1;
1959 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001960
1961 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001962 *pos++ = len;
1963 for (i = 0; i < len; i++, pos++) {
1964 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001965
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001966 if (i < wpa_s->extended_capa_len) {
1967 *pos &= ~wpa_s->extended_capa_mask[i];
1968 *pos |= wpa_s->extended_capa[i];
1969 }
1970 }
1971
1972 while (len > 0 && buf[1 + len] == 0) {
1973 len--;
1974 buf[1] = len;
1975 }
1976 if (len == 0)
1977 return 0;
1978
1979 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001980}
1981
1982
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001983static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1984 struct wpa_bss *test_bss)
1985{
1986 struct wpa_bss *bss;
1987
1988 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1989 if (bss == test_bss)
1990 return 1;
1991 }
1992
1993 return 0;
1994}
1995
1996
1997static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1998 struct wpa_ssid *test_ssid)
1999{
2000 struct wpa_ssid *ssid;
2001
2002 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2003 if (ssid == test_ssid)
2004 return 1;
2005 }
2006
2007 return 0;
2008}
2009
2010
2011int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2012 struct wpa_ssid *test_ssid)
2013{
2014 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2015 return 0;
2016
2017 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2018}
2019
2020
2021void wpas_connect_work_free(struct wpa_connect_work *cwork)
2022{
2023 if (cwork == NULL)
2024 return;
2025 os_free(cwork);
2026}
2027
2028
2029void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2030{
2031 struct wpa_connect_work *cwork;
2032 struct wpa_radio_work *work = wpa_s->connect_work;
2033
2034 if (!work)
2035 return;
2036
2037 wpa_s->connect_work = NULL;
2038 cwork = work->ctx;
2039 work->ctx = NULL;
2040 wpas_connect_work_free(cwork);
2041 radio_work_done(work);
2042}
2043
2044
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002045int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2046{
2047 struct os_reltime now;
2048 u8 addr[ETH_ALEN];
2049
2050 os_get_reltime(&now);
2051 if (wpa_s->last_mac_addr_style == style &&
2052 wpa_s->last_mac_addr_change.sec != 0 &&
2053 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2054 wpa_s->conf->rand_addr_lifetime)) {
2055 wpa_msg(wpa_s, MSG_DEBUG,
2056 "Previously selected random MAC address has not yet expired");
2057 return 0;
2058 }
2059
2060 switch (style) {
2061 case 1:
2062 if (random_mac_addr(addr) < 0)
2063 return -1;
2064 break;
2065 case 2:
2066 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2067 if (random_mac_addr_keep_oui(addr) < 0)
2068 return -1;
2069 break;
2070 default:
2071 return -1;
2072 }
2073
2074 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2075 wpa_msg(wpa_s, MSG_INFO,
2076 "Failed to set random MAC address");
2077 return -1;
2078 }
2079
2080 os_get_reltime(&wpa_s->last_mac_addr_change);
2081 wpa_s->mac_addr_changed = 1;
2082 wpa_s->last_mac_addr_style = style;
2083
2084 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2085 wpa_msg(wpa_s, MSG_INFO,
2086 "Could not update MAC address information");
2087 return -1;
2088 }
2089
2090 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2091 MAC2STR(addr));
2092
2093 return 0;
2094}
2095
2096
2097int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2098{
2099 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2100 !wpa_s->conf->preassoc_mac_addr)
2101 return 0;
2102
2103 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2104}
2105
2106
Hai Shalomc3565922019-10-28 11:58:20 -07002107static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2108{
2109#ifdef CONFIG_SAE
2110 int *groups = conf->sae_groups;
2111 int default_groups[] = { 19, 20, 21, 0 };
2112 const char *password;
2113
2114 if (!groups || groups[0] <= 0)
2115 groups = default_groups;
2116
2117 password = ssid->sae_password;
2118 if (!password)
2119 password = ssid->passphrase;
2120
Hai Shalom899fcc72020-10-19 14:38:18 -07002121 if (!password ||
2122 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2123 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002124 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002125 /* PT derivation not needed */
2126 sae_deinit_pt(ssid->pt);
2127 ssid->pt = NULL;
2128 return;
2129 }
2130
2131 if (ssid->pt)
2132 return; /* PT already derived */
2133 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2134 (const u8 *) password, os_strlen(password),
2135 ssid->sae_password_id);
2136#endif /* CONFIG_SAE */
2137}
2138
2139
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002140static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2141{
2142#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2143 os_free(wpa_s->sme.sae_rejected_groups);
2144 wpa_s->sme.sae_rejected_groups = NULL;
2145#ifdef CONFIG_TESTING_OPTIONS
2146 if (wpa_s->extra_sae_rejected_groups) {
2147 int i, *groups = wpa_s->extra_sae_rejected_groups;
2148
2149 for (i = 0; groups[i]; i++) {
2150 wpa_printf(MSG_DEBUG,
2151 "TESTING: Indicate rejection of an extra SAE group %d",
2152 groups[i]);
2153 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2154 groups[i]);
2155 }
2156 }
2157#endif /* CONFIG_TESTING_OPTIONS */
2158#endif /* CONFIG_SAE && CONFIG_SME */
2159}
2160
2161
Hai Shalom60840252021-02-19 19:02:11 -08002162int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2163{
2164 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2165 wpa_msg(wpa_s, MSG_INFO,
2166 "Could not restore permanent MAC address");
2167 return -1;
2168 }
2169 wpa_s->mac_addr_changed = 0;
2170 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2171 wpa_msg(wpa_s, MSG_INFO,
2172 "Could not update MAC address information");
2173 return -1;
2174 }
2175 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2176 return 0;
2177}
2178
2179
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002180static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182/**
2183 * wpa_supplicant_associate - Request association
2184 * @wpa_s: Pointer to wpa_supplicant data
2185 * @bss: Scan results for the selected BSS, or %NULL if not available
2186 * @ssid: Configuration data for the selected network
2187 *
2188 * This function is used to request %wpa_supplicant to associate with a BSS.
2189 */
2190void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2191 struct wpa_bss *bss, struct wpa_ssid *ssid)
2192{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002193 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002194 int rand_style;
2195
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002196 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002197 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002198
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002199 /*
2200 * If we are starting a new connection, any previously pending EAPOL
2201 * RX cannot be valid anymore.
2202 */
2203 wpabuf_free(wpa_s->pending_eapol_rx);
2204 wpa_s->pending_eapol_rx = NULL;
2205
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002206 if (ssid->mac_addr == -1)
2207 rand_style = wpa_s->conf->mac_addr;
2208 else
2209 rand_style = ssid->mac_addr;
2210
Hai Shalomfdcde762020-04-02 11:19:20 -07002211 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002212 wmm_ac_clear_saved_tspecs(wpa_s);
2213 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002214 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002215#ifdef CONFIG_TESTING_OPTIONS
2216 wpa_s->testing_resend_assoc = 0;
2217#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002218
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002219 if (wpa_s->last_ssid == ssid) {
2220 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002221 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002222 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2223 wmm_ac_save_tspecs(wpa_s);
2224 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002225 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2226 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002227 }
Hai Shalomc3565922019-10-28 11:58:20 -07002228 } else {
2229#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002230 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002231 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2232#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002233 }
2234
2235 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002236 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2237 return;
2238 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002239 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002240 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002241 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002242 }
2243 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244
2245#ifdef CONFIG_IBSS_RSN
2246 ibss_rsn_deinit(wpa_s->ibss_rsn);
2247 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002248#else /* CONFIG_IBSS_RSN */
2249 if (ssid->mode == WPAS_MODE_IBSS &&
2250 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2251 wpa_msg(wpa_s, MSG_INFO,
2252 "IBSS RSN not supported in the build");
2253 return;
2254 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255#endif /* CONFIG_IBSS_RSN */
2256
2257 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2258 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2259#ifdef CONFIG_AP
2260 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2261 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2262 "mode");
2263 return;
2264 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002265 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2266 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002267 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2268 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002269 return;
2270 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 wpa_s->current_bss = bss;
2272#else /* CONFIG_AP */
2273 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2274 "the build");
2275#endif /* CONFIG_AP */
2276 return;
2277 }
2278
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002279 if (ssid->mode == WPAS_MODE_MESH) {
2280#ifdef CONFIG_MESH
2281 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2282 wpa_msg(wpa_s, MSG_INFO,
2283 "Driver does not support mesh mode");
2284 return;
2285 }
2286 if (bss)
2287 ssid->frequency = bss->freq;
2288 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2289 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2290 return;
2291 }
2292 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002293#else /* CONFIG_MESH */
2294 wpa_msg(wpa_s, MSG_ERROR,
2295 "mesh mode support not included in the build");
2296#endif /* CONFIG_MESH */
2297 return;
2298 }
2299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002300 /*
2301 * Set WPA state machine configuration to match the selected network now
2302 * so that the information is available before wpas_start_assoc_cb()
2303 * gets called. This is needed at least for RSN pre-authentication where
2304 * candidate APs are added to a list based on scan result processing
2305 * before completion of the first association.
2306 */
2307 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2308
2309#ifdef CONFIG_DPP
2310 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2311 return;
2312#endif /* CONFIG_DPP */
2313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314#ifdef CONFIG_TDLS
2315 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002316 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002317#endif /* CONFIG_TDLS */
2318
Hai Shalomc3565922019-10-28 11:58:20 -07002319#ifdef CONFIG_MBO
2320 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2321#endif /* CONFIG_MBO */
2322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002323 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002324 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325 sme_authenticate(wpa_s, bss, ssid);
2326 return;
2327 }
2328
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002329 if (wpa_s->connect_work) {
2330 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2331 return;
2332 }
2333
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002334 if (radio_work_pending(wpa_s, "connect")) {
2335 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2336 return;
2337 }
2338
Dmitry Shmidt29333592017-01-09 12:27:11 -08002339#ifdef CONFIG_SME
2340 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2341 /* Clear possibly set auth_alg, if any, from last attempt. */
2342 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2343 }
2344#endif /* CONFIG_SME */
2345
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002346 wpas_abort_ongoing_scan(wpa_s);
2347
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002348 cwork = os_zalloc(sizeof(*cwork));
2349 if (cwork == NULL)
2350 return;
2351
2352 cwork->bss = bss;
2353 cwork->ssid = ssid;
2354
2355 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2356 wpas_start_assoc_cb, cwork) < 0) {
2357 os_free(cwork);
2358 }
2359}
2360
2361
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002362static int bss_is_ibss(struct wpa_bss *bss)
2363{
2364 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2365 IEEE80211_CAP_IBSS;
2366}
2367
2368
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002369static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2370 const struct wpa_ssid *ssid)
2371{
2372 enum hostapd_hw_mode hw_mode;
2373 struct hostapd_hw_modes *mode = NULL;
2374 u8 channel;
2375 int i;
2376
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002377 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2378 if (hw_mode == NUM_HOSTAPD_MODES)
2379 return 0;
2380 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2381 if (wpa_s->hw.modes[i].mode == hw_mode) {
2382 mode = &wpa_s->hw.modes[i];
2383 break;
2384 }
2385 }
2386
2387 if (!mode)
2388 return 0;
2389
2390 return mode->vht_capab != 0;
2391}
2392
2393
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002394void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2395 const struct wpa_ssid *ssid,
2396 struct hostapd_freq_params *freq)
2397{
Hai Shalom81f62d82019-07-22 12:10:00 -07002398 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002399 enum hostapd_hw_mode hw_mode;
2400 struct hostapd_hw_modes *mode = NULL;
2401 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2402 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002403 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002404 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2405 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002406 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002407 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002408 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002409 int chwidth, seg0, seg1;
2410 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002411 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002412
2413 freq->freq = ssid->frequency;
2414
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002415 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2416 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2417
2418 if (ssid->mode != WPAS_MODE_IBSS)
2419 break;
2420
2421 /* Don't adjust control freq in case of fixed_freq */
2422 if (ssid->fixed_freq)
2423 break;
2424
2425 if (!bss_is_ibss(bss))
2426 continue;
2427
2428 if (ssid->ssid_len == bss->ssid_len &&
2429 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2430 wpa_printf(MSG_DEBUG,
2431 "IBSS already found in scan results, adjust control freq: %d",
2432 bss->freq);
2433 freq->freq = bss->freq;
2434 obss_scan = 0;
2435 break;
2436 }
2437 }
2438
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002439 /* For IBSS check HT_IBSS flag */
2440 if (ssid->mode == WPAS_MODE_IBSS &&
2441 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2442 return;
2443
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002444 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2445 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2446 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2447 wpa_printf(MSG_DEBUG,
2448 "IBSS: WEP/TKIP detected, do not try to enable HT");
2449 return;
2450 }
2451
2452 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002453 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2454 if (wpa_s->hw.modes[i].mode == hw_mode) {
2455 mode = &wpa_s->hw.modes[i];
2456 break;
2457 }
2458 }
2459
2460 if (!mode)
2461 return;
2462
Hai Shalom60840252021-02-19 19:02:11 -08002463 freq->channel = channel;
2464
Hai Shalomc3565922019-10-28 11:58:20 -07002465 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2466 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002467
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002468#ifdef CONFIG_HT_OVERRIDES
2469 if (ssid->disable_ht) {
2470 freq->ht_enabled = 0;
2471 return;
2472 }
2473#endif /* CONFIG_HT_OVERRIDES */
2474
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002475 freq->ht_enabled = ht_supported(mode);
2476 if (!freq->ht_enabled)
2477 return;
2478
Hai Shalomc3565922019-10-28 11:58:20 -07002479 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2480 if (is_24ghz)
2481 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002482#ifdef CONFIG_HE_OVERRIDES
2483 if (is_24ghz && ssid->disable_he)
2484 freq->he_enabled = 0;
2485#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002486
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002487 /* Setup higher BW only for 5 GHz */
2488 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2489 return;
2490
2491 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2492 pri_chan = &mode->channels[chan_idx];
2493 if (pri_chan->chan == channel)
2494 break;
2495 pri_chan = NULL;
2496 }
2497 if (!pri_chan)
2498 return;
2499
2500 /* Check primary channel flags */
2501 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2502 return;
2503
Hai Shalom74f70d42019-02-11 14:42:39 -08002504 freq->channel = pri_chan->chan;
2505
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002506#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002507 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002508#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002509 if (ssid->disable_vht)
2510 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002511#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002512 goto skip_ht40;
2513 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002514#endif /* CONFIG_HT_OVERRIDES */
2515
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002516 /* Check/setup HT40+/HT40- */
2517 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2518 if (ht40plus[j] == channel) {
2519 ht40 = 1;
2520 break;
2521 }
2522 }
2523
2524 /* Find secondary channel */
2525 for (i = 0; i < mode->num_channels; i++) {
2526 sec_chan = &mode->channels[i];
2527 if (sec_chan->chan == channel + ht40 * 4)
2528 break;
2529 sec_chan = NULL;
2530 }
2531 if (!sec_chan)
2532 return;
2533
2534 /* Check secondary channel flags */
2535 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2536 return;
2537
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002538 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002539 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2540 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002541 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002542 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2543 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002544 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002545 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002546
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002547 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002548 struct wpa_scan_results *scan_res;
2549
2550 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2551 if (scan_res == NULL) {
2552 /* Back to HT20 */
2553 freq->sec_channel_offset = 0;
2554 return;
2555 }
2556
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002557 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002558 switch (res) {
2559 case 0:
2560 /* Back to HT20 */
2561 freq->sec_channel_offset = 0;
2562 break;
2563 case 1:
2564 /* Configuration allowed */
2565 break;
2566 case 2:
2567 /* Switch pri/sec channels */
2568 freq->freq = hw_get_freq(mode, sec_chan->chan);
2569 freq->sec_channel_offset = -freq->sec_channel_offset;
2570 freq->channel = sec_chan->chan;
2571 break;
2572 default:
2573 freq->sec_channel_offset = 0;
2574 break;
2575 }
2576
2577 wpa_scan_results_free(scan_res);
2578 }
2579
Hai Shalom74f70d42019-02-11 14:42:39 -08002580#ifdef CONFIG_HT_OVERRIDES
2581skip_ht40:
2582#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002583 wpa_printf(MSG_DEBUG,
2584 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2585 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002586
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002587 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002588 return;
2589
2590 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002591 if (ssid->mode == WPAS_MODE_IBSS &&
2592 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002593 return;
2594
2595 vht_freq = *freq;
2596
Paul Stewart092955c2017-02-06 09:13:09 -08002597#ifdef CONFIG_VHT_OVERRIDES
2598 if (ssid->disable_vht) {
2599 freq->vht_enabled = 0;
2600 return;
2601 }
2602#endif /* CONFIG_VHT_OVERRIDES */
2603
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002604 vht_freq.vht_enabled = vht_supported(mode);
2605 if (!vht_freq.vht_enabled)
2606 return;
2607
Hai Shalomfdcde762020-04-02 11:19:20 -07002608 /* Enable HE with VHT for 5 GHz */
2609 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002610
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002611 /* setup center_freq1, bandwidth */
2612 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2613 if (freq->channel >= vht80[j] &&
2614 freq->channel < vht80[j] + 16)
2615 break;
2616 }
2617
2618 if (j == ARRAY_SIZE(vht80))
2619 return;
2620
2621 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2622 struct hostapd_channel_data *chan;
2623
2624 chan = hw_get_channel_chan(mode, i, NULL);
2625 if (!chan)
2626 return;
2627
2628 /* Back to HT configuration if channel not usable */
2629 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2630 return;
2631 }
2632
Hai Shalom81f62d82019-07-22 12:10:00 -07002633 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002634 seg0 = vht80[j] + 6;
2635 seg1 = 0;
2636
Hai Shalom81f62d82019-07-22 12:10:00 -07002637 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002638 /* setup center_freq2, bandwidth */
2639 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2640 /* Only accept 80 MHz segments separated by a gap */
2641 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2642 continue;
2643 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2644 struct hostapd_channel_data *chan;
2645
2646 chan = hw_get_channel_chan(mode, i, NULL);
2647 if (!chan)
2648 continue;
2649
2650 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2651 HOSTAPD_CHAN_NO_IR |
2652 HOSTAPD_CHAN_RADAR))
2653 continue;
2654
2655 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002656 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002657 vht_caps |=
2658 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2659 seg1 = vht80[k] + 6;
2660 }
2661
Hai Shalom81f62d82019-07-22 12:10:00 -07002662 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002663 break;
2664 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002665 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002666 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002667 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002668 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2669 seg0 = 50;
2670 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002671 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002672 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2673 seg0 = 114;
2674 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002675 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2676 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002677 seg0 = vht80[j] + 2;
2678#ifdef CONFIG_HT_OVERRIDES
2679 if (ssid->disable_ht40)
2680 seg0 = 0;
2681#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002682 }
2683
Hai Shalomfdcde762020-04-02 11:19:20 -07002684#ifdef CONFIG_HE_OVERRIDES
2685 if (ssid->disable_he) {
2686 vht_freq.he_enabled = 0;
2687 freq->he_enabled = 0;
2688 }
2689#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002690 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002691 freq->channel, ssid->enable_edmg,
2692 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002693 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002694 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002695 chwidth, seg0, seg1, vht_caps,
2696 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002697 return;
2698
2699 *freq = vht_freq;
2700
2701 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2702 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002703}
2704
2705
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002706#ifdef CONFIG_FILS
2707static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2708 size_t ie_buf_len)
2709{
2710 struct fils_hlp_req *req;
2711 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2712 const u8 *pos;
2713 u8 *buf = ie_buf;
2714
2715 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2716 list) {
2717 rem_len = ie_buf_len - ie_len;
2718 pos = wpabuf_head(req->pkt);
2719 hdr_len = 1 + 2 * ETH_ALEN + 6;
2720 hlp_len = wpabuf_len(req->pkt);
2721
2722 if (rem_len < 2 + hdr_len + hlp_len) {
2723 wpa_printf(MSG_ERROR,
2724 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2725 (unsigned long) rem_len,
2726 (unsigned long) (2 + hdr_len + hlp_len));
2727 break;
2728 }
2729
2730 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2731 /* Element ID */
2732 *buf++ = WLAN_EID_EXTENSION;
2733 /* Length */
2734 *buf++ = len;
2735 /* Element ID Extension */
2736 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2737 /* Destination MAC address */
2738 os_memcpy(buf, req->dst, ETH_ALEN);
2739 buf += ETH_ALEN;
2740 /* Source MAC address */
2741 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2742 buf += ETH_ALEN;
2743 /* LLC/SNAP Header */
2744 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2745 buf += 6;
2746 /* HLP Packet */
2747 os_memcpy(buf, pos, len - hdr_len);
2748 buf += len - hdr_len;
2749 pos += len - hdr_len;
2750
2751 hlp_len -= len - hdr_len;
2752 ie_len += 2 + len;
2753 rem_len -= 2 + len;
2754
2755 while (hlp_len) {
2756 len = (hlp_len > 255) ? 255 : hlp_len;
2757 if (rem_len < 2 + len)
2758 break;
2759 *buf++ = WLAN_EID_FRAGMENT;
2760 *buf++ = len;
2761 os_memcpy(buf, pos, len);
2762 buf += len;
2763 pos += len;
2764
2765 hlp_len -= len;
2766 ie_len += 2 + len;
2767 rem_len -= 2 + len;
2768 }
2769 }
2770
2771 return ie_len;
2772}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002773
2774
2775int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2776{
2777 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2778 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2779 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2780 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2781}
2782
2783
2784int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2785{
2786#ifdef CONFIG_FILS_SK_PFS
2787 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2788 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2789#else /* CONFIG_FILS_SK_PFS */
2790 return 0;
2791#endif /* CONFIG_FILS_SK_PFS */
2792}
2793
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002794#endif /* CONFIG_FILS */
2795
2796
2797static u8 * wpas_populate_assoc_ies(
2798 struct wpa_supplicant *wpa_s,
2799 struct wpa_bss *bss, struct wpa_ssid *ssid,
2800 struct wpa_driver_associate_params *params,
2801 enum wpa_drv_update_connect_params_mask *mask)
2802{
2803 u8 *wpa_ie;
2804 size_t max_wpa_ie_len = 500;
2805 size_t wpa_ie_len;
2806 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002807#ifdef CONFIG_MBO
2808 const u8 *mbo_ie;
2809#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302810#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2811 int pmksa_cached = 0;
2812#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002813#ifdef CONFIG_FILS
2814 const u8 *realm, *username, *rrk;
2815 size_t realm_len, username_len, rrk_len;
2816 u16 next_seq_num;
2817 struct fils_hlp_req *req;
2818
2819 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2820 list) {
2821 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2822 2 + 2 * wpabuf_len(req->pkt) / 255;
2823 }
2824#endif /* CONFIG_FILS */
2825
2826 wpa_ie = os_malloc(max_wpa_ie_len);
2827 if (!wpa_ie) {
2828 wpa_printf(MSG_ERROR,
2829 "Failed to allocate connect IE buffer for %lu bytes",
2830 (unsigned long) max_wpa_ie_len);
2831 return NULL;
2832 }
2833
2834 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2835 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2836 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2837 int try_opportunistic;
2838 const u8 *cache_id = NULL;
2839
2840 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2841 wpa_s->conf->okc :
2842 ssid->proactive_key_caching) &&
2843 (ssid->proto & WPA_PROTO_RSN);
2844#ifdef CONFIG_FILS
2845 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2846 cache_id = wpa_bss_get_fils_cache_id(bss);
2847#endif /* CONFIG_FILS */
2848 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2849 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002850 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002851 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302852#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2853 pmksa_cached = 1;
2854#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002855 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002856 wpa_ie_len = max_wpa_ie_len;
2857 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2858 wpa_ie, &wpa_ie_len)) {
2859 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2860 "key management and encryption suites");
2861 os_free(wpa_ie);
2862 return NULL;
2863 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002864#ifdef CONFIG_HS20
2865 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2866 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2867 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2868 wpa_ie_len = max_wpa_ie_len;
2869 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2870 wpa_ie, &wpa_ie_len)) {
2871 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2872 "key management and encryption suites");
2873 os_free(wpa_ie);
2874 return NULL;
2875 }
2876#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2878 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2879 /*
2880 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2881 * use non-WPA since the scan results did not indicate that the
2882 * AP is using WPA or WPA2.
2883 */
2884 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2885 wpa_ie_len = 0;
2886 wpa_s->wpa_proto = 0;
2887 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2888 wpa_ie_len = max_wpa_ie_len;
2889 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2890 wpa_ie, &wpa_ie_len)) {
2891 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2892 "key management and encryption suites (no "
2893 "scan results)");
2894 os_free(wpa_ie);
2895 return NULL;
2896 }
2897#ifdef CONFIG_WPS
2898 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2899 struct wpabuf *wps_ie;
2900 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2901 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2902 wpa_ie_len = wpabuf_len(wps_ie);
2903 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2904 } else
2905 wpa_ie_len = 0;
2906 wpabuf_free(wps_ie);
2907 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2908 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2909 params->wps = WPS_MODE_PRIVACY;
2910 else
2911 params->wps = WPS_MODE_OPEN;
2912 wpa_s->wpa_proto = 0;
2913#endif /* CONFIG_WPS */
2914 } else {
2915 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2916 wpa_ie_len = 0;
2917 wpa_s->wpa_proto = 0;
2918 }
2919
2920#ifdef IEEE8021X_EAPOL
2921 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2922 if (ssid->leap) {
2923 if (ssid->non_leap == 0)
2924 algs = WPA_AUTH_ALG_LEAP;
2925 else
2926 algs |= WPA_AUTH_ALG_LEAP;
2927 }
2928 }
2929
2930#ifdef CONFIG_FILS
2931 /* Clear FILS association */
2932 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2933
2934 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2935 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2936 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2937 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002938 &next_seq_num, &rrk, &rrk_len) == 0 &&
2939 (!wpa_s->last_con_fail_realm ||
2940 wpa_s->last_con_fail_realm_len != realm_len ||
2941 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002942 algs = WPA_AUTH_ALG_FILS;
2943 params->fils_erp_username = username;
2944 params->fils_erp_username_len = username_len;
2945 params->fils_erp_realm = realm;
2946 params->fils_erp_realm_len = realm_len;
2947 params->fils_erp_next_seq_num = next_seq_num;
2948 params->fils_erp_rrk = rrk;
2949 params->fils_erp_rrk_len = rrk_len;
2950
2951 if (mask)
2952 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302953 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2954 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2955 pmksa_cached) {
2956 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002957 }
2958#endif /* CONFIG_FILS */
2959#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002960#ifdef CONFIG_SAE
2961 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2962 algs = WPA_AUTH_ALG_SAE;
2963#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002964
2965 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2966 if (ssid->auth_alg) {
2967 algs = ssid->auth_alg;
2968 wpa_dbg(wpa_s, MSG_DEBUG,
2969 "Overriding auth_alg selection: 0x%x", algs);
2970 }
2971
Hai Shalom5f92bc92019-04-18 11:54:11 -07002972#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302973 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002974 wpa_dbg(wpa_s, MSG_DEBUG,
2975 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2976 algs = WPA_AUTH_ALG_OPEN;
2977 }
2978#endif /* CONFIG_SAE */
2979
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002980#ifdef CONFIG_P2P
2981 if (wpa_s->global->p2p) {
2982 u8 *pos;
2983 size_t len;
2984 int res;
2985 pos = wpa_ie + wpa_ie_len;
2986 len = max_wpa_ie_len - wpa_ie_len;
2987 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2988 ssid->p2p_group);
2989 if (res >= 0)
2990 wpa_ie_len += res;
2991 }
2992
2993 wpa_s->cross_connect_disallowed = 0;
2994 if (bss) {
2995 struct wpabuf *p2p;
2996 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2997 if (p2p) {
2998 wpa_s->cross_connect_disallowed =
2999 p2p_get_cross_connect_disallowed(p2p);
3000 wpabuf_free(p2p);
3001 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3002 "connection",
3003 wpa_s->cross_connect_disallowed ?
3004 "disallows" : "allows");
3005 }
3006 }
3007
3008 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3009#endif /* CONFIG_P2P */
3010
3011 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003012 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003013 wpa_ie + wpa_ie_len,
3014 max_wpa_ie_len -
3015 wpa_ie_len);
3016 }
3017
3018 /*
3019 * Workaround: Add Extended Capabilities element only if the AP
3020 * included this element in Beacon/Probe Response frames. Some older
3021 * APs seem to have interoperability issues if this element is
3022 * included, so while the standard may require us to include the
3023 * element in all cases, it is justifiable to skip it to avoid
3024 * interoperability issues.
3025 */
3026 if (ssid->p2p_group)
3027 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3028 else
3029 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3030
3031 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3032 u8 ext_capab[18];
3033 int ext_capab_len;
3034 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3035 sizeof(ext_capab));
3036 if (ext_capab_len > 0 &&
3037 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3038 u8 *pos = wpa_ie;
3039 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3040 pos += 2 + pos[1];
3041 os_memmove(pos + ext_capab_len, pos,
3042 wpa_ie_len - (pos - wpa_ie));
3043 wpa_ie_len += ext_capab_len;
3044 os_memcpy(pos, ext_capab, ext_capab_len);
3045 }
3046 }
3047
3048#ifdef CONFIG_HS20
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003049 if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003050 struct wpabuf *hs20;
3051
Roshan Pius3a1667e2018-07-03 15:17:14 -07003052 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003053 if (hs20) {
3054 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3055 size_t len;
3056
Hai Shalom74f70d42019-02-11 14:42:39 -08003057 wpas_hs20_add_indication(hs20, pps_mo_id,
3058 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003059 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003060 len = max_wpa_ie_len - wpa_ie_len;
3061 if (wpabuf_len(hs20) <= len) {
3062 os_memcpy(wpa_ie + wpa_ie_len,
3063 wpabuf_head(hs20), wpabuf_len(hs20));
3064 wpa_ie_len += wpabuf_len(hs20);
3065 }
3066 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003067 }
3068 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003069 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003070#endif /* CONFIG_HS20 */
3071
3072 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3073 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3074 size_t len;
3075
3076 len = max_wpa_ie_len - wpa_ie_len;
3077 if (wpabuf_len(buf) <= len) {
3078 os_memcpy(wpa_ie + wpa_ie_len,
3079 wpabuf_head(buf), wpabuf_len(buf));
3080 wpa_ie_len += wpabuf_len(buf);
3081 }
3082 }
3083
3084#ifdef CONFIG_FST
3085 if (wpa_s->fst_ies) {
3086 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3087
3088 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3089 os_memcpy(wpa_ie + wpa_ie_len,
3090 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3091 wpa_ie_len += fst_ies_len;
3092 }
3093 }
3094#endif /* CONFIG_FST */
3095
3096#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003097 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003098 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003099 int len;
3100
3101 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003102 max_wpa_ie_len - wpa_ie_len,
3103 !!mbo_attr_from_mbo_ie(mbo_ie,
3104 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003105 if (len >= 0)
3106 wpa_ie_len += len;
3107 }
3108#endif /* CONFIG_MBO */
3109
3110#ifdef CONFIG_FILS
3111 if (algs == WPA_AUTH_ALG_FILS) {
3112 size_t len;
3113
3114 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3115 max_wpa_ie_len - wpa_ie_len);
3116 wpa_ie_len += len;
3117 }
3118#endif /* CONFIG_FILS */
3119
3120#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003121#ifdef CONFIG_TESTING_OPTIONS
3122 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3123 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3124 } else
3125#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003126 if (algs == WPA_AUTH_ALG_OPEN &&
3127 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3128 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003129 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003130
Roshan Pius3a1667e2018-07-03 15:17:14 -07003131 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003132 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003133 } else if (wpa_s->assoc_status_code ==
3134 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003135 if (wpa_s->last_owe_group == 19)
3136 group = 20;
3137 else if (wpa_s->last_owe_group == 20)
3138 group = 21;
3139 else
3140 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003141 } else {
3142 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003143 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003144
Roshan Pius3a1667e2018-07-03 15:17:14 -07003145 wpa_s->last_owe_group = group;
3146 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003147 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3148 if (owe_ie &&
3149 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3150 os_memcpy(wpa_ie + wpa_ie_len,
3151 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3152 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003153 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003154 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003155 }
3156#endif /* CONFIG_OWE */
3157
Hai Shalom021b0b52019-04-10 11:17:58 -07003158#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003159 if (DPP_VERSION > 1 &&
3160 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003161 ssid->dpp_netaccesskey &&
3162 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003163 struct rsn_pmksa_cache_entry *pmksa;
3164
3165 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3166 if (!pmksa || !pmksa->dpp_pfs)
3167 goto pfs_fail;
3168
Hai Shalom021b0b52019-04-10 11:17:58 -07003169 dpp_pfs_free(wpa_s->dpp_pfs);
3170 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3171 ssid->dpp_netaccesskey_len);
3172 if (!wpa_s->dpp_pfs) {
3173 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3174 /* Try to continue without PFS */
3175 goto pfs_fail;
3176 }
3177 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3178 max_wpa_ie_len - wpa_ie_len) {
3179 os_memcpy(wpa_ie + wpa_ie_len,
3180 wpabuf_head(wpa_s->dpp_pfs->ie),
3181 wpabuf_len(wpa_s->dpp_pfs->ie));
3182 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3183 }
3184 }
3185pfs_fail:
3186#endif /* CONFIG_DPP2 */
3187
Roshan Pius3a1667e2018-07-03 15:17:14 -07003188#ifdef CONFIG_IEEE80211R
3189 /*
3190 * Add MDIE under these conditions: the network profile allows FT,
3191 * the AP supports FT, and the mobility domain ID matches.
3192 */
3193 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3194 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3195
3196 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3197 size_t len = 0;
3198 const u8 *md = mdie + 2;
3199 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3200
3201 if (os_memcmp(md, wpa_md,
3202 MOBILITY_DOMAIN_ID_LEN) == 0) {
3203 /* Add mobility domain IE */
3204 len = wpa_ft_add_mdie(
3205 wpa_s->wpa, wpa_ie + wpa_ie_len,
3206 max_wpa_ie_len - wpa_ie_len, mdie);
3207 wpa_ie_len += len;
3208 }
3209#ifdef CONFIG_SME
3210 if (len > 0 && wpa_s->sme.ft_used &&
3211 wpa_sm_has_ptk(wpa_s->wpa)) {
3212 wpa_dbg(wpa_s, MSG_DEBUG,
3213 "SME: Trying to use FT over-the-air");
3214 algs |= WPA_AUTH_ALG_FT;
3215 }
3216#endif /* CONFIG_SME */
3217 }
3218 }
3219#endif /* CONFIG_IEEE80211R */
3220
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003221#ifdef CONFIG_TESTING_OPTIONS
3222 if (wpa_s->rsnxe_override_assoc &&
3223 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3224 max_wpa_ie_len - wpa_ie_len) {
3225 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3226 os_memcpy(wpa_ie + wpa_ie_len,
3227 wpabuf_head(wpa_s->rsnxe_override_assoc),
3228 wpabuf_len(wpa_s->rsnxe_override_assoc));
3229 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3230 } else
3231#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003232 if (wpa_s->rsnxe_len > 0 &&
3233 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3234 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3235 wpa_ie_len += wpa_s->rsnxe_len;
3236 }
3237
Hai Shalom60840252021-02-19 19:02:11 -08003238 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3239 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003240 struct wpabuf *mscs_ie;
3241 size_t mscs_ie_len, buf_len;
3242
Hai Shalom899fcc72020-10-19 14:38:18 -07003243 buf_len = 3 + /* MSCS descriptor IE header */
3244 1 + /* Request type */
3245 2 + /* User priority control */
3246 4 + /* Stream timeout */
3247 3 + /* TCLAS Mask IE header */
3248 wpa_s->robust_av.frame_classifier_len;
3249 mscs_ie = wpabuf_alloc(buf_len);
3250 if (!mscs_ie) {
3251 wpa_printf(MSG_INFO,
3252 "MSCS: Failed to allocate MSCS IE");
3253 goto mscs_fail;
3254 }
3255
3256 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3257 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3258 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3259 mscs_ie_len = wpabuf_len(mscs_ie);
3260 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3261 mscs_ie_len);
3262 wpa_ie_len += mscs_ie_len;
3263 }
3264
3265 wpabuf_free(mscs_ie);
3266 }
3267mscs_fail:
3268
Hai Shalom74f70d42019-02-11 14:42:39 -08003269 if (ssid->multi_ap_backhaul_sta) {
3270 size_t multi_ap_ie_len;
3271
3272 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3273 max_wpa_ie_len - wpa_ie_len,
3274 MULTI_AP_BACKHAUL_STA);
3275 if (multi_ap_ie_len == 0) {
3276 wpa_printf(MSG_ERROR,
3277 "Multi-AP: Failed to build Multi-AP IE");
3278 os_free(wpa_ie);
3279 return NULL;
3280 }
3281 wpa_ie_len += multi_ap_ie_len;
3282 }
3283
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 params->wpa_ie = wpa_ie;
3285 params->wpa_ie_len = wpa_ie_len;
3286 params->auth_alg = algs;
3287 if (mask)
3288 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3289
3290 return wpa_ie;
3291}
3292
3293
Hai Shalomc3565922019-10-28 11:58:20 -07003294#ifdef CONFIG_OWE
3295static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3296{
3297 struct wpa_driver_associate_params params;
3298 u8 *wpa_ie;
3299
3300 os_memset(&params, 0, sizeof(params));
3301 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3302 wpa_s->current_ssid, &params, NULL);
3303 if (!wpa_ie)
3304 return;
3305
3306 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3307 os_free(wpa_ie);
3308}
3309#endif /* CONFIG_OWE */
3310
3311
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3313static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3314{
3315 struct wpa_driver_associate_params params;
3316 enum wpa_drv_update_connect_params_mask mask = 0;
3317 u8 *wpa_ie;
3318
3319 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3320 return; /* nothing to do */
3321
3322 os_memset(&params, 0, sizeof(params));
3323 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3324 wpa_s->current_ssid, &params, &mask);
3325 if (!wpa_ie)
3326 return;
3327
3328 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3329 os_free(wpa_ie);
3330 return;
3331 }
3332
3333 wpa_s->auth_alg = params.auth_alg;
3334 wpa_drv_update_connect_params(wpa_s, &params, mask);
3335 os_free(wpa_ie);
3336}
3337#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3338
3339
Hai Shalomc3565922019-10-28 11:58:20 -07003340static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3341{
3342 if (!edmg_ie || edmg_ie[1] < 6)
3343 return 0;
3344 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3345}
3346
3347
3348static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3349{
3350 if (!edmg_ie || edmg_ie[1] < 6)
3351 return 0;
3352 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3353}
3354
3355
3356/* Returns the intersection of two EDMG configurations.
3357 * Note: The current implementation is limited to CB2 only (CB1 included),
3358 * i.e., the implementation supports up to 2 contiguous channels.
3359 * For supporting non-contiguous (aggregated) channels and for supporting
3360 * CB3 and above, this function will need to be extended.
3361 */
3362static struct ieee80211_edmg_config
3363get_edmg_intersection(struct ieee80211_edmg_config a,
3364 struct ieee80211_edmg_config b,
3365 u8 primary_channel)
3366{
3367 struct ieee80211_edmg_config result;
3368 int i, contiguous = 0;
3369 int max_contiguous = 0;
3370
3371 result.channels = b.channels & a.channels;
3372 if (!result.channels) {
3373 wpa_printf(MSG_DEBUG,
3374 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3375 a.channels, b.channels);
3376 goto fail;
3377 }
3378
3379 if (!(result.channels & BIT(primary_channel - 1))) {
3380 wpa_printf(MSG_DEBUG,
3381 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3382 primary_channel, result.channels);
3383 goto fail;
3384 }
3385
3386 /* Find max contiguous channels */
3387 for (i = 0; i < 6; i++) {
3388 if (result.channels & BIT(i))
3389 contiguous++;
3390 else
3391 contiguous = 0;
3392
3393 if (contiguous > max_contiguous)
3394 max_contiguous = contiguous;
3395 }
3396
3397 /* Assuming AP and STA supports ONLY contiguous channels,
3398 * bw configuration can have value between 4-7.
3399 */
3400 if ((b.bw_config < a.bw_config))
3401 result.bw_config = b.bw_config;
3402 else
3403 result.bw_config = a.bw_config;
3404
3405 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3406 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3407 wpa_printf(MSG_DEBUG,
3408 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3409 max_contiguous);
3410 goto fail;
3411 }
3412
3413 return result;
3414
3415fail:
3416 result.channels = 0;
3417 result.bw_config = 0;
3418 return result;
3419}
3420
3421
3422static struct ieee80211_edmg_config
3423get_supported_edmg(struct wpa_supplicant *wpa_s,
3424 struct hostapd_freq_params *freq,
3425 struct ieee80211_edmg_config request_edmg)
3426{
3427 enum hostapd_hw_mode hw_mode;
3428 struct hostapd_hw_modes *mode = NULL;
3429 u8 primary_channel;
3430
3431 if (!wpa_s->hw.modes)
3432 goto fail;
3433
3434 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3435 if (hw_mode == NUM_HOSTAPD_MODES)
3436 goto fail;
3437
Hai Shalom60840252021-02-19 19:02:11 -08003438 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003439 if (!mode)
3440 goto fail;
3441
3442 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3443
3444fail:
3445 request_edmg.channels = 0;
3446 request_edmg.bw_config = 0;
3447 return request_edmg;
3448}
3449
3450
Hai Shalom021b0b52019-04-10 11:17:58 -07003451#ifdef CONFIG_MBO
3452void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3453{
3454 struct wpa_driver_associate_params params;
3455 u8 *wpa_ie;
3456
3457 /*
3458 * Update MBO connect params only in case of change of MBO attributes
3459 * when connected, if the AP support MBO.
3460 */
3461
3462 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3463 !wpa_s->current_bss ||
3464 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3465 return;
3466
3467 os_memset(&params, 0, sizeof(params));
3468 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3469 wpa_s->current_ssid, &params, NULL);
3470 if (!wpa_ie)
3471 return;
3472
3473 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3474 os_free(wpa_ie);
3475}
3476#endif /* CONFIG_MBO */
3477
3478
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003479static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3480{
3481 struct wpa_connect_work *cwork = work->ctx;
3482 struct wpa_bss *bss = cwork->bss;
3483 struct wpa_ssid *ssid = cwork->ssid;
3484 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003485 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003486 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003487 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003488 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003489 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003490#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003491 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003492#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003493 int assoc_failed = 0;
3494 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003495 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003496#ifdef CONFIG_HT_OVERRIDES
3497 struct ieee80211_ht_capabilities htcaps;
3498 struct ieee80211_ht_capabilities htcaps_mask;
3499#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003500#ifdef CONFIG_VHT_OVERRIDES
3501 struct ieee80211_vht_capabilities vhtcaps;
3502 struct ieee80211_vht_capabilities vhtcaps_mask;
3503#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003504
3505 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003506 if (work->started) {
3507 wpa_s->connect_work = NULL;
3508
3509 /* cancel possible auth. timeout */
3510 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3511 NULL);
3512 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003513 wpas_connect_work_free(cwork);
3514 return;
3515 }
3516
3517 wpa_s->connect_work = work;
3518
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003519 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3520 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003521 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3522 wpas_connect_work_done(wpa_s);
3523 return;
3524 }
3525
Dmitry Shmidte4663042016-04-04 10:07:49 -07003526 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 os_memset(&params, 0, sizeof(params));
3528 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003529 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003530
3531 /* Starting new association, so clear the possibly used WPA IE from the
3532 * previous association. */
3533 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3534 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3535 wpa_s->rsnxe_len = 0;
3536 wpa_s->mscs_setup_done = false;
3537
3538 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3539 if (!wpa_ie) {
3540 wpas_connect_work_done(wpa_s);
3541 return;
3542 }
3543
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003544 if (bss &&
3545 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546#ifdef CONFIG_IEEE80211R
3547 const u8 *ie, *md = NULL;
3548#endif /* CONFIG_IEEE80211R */
3549 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3550 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3551 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3552 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3553 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3554 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3555 if (bssid_changed)
3556 wpas_notify_bssid_changed(wpa_s);
3557#ifdef CONFIG_IEEE80211R
3558 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3559 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3560 md = ie + 2;
3561 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3562 if (md) {
3563 /* Prepare for the next transition */
3564 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3565 }
3566#endif /* CONFIG_IEEE80211R */
3567#ifdef CONFIG_WPS
3568 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3569 wpa_s->conf->ap_scan == 2 &&
3570 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3571 /* Use ap_scan==1 style network selection to find the network
3572 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003573 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003574 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 wpa_s->reassociate = 1;
3576 wpa_supplicant_req_scan(wpa_s, 0, 0);
3577 return;
3578#endif /* CONFIG_WPS */
3579 } else {
3580 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3581 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003582 if (bss)
3583 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3584 else
3585 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003586 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003587 if (!wpa_s->pno)
3588 wpa_supplicant_cancel_sched_scan(wpa_s);
3589
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 wpa_supplicant_cancel_scan(wpa_s);
3591
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3593 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003594 cipher_pairwise = wpa_s->pairwise_cipher;
3595 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003596 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3598 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3599 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3600 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003601#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003602 if (wpa_set_wep_keys(wpa_s, ssid)) {
3603 use_crypt = 1;
3604 wep_keys_set = 1;
3605 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003606#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 }
3608 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3609 use_crypt = 0;
3610
3611#ifdef IEEE8021X_EAPOL
3612 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3613 if ((ssid->eapol_flags &
3614 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3615 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3616 !wep_keys_set) {
3617 use_crypt = 0;
3618 } else {
3619 /* Assume that dynamic WEP-104 keys will be used and
3620 * set cipher suites in order for drivers to expect
3621 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003622 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623 }
3624 }
3625#endif /* IEEE8021X_EAPOL */
3626
3627 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3628 /* Set the key before (and later after) association */
3629 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3630 }
3631
3632 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3633 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 params.ssid = bss->ssid;
3635 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003636 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3637 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003638 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3639 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003640 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003641 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003642 ssid->bssid_set,
3643 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003644 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003645 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003646 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003647 params.bssid_hint = bss->bssid;
3648 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003649 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003651 if (ssid->bssid_hint_set)
3652 params.bssid_hint = ssid->bssid_hint;
3653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 params.ssid = ssid->ssid;
3655 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003656 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003657 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003658
3659 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3660 wpa_s->conf->ap_scan == 2) {
3661 params.bssid = ssid->bssid;
3662 params.fixed_bssid = 1;
3663 }
3664
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003665 /* Initial frequency for IBSS/mesh */
3666 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003667 ssid->frequency > 0 && params.freq.freq == 0)
3668 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003669
3670 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003671 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003672 if (ssid->beacon_int)
3673 params.beacon_int = ssid->beacon_int;
3674 else
3675 params.beacon_int = wpa_s->conf->beacon_int;
3676 }
3677
Hai Shalomc3565922019-10-28 11:58:20 -07003678 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003679 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3680 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003681 else
3682 edmg_ie_oper = NULL;
3683
3684 if (edmg_ie_oper) {
3685 params.freq.edmg.channels =
3686 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3687 params.freq.edmg.bw_config =
3688 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3689 wpa_printf(MSG_DEBUG,
3690 "AP supports EDMG channels 0x%x, bw_config %d",
3691 params.freq.edmg.channels,
3692 params.freq.edmg.bw_config);
3693
3694 /* User may ask for specific EDMG channel for EDMG connection
3695 * (must be supported by AP)
3696 */
3697 if (ssid->edmg_channel) {
3698 struct ieee80211_edmg_config configured_edmg;
3699 enum hostapd_hw_mode hw_mode;
3700 u8 primary_channel;
3701
3702 hw_mode = ieee80211_freq_to_chan(bss->freq,
3703 &primary_channel);
3704 if (hw_mode == NUM_HOSTAPD_MODES)
3705 goto edmg_fail;
3706
3707 hostapd_encode_edmg_chan(ssid->enable_edmg,
3708 ssid->edmg_channel,
3709 primary_channel,
3710 &configured_edmg);
3711
3712 if (ieee802_edmg_is_allowed(params.freq.edmg,
3713 configured_edmg)) {
3714 params.freq.edmg = configured_edmg;
3715 wpa_printf(MSG_DEBUG,
3716 "Use EDMG channel %d for connection",
3717 ssid->edmg_channel);
3718 } else {
3719 edmg_fail:
3720 params.freq.edmg.channels = 0;
3721 params.freq.edmg.bw_config = 0;
3722 wpa_printf(MSG_WARNING,
3723 "EDMG channel %d not supported by AP, fallback to DMG",
3724 ssid->edmg_channel);
3725 }
3726 }
3727
3728 if (params.freq.edmg.channels) {
3729 wpa_printf(MSG_DEBUG,
3730 "EDMG before: channels 0x%x, bw_config %d",
3731 params.freq.edmg.channels,
3732 params.freq.edmg.bw_config);
3733 params.freq.edmg = get_supported_edmg(wpa_s,
3734 &params.freq,
3735 params.freq.edmg);
3736 wpa_printf(MSG_DEBUG,
3737 "EDMG after: channels 0x%x, bw_config %d",
3738 params.freq.edmg.channels,
3739 params.freq.edmg.bw_config);
3740 }
3741 }
3742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 params.pairwise_suite = cipher_pairwise;
3744 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003745 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003746 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003747 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003748 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003750 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003751#ifdef CONFIG_WEP
3752 {
3753 int i;
3754
3755 for (i = 0; i < NUM_WEP_KEYS; i++) {
3756 if (ssid->wep_key_len[i])
3757 params.wep_key[i] = ssid->wep_key[i];
3758 params.wep_key_len[i] = ssid->wep_key_len[i];
3759 }
3760 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003762#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763
Hai Shalom74f70d42019-02-11 14:42:39 -08003764 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003765 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3766 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 params.passphrase = ssid->passphrase;
3768 if (ssid->psk_set)
3769 params.psk = ssid->psk;
3770 }
3771
Hai Shalom74f70d42019-02-11 14:42:39 -08003772 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3773 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3774 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3775 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3776 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003777 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003778
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003779 if (wpa_s->conf->key_mgmt_offload) {
3780 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3781 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003782 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3783 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003784 params.req_key_mgmt_offload =
3785 ssid->proactive_key_caching < 0 ?
3786 wpa_s->conf->okc : ssid->proactive_key_caching;
3787 else
3788 params.req_key_mgmt_offload = 1;
3789
3790 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3791 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3792 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3793 ssid->psk_set)
3794 params.psk = ssid->psk;
3795 }
3796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003797 params.drop_unencrypted = use_crypt;
3798
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003799 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003800 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3802 struct wpa_ie_data ie;
3803 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3804 ie.capabilities &
3805 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3806 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3807 "MFP: require MFP");
3808 params.mgmt_frame_protection =
3809 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003810#ifdef CONFIG_OWE
3811 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3812 !ssid->owe_only) {
3813 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3814#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815 }
3816 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003817
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003818 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003820 if (wpa_s->p2pdev->set_sta_uapsd)
3821 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822 else
3823 params.uapsd = -1;
3824
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003825#ifdef CONFIG_HT_OVERRIDES
3826 os_memset(&htcaps, 0, sizeof(htcaps));
3827 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3828 params.htcaps = (u8 *) &htcaps;
3829 params.htcaps_mask = (u8 *) &htcaps_mask;
3830 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3831#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003832#ifdef CONFIG_VHT_OVERRIDES
3833 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3834 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3835 params.vhtcaps = &vhtcaps;
3836 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003837 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003838#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003839#ifdef CONFIG_HE_OVERRIDES
3840 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3841#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003842
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003843#ifdef CONFIG_P2P
3844 /*
3845 * If multi-channel concurrency is not supported, check for any
3846 * frequency conflict. In case of any frequency conflict, remove the
3847 * least prioritized connection.
3848 */
3849 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003850 int freq, num;
3851 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003852 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003853 wpa_printf(MSG_DEBUG,
3854 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003855 freq, params.freq.freq);
3856 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003857 wpa_s, params.freq.freq, ssid) < 0) {
3858 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003859 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003860 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003861 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003862 }
3863 }
3864#endif /* CONFIG_P2P */
3865
Dmitry Shmidte4663042016-04-04 10:07:49 -07003866 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3867 wpa_s->current_ssid)
3868 params.prev_bssid = prev_bssid;
3869
Hai Shalom60840252021-02-19 19:02:11 -08003870#ifdef CONFIG_SAE
3871 params.sae_pwe = wpa_s->conf->sae_pwe;
3872#endif /* CONFIG_SAE */
3873
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003874 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003875 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876 if (ret < 0) {
3877 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3878 "failed");
3879 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3880 /*
3881 * The driver is known to mean what is saying, so we
3882 * can stop right here; the association will not
3883 * succeed.
3884 */
3885 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08003886 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08003887 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003888 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3890 return;
3891 }
3892 /* try to continue anyway; new association will be tried again
3893 * after timeout */
3894 assoc_failed = 1;
3895 }
3896
3897 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3898 /* Set the key after the association just in case association
3899 * cleared the previously configured key. */
3900 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3901 /* No need to timeout authentication since there is no key
3902 * management. */
3903 wpa_supplicant_cancel_auth_timeout(wpa_s);
3904 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3905#ifdef CONFIG_IBSS_RSN
3906 } else if (ssid->mode == WPAS_MODE_IBSS &&
3907 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3908 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3909 /*
3910 * RSN IBSS authentication is per-STA and we can disable the
3911 * per-BSSID authentication.
3912 */
3913 wpa_supplicant_cancel_auth_timeout(wpa_s);
3914#endif /* CONFIG_IBSS_RSN */
3915 } else {
3916 /* Timeout for IEEE 802.11 authentication and association */
3917 int timeout = 60;
3918
3919 if (assoc_failed) {
3920 /* give IBSS a bit more time */
3921 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3922 } else if (wpa_s->conf->ap_scan == 1) {
3923 /* give IBSS a bit more time */
3924 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3925 }
3926 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3927 }
3928
Hai Shalomfdcde762020-04-02 11:19:20 -07003929#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003930 if (wep_keys_set &&
3931 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932 /* Set static WEP keys again */
3933 wpa_set_wep_keys(wpa_s, ssid);
3934 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003935#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003936
3937 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3938 /*
3939 * Do not allow EAP session resumption between different
3940 * network configurations.
3941 */
3942 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3943 }
3944 old_ssid = wpa_s->current_ssid;
3945 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003946
3947 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003948 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003949#ifdef CONFIG_HS20
3950 hs20_configure_frame_filters(wpa_s);
3951#endif /* CONFIG_HS20 */
3952 }
3953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003954 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3955 wpa_supplicant_initiate_eapol(wpa_s);
3956 if (old_ssid != wpa_s->current_ssid)
3957 wpas_notify_network_changed(wpa_s);
3958}
3959
3960
3961static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3962 const u8 *addr)
3963{
3964 struct wpa_ssid *old_ssid;
3965
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003966 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003968 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003969 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003970 wpa_sm_set_config(wpa_s->wpa, NULL);
3971 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3972 if (old_ssid != wpa_s->current_ssid)
3973 wpas_notify_network_changed(wpa_s);
3974 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3975}
3976
3977
3978/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003979 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3980 * @wpa_s: Pointer to wpa_supplicant data
3981 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3982 *
3983 * This function is used to request %wpa_supplicant to deauthenticate from the
3984 * current AP.
3985 */
3986void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003987 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003988{
3989 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003990 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003991 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003993 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003994 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003995 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003996 reason_code, reason2str(reason_code),
3997 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003998
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003999 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4000 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4001 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004002 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004003 else if (!is_zero_ether_addr(wpa_s->bssid))
4004 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004005 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4006 /*
4007 * When using driver-based BSS selection, we may not know the
4008 * BSSID with which we are currently trying to associate. We
4009 * need to notify the driver of this disconnection even in such
4010 * a case, so use the all zeros address here.
4011 */
4012 addr = wpa_s->bssid;
4013 zero_addr = 1;
4014 }
4015
Hai Shalom74f70d42019-02-11 14:42:39 -08004016 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4017 wpa_s->enabled_4addr_mode = 0;
4018
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004019#ifdef CONFIG_TDLS
4020 wpa_tdls_teardown_peers(wpa_s->wpa);
4021#endif /* CONFIG_TDLS */
4022
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004023#ifdef CONFIG_MESH
4024 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004025 struct mesh_conf *mconf;
4026
4027 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004028 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4029 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004030 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4031 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004032 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004033 }
4034#endif /* CONFIG_MESH */
4035
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004036 if (addr) {
4037 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004038 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004039 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004040 event.deauth_info.locally_generated = 1;
4041 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004042 if (zero_addr)
4043 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 }
4045
4046 wpa_supplicant_clear_connection(wpa_s, addr);
4047}
4048
Hai Shalomfdcde762020-04-02 11:19:20 -07004049
4050void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4051{
4052 wpa_s->own_reconnect_req = 1;
4053 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4054
4055}
4056
4057
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004058static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4059 struct wpa_ssid *ssid)
4060{
4061 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4062 return;
4063
4064 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004065 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004066 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4067 wpas_notify_network_enabled_changed(wpa_s, ssid);
4068
4069 /*
4070 * Try to reassociate since there is no current configuration and a new
4071 * network was made available.
4072 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004073 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004074 wpa_s->reassociate = 1;
4075}
4076
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004077
Roshan Pius950bec92016-07-19 09:49:24 -07004078/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004079 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004080 * @wpa_s: wpa_supplicant structure for a network interface
4081 * Returns: The new network configuration or %NULL if operation failed
4082 *
4083 * This function performs the following operations:
4084 * 1. Adds a new network.
4085 * 2. Send network addition notification.
4086 * 3. Marks the network disabled.
4087 * 4. Set network default parameters.
4088 */
4089struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4090{
4091 struct wpa_ssid *ssid;
4092
4093 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004094 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004095 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004096 wpas_notify_network_added(wpa_s, ssid);
4097 ssid->disabled = 1;
4098 wpa_config_set_network_defaults(ssid);
4099
4100 return ssid;
4101}
4102
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004103
Roshan Pius950bec92016-07-19 09:49:24 -07004104/**
4105 * wpa_supplicant_remove_network - Remove a configured network based on id
4106 * @wpa_s: wpa_supplicant structure for a network interface
4107 * @id: Unique network id to search for
4108 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4109 * could not be removed
4110 *
4111 * This function performs the following operations:
4112 * 1. Removes the network.
4113 * 2. Send network removal notification.
4114 * 3. Update internal state machines.
4115 * 4. Stop any running sched scans.
4116 */
4117int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4118{
4119 struct wpa_ssid *ssid;
4120 int was_disabled;
4121
4122 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004123 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004124 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004125 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004126
4127 if (wpa_s->last_ssid == ssid)
4128 wpa_s->last_ssid = NULL;
4129
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004130 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004131#ifdef CONFIG_SME
4132 wpa_s->sme.prev_bssid_set = 0;
4133#endif /* CONFIG_SME */
4134 /*
4135 * Invalidate the EAP session cache if the current or
4136 * previously used network is removed.
4137 */
4138 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4139 }
4140
4141 if (ssid == wpa_s->current_ssid) {
4142 wpa_sm_set_config(wpa_s->wpa, NULL);
4143 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4144
4145 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4146 wpa_s->own_disconnect_req = 1;
4147 wpa_supplicant_deauthenticate(wpa_s,
4148 WLAN_REASON_DEAUTH_LEAVING);
4149 }
4150
4151 was_disabled = ssid->disabled;
4152
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004153 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004154 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004155
4156 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004157 wpa_printf(MSG_DEBUG,
4158 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004159 wpa_supplicant_cancel_sched_scan(wpa_s);
4160 wpa_supplicant_req_scan(wpa_s, 0, 0);
4161 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004162
Roshan Pius950bec92016-07-19 09:49:24 -07004163 return 0;
4164}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004165
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004167/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004168 * wpa_supplicant_remove_all_networks - Remove all configured networks
4169 * @wpa_s: wpa_supplicant structure for a network interface
4170 * Returns: 0 on success (errors are currently ignored)
4171 *
4172 * This function performs the following operations:
4173 * 1. Remove all networks.
4174 * 2. Send network removal notifications.
4175 * 3. Update internal state machines.
4176 * 4. Stop any running sched scans.
4177 */
4178int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4179{
4180 struct wpa_ssid *ssid;
4181
4182 if (wpa_s->sched_scanning)
4183 wpa_supplicant_cancel_sched_scan(wpa_s);
4184
4185 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4186 if (wpa_s->current_ssid) {
4187#ifdef CONFIG_SME
4188 wpa_s->sme.prev_bssid_set = 0;
4189#endif /* CONFIG_SME */
4190 wpa_sm_set_config(wpa_s->wpa, NULL);
4191 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4192 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4193 wpa_s->own_disconnect_req = 1;
4194 wpa_supplicant_deauthenticate(
4195 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4196 }
4197 ssid = wpa_s->conf->ssid;
4198 while (ssid) {
4199 struct wpa_ssid *remove_ssid = ssid;
4200 int id;
4201
4202 id = ssid->id;
4203 ssid = ssid->next;
4204 if (wpa_s->last_ssid == remove_ssid)
4205 wpa_s->last_ssid = NULL;
4206 wpas_notify_network_removed(wpa_s, remove_ssid);
4207 wpa_config_remove_network(wpa_s->conf, id);
4208 }
4209 return 0;
4210}
4211
4212
4213/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004214 * wpa_supplicant_enable_network - Mark a configured network as enabled
4215 * @wpa_s: wpa_supplicant structure for a network interface
4216 * @ssid: wpa_ssid structure for a configured network or %NULL
4217 *
4218 * Enables the specified network or all networks if no network specified.
4219 */
4220void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4221 struct wpa_ssid *ssid)
4222{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004223 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004224 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4225 wpa_supplicant_enable_one_network(wpa_s, ssid);
4226 } else
4227 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004229 if (wpa_s->reassociate && !wpa_s->disconnected &&
4230 (!wpa_s->current_ssid ||
4231 wpa_s->wpa_state == WPA_DISCONNECTED ||
4232 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004233 if (wpa_s->sched_scanning) {
4234 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4235 "new network to scan filters");
4236 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004237 }
4238
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004239 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4240 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004241 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004242 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004243 }
4244}
4245
4246
4247/**
4248 * wpa_supplicant_disable_network - Mark a configured network as disabled
4249 * @wpa_s: wpa_supplicant structure for a network interface
4250 * @ssid: wpa_ssid structure for a configured network or %NULL
4251 *
4252 * Disables the specified network or all networks if no network specified.
4253 */
4254void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4255 struct wpa_ssid *ssid)
4256{
4257 struct wpa_ssid *other_ssid;
4258 int was_disabled;
4259
4260 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004261 if (wpa_s->sched_scanning)
4262 wpa_supplicant_cancel_sched_scan(wpa_s);
4263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004264 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4265 other_ssid = other_ssid->next) {
4266 was_disabled = other_ssid->disabled;
4267 if (was_disabled == 2)
4268 continue; /* do not change persistent P2P group
4269 * data */
4270
4271 other_ssid->disabled = 1;
4272
4273 if (was_disabled != other_ssid->disabled)
4274 wpas_notify_network_enabled_changed(
4275 wpa_s, other_ssid);
4276 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004277 if (wpa_s->current_ssid) {
4278 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4279 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004280 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004281 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004282 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004283 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004284 if (ssid == wpa_s->current_ssid) {
4285 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4286 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004287 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004289 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290
4291 was_disabled = ssid->disabled;
4292
4293 ssid->disabled = 1;
4294
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004295 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004297 if (wpa_s->sched_scanning) {
4298 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4299 "to remove network from filters");
4300 wpa_supplicant_cancel_sched_scan(wpa_s);
4301 wpa_supplicant_req_scan(wpa_s, 0, 0);
4302 }
4303 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 }
4305}
4306
4307
4308/**
4309 * wpa_supplicant_select_network - Attempt association with a network
4310 * @wpa_s: wpa_supplicant structure for a network interface
4311 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4312 */
4313void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4314 struct wpa_ssid *ssid)
4315{
4316
4317 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004318 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004320 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004321 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4322 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004323 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004324 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004325 disconnected = 1;
4326 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004327
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004328 if (ssid)
4329 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004331 /*
4332 * Mark all other networks disabled or mark all networks enabled if no
4333 * network specified.
4334 */
4335 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4336 other_ssid = other_ssid->next) {
4337 int was_disabled = other_ssid->disabled;
4338 if (was_disabled == 2)
4339 continue; /* do not change persistent P2P group data */
4340
4341 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004342 if (was_disabled && !other_ssid->disabled)
4343 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004344
4345 if (was_disabled != other_ssid->disabled)
4346 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4347 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004348
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004349 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4350 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004351 /* We are already associated with the selected network */
4352 wpa_printf(MSG_DEBUG, "Already associated with the "
4353 "selected network - do nothing");
4354 return;
4355 }
4356
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004357 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004358 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004359 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004360 wpa_s->connect_without_scan =
4361 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004362
4363 /*
4364 * Don't optimize next scan freqs since a new ESS has been
4365 * selected.
4366 */
4367 os_free(wpa_s->next_scan_freqs);
4368 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004369 } else {
4370 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004371 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004373 wpa_s->disconnected = 0;
4374 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004375 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004376 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004377 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004378 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004379 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4380 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004381
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004382 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004383 wpa_supplicant_fast_associate(wpa_s) != 1) {
4384 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004385 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004386 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004387 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388
4389 if (ssid)
4390 wpas_notify_network_selected(wpa_s, ssid);
4391}
4392
4393
4394/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004395 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4396 * @wpa_s: wpa_supplicant structure for a network interface
4397 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4398 * @pkcs11_module_path: PKCS #11 module path or NULL
4399 * Returns: 0 on success; -1 on failure
4400 *
4401 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4402 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4403 * module path fails the paths will be reset to the default value (NULL).
4404 */
4405int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4406 const char *pkcs11_engine_path,
4407 const char *pkcs11_module_path)
4408{
4409 char *pkcs11_engine_path_copy = NULL;
4410 char *pkcs11_module_path_copy = NULL;
4411
4412 if (pkcs11_engine_path != NULL) {
4413 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4414 if (pkcs11_engine_path_copy == NULL)
4415 return -1;
4416 }
4417 if (pkcs11_module_path != NULL) {
4418 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004419 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004420 os_free(pkcs11_engine_path_copy);
4421 return -1;
4422 }
4423 }
4424
4425 os_free(wpa_s->conf->pkcs11_engine_path);
4426 os_free(wpa_s->conf->pkcs11_module_path);
4427 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4428 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4429
4430 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4431 eapol_sm_deinit(wpa_s->eapol);
4432 wpa_s->eapol = NULL;
4433 if (wpa_supplicant_init_eapol(wpa_s)) {
4434 /* Error -> Reset paths to the default value (NULL) once. */
4435 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4436 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4437 NULL);
4438
4439 return -1;
4440 }
4441 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4442
4443 return 0;
4444}
4445
4446
4447/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004448 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4449 * @wpa_s: wpa_supplicant structure for a network interface
4450 * @ap_scan: AP scan mode
4451 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4452 *
4453 */
4454int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4455{
4456
4457 int old_ap_scan;
4458
4459 if (ap_scan < 0 || ap_scan > 2)
4460 return -1;
4461
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004462 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4463 wpa_printf(MSG_INFO,
4464 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4465 }
4466
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004467#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004468 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4469 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4470 wpa_s->wpa_state < WPA_COMPLETED) {
4471 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4472 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004473 return 0;
4474 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004475#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004477 old_ap_scan = wpa_s->conf->ap_scan;
4478 wpa_s->conf->ap_scan = ap_scan;
4479
4480 if (old_ap_scan != wpa_s->conf->ap_scan)
4481 wpas_notify_ap_scan_changed(wpa_s);
4482
4483 return 0;
4484}
4485
4486
4487/**
4488 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4489 * @wpa_s: wpa_supplicant structure for a network interface
4490 * @expire_age: Expiration age in seconds
4491 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4492 *
4493 */
4494int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4495 unsigned int bss_expire_age)
4496{
4497 if (bss_expire_age < 10) {
4498 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4499 bss_expire_age);
4500 return -1;
4501 }
4502 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4503 bss_expire_age);
4504 wpa_s->conf->bss_expiration_age = bss_expire_age;
4505
4506 return 0;
4507}
4508
4509
4510/**
4511 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4512 * @wpa_s: wpa_supplicant structure for a network interface
4513 * @expire_count: number of scans after which an unseen BSS is reclaimed
4514 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4515 *
4516 */
4517int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4518 unsigned int bss_expire_count)
4519{
4520 if (bss_expire_count < 1) {
4521 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4522 bss_expire_count);
4523 return -1;
4524 }
4525 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4526 bss_expire_count);
4527 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4528
4529 return 0;
4530}
4531
4532
4533/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004534 * wpa_supplicant_set_scan_interval - Set scan interval
4535 * @wpa_s: wpa_supplicant structure for a network interface
4536 * @scan_interval: scan interval in seconds
4537 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4538 *
4539 */
4540int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4541 int scan_interval)
4542{
4543 if (scan_interval < 0) {
4544 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4545 scan_interval);
4546 return -1;
4547 }
4548 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4549 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004550 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004551
4552 return 0;
4553}
4554
4555
4556/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 * wpa_supplicant_set_debug_params - Set global debug params
4558 * @global: wpa_global structure
4559 * @debug_level: debug level
4560 * @debug_timestamp: determines if show timestamp in debug data
4561 * @debug_show_keys: determines if show keys in debug data
4562 * Returns: 0 if succeed or -1 if debug_level has wrong value
4563 */
4564int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4565 int debug_timestamp, int debug_show_keys)
4566{
4567
4568 int old_level, old_timestamp, old_show_keys;
4569
4570 /* check for allowed debuglevels */
4571 if (debug_level != MSG_EXCESSIVE &&
4572 debug_level != MSG_MSGDUMP &&
4573 debug_level != MSG_DEBUG &&
4574 debug_level != MSG_INFO &&
4575 debug_level != MSG_WARNING &&
4576 debug_level != MSG_ERROR)
4577 return -1;
4578
4579 old_level = wpa_debug_level;
4580 old_timestamp = wpa_debug_timestamp;
4581 old_show_keys = wpa_debug_show_keys;
4582
4583 wpa_debug_level = debug_level;
4584 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4585 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4586
4587 if (wpa_debug_level != old_level)
4588 wpas_notify_debug_level_changed(global);
4589 if (wpa_debug_timestamp != old_timestamp)
4590 wpas_notify_debug_timestamp_changed(global);
4591 if (wpa_debug_show_keys != old_show_keys)
4592 wpas_notify_debug_show_keys_changed(global);
4593
4594 return 0;
4595}
4596
4597
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004598#ifdef CONFIG_OWE
4599static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4600 const u8 *entry_ssid, size_t entry_ssid_len)
4601{
4602 const u8 *owe, *pos, *end;
4603 u8 ssid_len;
4604 struct wpa_bss *bss;
4605
4606 /* Check network profile SSID aganst the SSID in the
4607 * OWE Transition Mode element. */
4608
4609 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4610 if (!bss)
4611 return 0;
4612
4613 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4614 if (!owe)
4615 return 0;
4616
4617 pos = owe + 6;
4618 end = owe + 2 + owe[1];
4619
4620 if (end - pos < ETH_ALEN + 1)
4621 return 0;
4622 pos += ETH_ALEN;
4623 ssid_len = *pos++;
4624 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4625 return 0;
4626
4627 return entry_ssid_len == ssid_len &&
4628 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4629}
4630#endif /* CONFIG_OWE */
4631
4632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004633/**
4634 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4635 * @wpa_s: Pointer to wpa_supplicant data
4636 * Returns: A pointer to the current network structure or %NULL on failure
4637 */
4638struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4639{
4640 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004641 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 int res;
4643 size_t ssid_len;
4644 u8 bssid[ETH_ALEN];
4645 int wired;
4646
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004647 res = wpa_drv_get_ssid(wpa_s, ssid);
4648 if (res < 0) {
4649 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4650 "driver");
4651 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004652 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004653 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004655 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004656 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4657 "driver");
4658 return NULL;
4659 }
4660
4661 wired = wpa_s->conf->ap_scan == 0 &&
4662 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4663
4664 entry = wpa_s->conf->ssid;
4665 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004666 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004668 (!entry->ssid ||
4669 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4670 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004671 (!entry->bssid_set ||
4672 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4673 return entry;
4674#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004675 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4677 (entry->ssid == NULL || entry->ssid_len == 0) &&
4678 (!entry->bssid_set ||
4679 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4680 return entry;
4681#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004682
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004683#ifdef CONFIG_OWE
4684 if (!wpas_network_disabled(wpa_s, entry) &&
4685 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4686 entry->ssid_len) &&
4687 (!entry->bssid_set ||
4688 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4689 return entry;
4690#endif /* CONFIG_OWE */
4691
Dmitry Shmidt04949592012-07-19 12:16:46 -07004692 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004693 entry->ssid_len == 0 &&
4694 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4695 return entry;
4696
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004697 entry = entry->next;
4698 }
4699
4700 return NULL;
4701}
4702
4703
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004704static int select_driver(struct wpa_supplicant *wpa_s, int i)
4705{
4706 struct wpa_global *global = wpa_s->global;
4707
4708 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004709 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004710 if (global->drv_priv[i] == NULL) {
4711 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4712 "'%s'", wpa_drivers[i]->name);
4713 return -1;
4714 }
4715 }
4716
4717 wpa_s->driver = wpa_drivers[i];
4718 wpa_s->global_drv_priv = global->drv_priv[i];
4719
4720 return 0;
4721}
4722
4723
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004724static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4725 const char *name)
4726{
4727 int i;
4728 size_t len;
4729 const char *pos, *driver = name;
4730
4731 if (wpa_s == NULL)
4732 return -1;
4733
4734 if (wpa_drivers[0] == NULL) {
4735 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4736 "wpa_supplicant");
4737 return -1;
4738 }
4739
4740 if (name == NULL) {
4741 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004742 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004743 }
4744
4745 do {
4746 pos = os_strchr(driver, ',');
4747 if (pos)
4748 len = pos - driver;
4749 else
4750 len = os_strlen(driver);
4751
4752 for (i = 0; wpa_drivers[i]; i++) {
4753 if (os_strlen(wpa_drivers[i]->name) == len &&
4754 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004755 0) {
4756 /* First driver that succeeds wins */
4757 if (select_driver(wpa_s, i) == 0)
4758 return 0;
4759 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004760 }
4761
4762 driver = pos + 1;
4763 } while (pos);
4764
4765 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4766 return -1;
4767}
4768
4769
4770/**
4771 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4772 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4773 * with struct wpa_driver_ops::init()
4774 * @src_addr: Source address of the EAPOL frame
4775 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4776 * @len: Length of the EAPOL data
4777 *
4778 * This function is called for each received EAPOL frame. Most driver
4779 * interfaces rely on more generic OS mechanism for receiving frames through
4780 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4781 * take care of received EAPOL frames and deliver them to the core supplicant
4782 * code by calling this function.
4783 */
4784void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4785 const u8 *buf, size_t len)
4786{
4787 struct wpa_supplicant *wpa_s = ctx;
4788
4789 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4790 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4791
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004792#ifdef CONFIG_TESTING_OPTIONS
4793 if (wpa_s->ignore_auth_resp) {
4794 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4795 return;
4796 }
4797#endif /* CONFIG_TESTING_OPTIONS */
4798
Jouni Malinena05074c2012-12-21 21:35:35 +02004799 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4800 (wpa_s->last_eapol_matches_bssid &&
4801#ifdef CONFIG_AP
4802 !wpa_s->ap_iface &&
4803#endif /* CONFIG_AP */
4804 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004805 /*
4806 * There is possible race condition between receiving the
4807 * association event and the EAPOL frame since they are coming
4808 * through different paths from the driver. In order to avoid
4809 * issues in trying to process the EAPOL frame before receiving
4810 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004811 * the association event is received. This may also be needed in
4812 * driver-based roaming case, so also use src_addr != BSSID as a
4813 * trigger if we have previously confirmed that the
4814 * Authenticator uses BSSID as the src_addr (which is not the
4815 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816 */
4817 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004818 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4819 wpa_supplicant_state_txt(wpa_s->wpa_state),
4820 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821 wpabuf_free(wpa_s->pending_eapol_rx);
4822 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4823 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004824 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004825 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4826 ETH_ALEN);
4827 }
4828 return;
4829 }
4830
Jouni Malinena05074c2012-12-21 21:35:35 +02004831 wpa_s->last_eapol_matches_bssid =
4832 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4833
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004834#ifdef CONFIG_AP
4835 if (wpa_s->ap_iface) {
4836 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4837 return;
4838 }
4839#endif /* CONFIG_AP */
4840
4841 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4842 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4843 "no key management is configured");
4844 return;
4845 }
4846
4847 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004848 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004849 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4850 wpa_s->wpa_state != WPA_COMPLETED) &&
4851 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004852 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004853 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004854 int timeout = 10;
4855
4856 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4857 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4858 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4859 /* Use longer timeout for IEEE 802.1X/EAP */
4860 timeout = 70;
4861 }
4862
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004863#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004864 if (wpa_s->current_ssid && wpa_s->current_bss &&
4865 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4866 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4867 /*
4868 * Use shorter timeout if going through WPS AP iteration
4869 * for PIN config method with an AP that does not
4870 * advertise Selected Registrar.
4871 */
4872 struct wpabuf *wps_ie;
4873
4874 wps_ie = wpa_bss_get_vendor_ie_multi(
4875 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4876 if (wps_ie &&
4877 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4878 timeout = 10;
4879 wpabuf_free(wps_ie);
4880 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004881#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004882
4883 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004884 }
4885 wpa_s->eapol_received++;
4886
4887 if (wpa_s->countermeasures) {
4888 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4889 "EAPOL packet");
4890 return;
4891 }
4892
4893#ifdef CONFIG_IBSS_RSN
4894 if (wpa_s->current_ssid &&
4895 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4896 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4897 return;
4898 }
4899#endif /* CONFIG_IBSS_RSN */
4900
4901 /* Source address of the incoming EAPOL frame could be compared to the
4902 * current BSSID. However, it is possible that a centralized
4903 * Authenticator could be using another MAC address than the BSSID of
4904 * an AP, so just allow any address to be used for now. The replies are
4905 * still sent to the current BSSID (if available), though. */
4906
4907 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4908 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004909 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4910 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004911 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4912 return;
4913 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004914 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004915 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4916 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4917 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004918 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 * handshake processing which would normally set portValid. We
4920 * need this to allow the EAPOL state machines to be completed
4921 * without going through EAPOL-Key handshake.
4922 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004923 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004924 }
4925}
4926
4927
Hai Shalomb755a2a2020-04-23 21:49:02 -07004928static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4929{
4930 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4931 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4932}
4933
4934
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004935int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004936{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004937 if ((!wpa_s->p2p_mgmt ||
4938 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4939 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004940 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004941 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4942 wpa_drv_get_mac_addr(wpa_s),
4943 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004944 wpas_eapol_needs_l2_packet(wpa_s) ?
4945 wpa_supplicant_rx_eapol : NULL,
4946 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004947 if (wpa_s->l2 == NULL)
4948 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004949
4950 if (l2_packet_set_packet_filter(wpa_s->l2,
4951 L2_PACKET_FILTER_PKTTYPE))
4952 wpa_dbg(wpa_s, MSG_DEBUG,
4953 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004954
4955 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4956 wpa_msg(wpa_s, MSG_ERROR,
4957 "Failed to get own L2 address");
4958 return -1;
4959 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960 } else {
4961 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4962 if (addr)
4963 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4964 }
4965
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004966 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004967 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004968
Hai Shalomc3565922019-10-28 11:58:20 -07004969#ifdef CONFIG_FST
4970 if (wpa_s->fst)
4971 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4972#endif /* CONFIG_FST */
4973
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004974 return 0;
4975}
4976
4977
Dmitry Shmidt04949592012-07-19 12:16:46 -07004978static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4979 const u8 *buf, size_t len)
4980{
4981 struct wpa_supplicant *wpa_s = ctx;
4982 const struct l2_ethhdr *eth;
4983
4984 if (len < sizeof(*eth))
4985 return;
4986 eth = (const struct l2_ethhdr *) buf;
4987
4988 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4989 !(eth->h_dest[0] & 0x01)) {
4990 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4991 " (bridge - not for this interface - ignore)",
4992 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4993 return;
4994 }
4995
4996 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4997 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4998 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4999 len - sizeof(*eth));
5000}
5001
5002
Hai Shalom899fcc72020-10-19 14:38:18 -07005003int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5004 const char *bridge_ifname)
5005{
5006 if (wpa_s->wpa_state > WPA_SCANNING)
5007 return -EBUSY;
5008
5009 if (bridge_ifname &&
5010 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5011 return -EINVAL;
5012
5013 if (!bridge_ifname)
5014 bridge_ifname = "";
5015
5016 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5017 return 0;
5018
5019 if (wpa_s->l2_br) {
5020 l2_packet_deinit(wpa_s->l2_br);
5021 wpa_s->l2_br = NULL;
5022 }
5023
5024 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5025 sizeof(wpa_s->bridge_ifname));
5026
5027 if (wpa_s->bridge_ifname[0]) {
5028 wpa_dbg(wpa_s, MSG_DEBUG,
5029 "Receiving packets from bridge interface '%s'",
5030 wpa_s->bridge_ifname);
5031 wpa_s->l2_br = l2_packet_init_bridge(
5032 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5033 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5034 if (!wpa_s->l2_br) {
5035 wpa_msg(wpa_s, MSG_ERROR,
5036 "Failed to open l2_packet connection for the bridge interface '%s'",
5037 wpa_s->bridge_ifname);
5038 goto fail;
5039 }
5040 }
5041
5042#ifdef CONFIG_TDLS
5043 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5044 goto fail;
5045#endif /* CONFIG_TDLS */
5046
5047 return 0;
5048fail:
5049 wpa_s->bridge_ifname[0] = 0;
5050 if (wpa_s->l2_br) {
5051 l2_packet_deinit(wpa_s->l2_br);
5052 wpa_s->l2_br = NULL;
5053 }
5054#ifdef CONFIG_TDLS
5055 if (!wpa_s->p2p_mgmt)
5056 wpa_tdls_init(wpa_s->wpa);
5057#endif /* CONFIG_TDLS */
5058 return -EIO;
5059}
5060
5061
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005062/**
5063 * wpa_supplicant_driver_init - Initialize driver interface parameters
5064 * @wpa_s: Pointer to wpa_supplicant data
5065 * Returns: 0 on success, -1 on failure
5066 *
5067 * This function is called to initialize driver interface parameters.
5068 * wpa_drv_init() must have been called before this function to initialize the
5069 * driver interface.
5070 */
5071int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5072{
5073 static int interface_count = 0;
5074
5075 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5076 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005077
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005078 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5079 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005080 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005081 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5082
Hai Shalomb755a2a2020-04-23 21:49:02 -07005083 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005084 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5085 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005086 wpa_s->l2_br = l2_packet_init_bridge(
5087 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5088 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005089 if (wpa_s->l2_br == NULL) {
5090 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5091 "connection for the bridge interface '%s'",
5092 wpa_s->bridge_ifname);
5093 return -1;
5094 }
5095 }
5096
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005097 if (wpa_s->conf->ap_scan == 2 &&
5098 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5099 wpa_printf(MSG_INFO,
5100 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5101 }
5102
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005103 wpa_clear_keys(wpa_s, NULL);
5104
5105 /* Make sure that TKIP countermeasures are not left enabled (could
5106 * happen if wpa_supplicant is killed during countermeasures. */
5107 wpa_drv_set_countermeasures(wpa_s, 0);
5108
5109 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5110 wpa_drv_flush_pmkid(wpa_s);
5111
5112 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005113 wpa_s->prev_scan_wildcard = 0;
5114
Dmitry Shmidt04949592012-07-19 12:16:46 -07005115 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005116 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5117 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5118 interface_count = 0;
5119 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005120#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005121 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005122 wpa_supplicant_delayed_sched_scan(wpa_s,
5123 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005124 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005125 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005126 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005127#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005128 interface_count++;
5129 } else
5130 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5131
5132 return 0;
5133}
5134
5135
5136static int wpa_supplicant_daemon(const char *pid_file)
5137{
5138 wpa_printf(MSG_DEBUG, "Daemonize..");
5139 return os_daemonize(pid_file);
5140}
5141
5142
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005143static struct wpa_supplicant *
5144wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005145{
5146 struct wpa_supplicant *wpa_s;
5147
5148 wpa_s = os_zalloc(sizeof(*wpa_s));
5149 if (wpa_s == NULL)
5150 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005151 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005152 wpa_s->scan_interval = 5;
5153 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005154 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005155 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005156 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005157 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005158
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005159 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005160 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005161#ifdef CONFIG_TESTING_OPTIONS
5162 dl_list_init(&wpa_s->drv_signal_override);
5163#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005164
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005165 return wpa_s;
5166}
5167
5168
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005169#ifdef CONFIG_HT_OVERRIDES
5170
5171static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5172 struct ieee80211_ht_capabilities *htcaps,
5173 struct ieee80211_ht_capabilities *htcaps_mask,
5174 const char *ht_mcs)
5175{
5176 /* parse ht_mcs into hex array */
5177 int i;
5178 const char *tmp = ht_mcs;
5179 char *end = NULL;
5180
5181 /* If ht_mcs is null, do not set anything */
5182 if (!ht_mcs)
5183 return 0;
5184
5185 /* This is what we are setting in the kernel */
5186 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5187
5188 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5189
5190 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005191 long v;
5192
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005193 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005194 v = strtol(tmp, &end, 16);
5195
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005196 if (errno == 0) {
5197 wpa_msg(wpa_s, MSG_DEBUG,
5198 "htcap value[%i]: %ld end: %p tmp: %p",
5199 i, v, end, tmp);
5200 if (end == tmp)
5201 break;
5202
5203 htcaps->supported_mcs_set[i] = v;
5204 tmp = end;
5205 } else {
5206 wpa_msg(wpa_s, MSG_ERROR,
5207 "Failed to parse ht-mcs: %s, error: %s\n",
5208 ht_mcs, strerror(errno));
5209 return -1;
5210 }
5211 }
5212
5213 /*
5214 * If we were able to parse any values, then set mask for the MCS set.
5215 */
5216 if (i) {
5217 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5218 IEEE80211_HT_MCS_MASK_LEN - 1);
5219 /* skip the 3 reserved bits */
5220 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5221 0x1f;
5222 }
5223
5224 return 0;
5225}
5226
5227
5228static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5229 struct ieee80211_ht_capabilities *htcaps,
5230 struct ieee80211_ht_capabilities *htcaps_mask,
5231 int disabled)
5232{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005233 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005234
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005235 if (disabled == -1)
5236 return 0;
5237
Hai Shalom74f70d42019-02-11 14:42:39 -08005238 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5239
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005240 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5241 htcaps_mask->ht_capabilities_info |= msk;
5242 if (disabled)
5243 htcaps->ht_capabilities_info &= msk;
5244 else
5245 htcaps->ht_capabilities_info |= msk;
5246
5247 return 0;
5248}
5249
5250
5251static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5252 struct ieee80211_ht_capabilities *htcaps,
5253 struct ieee80211_ht_capabilities *htcaps_mask,
5254 int factor)
5255{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005256 if (factor == -1)
5257 return 0;
5258
Hai Shalom74f70d42019-02-11 14:42:39 -08005259 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5260
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005261 if (factor < 0 || factor > 3) {
5262 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5263 "Must be 0-3 or -1", factor);
5264 return -EINVAL;
5265 }
5266
5267 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5268 htcaps->a_mpdu_params &= ~0x3;
5269 htcaps->a_mpdu_params |= factor & 0x3;
5270
5271 return 0;
5272}
5273
5274
5275static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5276 struct ieee80211_ht_capabilities *htcaps,
5277 struct ieee80211_ht_capabilities *htcaps_mask,
5278 int density)
5279{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005280 if (density == -1)
5281 return 0;
5282
Hai Shalom74f70d42019-02-11 14:42:39 -08005283 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5284
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005285 if (density < 0 || density > 7) {
5286 wpa_msg(wpa_s, MSG_ERROR,
5287 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5288 density);
5289 return -EINVAL;
5290 }
5291
5292 htcaps_mask->a_mpdu_params |= 0x1C;
5293 htcaps->a_mpdu_params &= ~(0x1C);
5294 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5295
5296 return 0;
5297}
5298
5299
5300static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5301 struct ieee80211_ht_capabilities *htcaps,
5302 struct ieee80211_ht_capabilities *htcaps_mask,
5303 int disabled)
5304{
Hai Shalom74f70d42019-02-11 14:42:39 -08005305 if (disabled)
5306 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005307
Paul Stewart092955c2017-02-06 09:13:09 -08005308 set_disable_ht40(htcaps, disabled);
5309 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005310
5311 return 0;
5312}
5313
5314
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005315static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5316 struct ieee80211_ht_capabilities *htcaps,
5317 struct ieee80211_ht_capabilities *htcaps_mask,
5318 int disabled)
5319{
5320 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005321 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5322 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005323
Hai Shalom74f70d42019-02-11 14:42:39 -08005324 if (disabled)
5325 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005326
5327 if (disabled)
5328 htcaps->ht_capabilities_info &= ~msk;
5329 else
5330 htcaps->ht_capabilities_info |= msk;
5331
5332 htcaps_mask->ht_capabilities_info |= msk;
5333
5334 return 0;
5335}
5336
5337
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005338static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5339 struct ieee80211_ht_capabilities *htcaps,
5340 struct ieee80211_ht_capabilities *htcaps_mask,
5341 int disabled)
5342{
5343 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005344 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005345
Hai Shalom74f70d42019-02-11 14:42:39 -08005346 if (disabled)
5347 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005348
5349 if (disabled)
5350 htcaps->ht_capabilities_info &= ~msk;
5351 else
5352 htcaps->ht_capabilities_info |= msk;
5353
5354 htcaps_mask->ht_capabilities_info |= msk;
5355
5356 return 0;
5357}
5358
5359
Hai Shalom74f70d42019-02-11 14:42:39 -08005360static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5361 struct ieee80211_ht_capabilities *htcaps,
5362 struct ieee80211_ht_capabilities *htcaps_mask,
5363 int tx_stbc)
5364{
5365 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5366
5367 if (tx_stbc == -1)
5368 return 0;
5369
5370 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5371
5372 if (tx_stbc < 0 || tx_stbc > 1) {
5373 wpa_msg(wpa_s, MSG_ERROR,
5374 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5375 return -EINVAL;
5376 }
5377
5378 htcaps_mask->ht_capabilities_info |= msk;
5379 htcaps->ht_capabilities_info &= ~msk;
5380 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5381
5382 return 0;
5383}
5384
5385
5386static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5387 struct ieee80211_ht_capabilities *htcaps,
5388 struct ieee80211_ht_capabilities *htcaps_mask,
5389 int rx_stbc)
5390{
5391 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5392
5393 if (rx_stbc == -1)
5394 return 0;
5395
5396 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5397
5398 if (rx_stbc < 0 || rx_stbc > 3) {
5399 wpa_msg(wpa_s, MSG_ERROR,
5400 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5401 return -EINVAL;
5402 }
5403
5404 htcaps_mask->ht_capabilities_info |= msk;
5405 htcaps->ht_capabilities_info &= ~msk;
5406 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5407
5408 return 0;
5409}
5410
5411
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005412void wpa_supplicant_apply_ht_overrides(
5413 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5414 struct wpa_driver_associate_params *params)
5415{
5416 struct ieee80211_ht_capabilities *htcaps;
5417 struct ieee80211_ht_capabilities *htcaps_mask;
5418
5419 if (!ssid)
5420 return;
5421
5422 params->disable_ht = ssid->disable_ht;
5423 if (!params->htcaps || !params->htcaps_mask)
5424 return;
5425
5426 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5427 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5428 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5429 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5430 ssid->disable_max_amsdu);
5431 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5432 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5433 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005434 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005435 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005436 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5437 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005438
5439 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005440 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005441 htcaps->ht_capabilities_info |= bit;
5442 htcaps_mask->ht_capabilities_info |= bit;
5443 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005444}
5445
5446#endif /* CONFIG_HT_OVERRIDES */
5447
5448
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005449#ifdef CONFIG_VHT_OVERRIDES
5450void wpa_supplicant_apply_vht_overrides(
5451 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5452 struct wpa_driver_associate_params *params)
5453{
5454 struct ieee80211_vht_capabilities *vhtcaps;
5455 struct ieee80211_vht_capabilities *vhtcaps_mask;
5456
5457 if (!ssid)
5458 return;
5459
5460 params->disable_vht = ssid->disable_vht;
5461
5462 vhtcaps = (void *) params->vhtcaps;
5463 vhtcaps_mask = (void *) params->vhtcaps_mask;
5464
5465 if (!vhtcaps || !vhtcaps_mask)
5466 return;
5467
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005468 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5469 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005470
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005471#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005472 if (ssid->disable_sgi) {
5473 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5474 VHT_CAP_SHORT_GI_160);
5475 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5476 VHT_CAP_SHORT_GI_160);
5477 wpa_msg(wpa_s, MSG_DEBUG,
5478 "disable-sgi override specified, vht-caps: 0x%x",
5479 vhtcaps->vht_capabilities_info);
5480 }
5481
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005482 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005483 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5484 int max_ampdu;
5485
5486 max_ampdu = (ssid->vht_capa &
5487 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5488 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005489
5490 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5491 wpa_set_ampdu_factor(wpa_s,
5492 (void *) params->htcaps,
5493 (void *) params->htcaps_mask,
5494 max_ampdu);
5495 }
5496#endif /* CONFIG_HT_OVERRIDES */
5497
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005498#define OVERRIDE_MCS(i) \
5499 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5500 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005501 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005502 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005503 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5504 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005505 } \
5506 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5507 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005508 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005509 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005510 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5511 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005512 }
5513
5514 OVERRIDE_MCS(1);
5515 OVERRIDE_MCS(2);
5516 OVERRIDE_MCS(3);
5517 OVERRIDE_MCS(4);
5518 OVERRIDE_MCS(5);
5519 OVERRIDE_MCS(6);
5520 OVERRIDE_MCS(7);
5521 OVERRIDE_MCS(8);
5522}
5523#endif /* CONFIG_VHT_OVERRIDES */
5524
5525
Hai Shalomfdcde762020-04-02 11:19:20 -07005526#ifdef CONFIG_HE_OVERRIDES
5527void wpa_supplicant_apply_he_overrides(
5528 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5529 struct wpa_driver_associate_params *params)
5530{
5531 if (!ssid)
5532 return;
5533
5534 params->disable_he = ssid->disable_he;
5535}
5536#endif /* CONFIG_HE_OVERRIDES */
5537
5538
Dmitry Shmidt04949592012-07-19 12:16:46 -07005539static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5540{
5541#ifdef PCSC_FUNCS
5542 size_t len;
5543
5544 if (!wpa_s->conf->pcsc_reader)
5545 return 0;
5546
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005547 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005548 if (!wpa_s->scard)
5549 return 1;
5550
5551 if (wpa_s->conf->pcsc_pin &&
5552 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5553 scard_deinit(wpa_s->scard);
5554 wpa_s->scard = NULL;
5555 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5556 return -1;
5557 }
5558
5559 len = sizeof(wpa_s->imsi) - 1;
5560 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5561 scard_deinit(wpa_s->scard);
5562 wpa_s->scard = NULL;
5563 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5564 return -1;
5565 }
5566 wpa_s->imsi[len] = '\0';
5567
5568 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5569
5570 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5571 wpa_s->imsi, wpa_s->mnc_len);
5572
5573 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5574 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5575#endif /* PCSC_FUNCS */
5576
5577 return 0;
5578}
5579
5580
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005581int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5582{
5583 char *val, *pos;
5584
5585 ext_password_deinit(wpa_s->ext_pw);
5586 wpa_s->ext_pw = NULL;
5587 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5588
5589 if (!wpa_s->conf->ext_password_backend)
5590 return 0;
5591
5592 val = os_strdup(wpa_s->conf->ext_password_backend);
5593 if (val == NULL)
5594 return -1;
5595 pos = os_strchr(val, ':');
5596 if (pos)
5597 *pos++ = '\0';
5598
5599 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5600
5601 wpa_s->ext_pw = ext_password_init(val, pos);
5602 os_free(val);
5603 if (wpa_s->ext_pw == NULL) {
5604 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5605 return -1;
5606 }
5607 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5608
5609 return 0;
5610}
5611
5612
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005613#ifdef CONFIG_FST
5614
5615static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5616{
5617 struct wpa_supplicant *wpa_s = ctx;
5618
5619 return (is_zero_ether_addr(wpa_s->bssid) ||
5620 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5621}
5622
5623
5624static void wpas_fst_get_channel_info_cb(void *ctx,
5625 enum hostapd_hw_mode *hw_mode,
5626 u8 *channel)
5627{
5628 struct wpa_supplicant *wpa_s = ctx;
5629
5630 if (wpa_s->current_bss) {
5631 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5632 channel);
5633 } else if (wpa_s->hw.num_modes) {
5634 *hw_mode = wpa_s->hw.modes[0].mode;
5635 } else {
5636 WPA_ASSERT(0);
5637 *hw_mode = 0;
5638 }
5639}
5640
5641
5642static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5643{
5644 struct wpa_supplicant *wpa_s = ctx;
5645
5646 *modes = wpa_s->hw.modes;
5647 return wpa_s->hw.num_modes;
5648}
5649
5650
5651static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5652{
5653 struct wpa_supplicant *wpa_s = ctx;
5654
5655 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5656 wpa_s->fst_ies = fst_ies;
5657}
5658
5659
5660static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5661{
5662 struct wpa_supplicant *wpa_s = ctx;
5663
Paul Stewart092955c2017-02-06 09:13:09 -08005664 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5665 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5666 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5667 return -1;
5668 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005669 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005670 wpa_s->own_addr, wpa_s->bssid,
5671 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005672 0);
5673}
5674
5675
5676static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5677{
5678 struct wpa_supplicant *wpa_s = ctx;
5679
5680 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5681 return wpa_s->received_mb_ies;
5682}
5683
5684
5685static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5686 const u8 *buf, size_t size)
5687{
5688 struct wpa_supplicant *wpa_s = ctx;
5689 struct mb_ies_info info;
5690
5691 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5692
5693 if (!mb_ies_info_by_ies(&info, buf, size)) {
5694 wpabuf_free(wpa_s->received_mb_ies);
5695 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5696 }
5697}
5698
5699
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005700static const u8 * wpas_fst_get_peer_first(void *ctx,
5701 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005702 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005703{
5704 struct wpa_supplicant *wpa_s = ctx;
5705
5706 *get_ctx = NULL;
5707 if (!is_zero_ether_addr(wpa_s->bssid))
5708 return (wpa_s->received_mb_ies || !mb_only) ?
5709 wpa_s->bssid : NULL;
5710 return NULL;
5711}
5712
5713
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005714static const u8 * wpas_fst_get_peer_next(void *ctx,
5715 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005716 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005717{
5718 return NULL;
5719}
5720
5721void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5722 struct fst_wpa_obj *iface_obj)
5723{
5724 iface_obj->ctx = wpa_s;
5725 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5726 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5727 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5728 iface_obj->set_ies = wpas_fst_set_ies_cb;
5729 iface_obj->send_action = wpas_fst_send_action_cb;
5730 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5731 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5732 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5733 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5734}
5735#endif /* CONFIG_FST */
5736
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005737static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005738 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005739{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005740 struct wowlan_triggers *triggers;
5741 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005742
5743 if (!wpa_s->conf->wowlan_triggers)
5744 return 0;
5745
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005746 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5747 if (triggers) {
5748 ret = wpa_drv_wowlan(wpa_s, triggers);
5749 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005750 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005751 return ret;
5752}
5753
5754
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005755enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005756{
5757 if (freq < 3000)
5758 return BAND_2_4_GHZ;
5759 if (freq > 50000)
5760 return BAND_60_GHZ;
5761 return BAND_5_GHZ;
5762}
5763
5764
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005765unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005766{
5767 int i;
5768 unsigned int band = 0;
5769
5770 if (freqs) {
5771 /* freqs are specified for the radio work */
5772 for (i = 0; freqs[i]; i++)
5773 band |= wpas_freq_to_band(freqs[i]);
5774 } else {
5775 /*
5776 * freqs are not specified, implies all
5777 * the supported freqs by HW
5778 */
5779 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5780 if (wpa_s->hw.modes[i].num_channels != 0) {
5781 if (wpa_s->hw.modes[i].mode ==
5782 HOSTAPD_MODE_IEEE80211B ||
5783 wpa_s->hw.modes[i].mode ==
5784 HOSTAPD_MODE_IEEE80211G)
5785 band |= BAND_2_4_GHZ;
5786 else if (wpa_s->hw.modes[i].mode ==
5787 HOSTAPD_MODE_IEEE80211A)
5788 band |= BAND_5_GHZ;
5789 else if (wpa_s->hw.modes[i].mode ==
5790 HOSTAPD_MODE_IEEE80211AD)
5791 band |= BAND_60_GHZ;
5792 else if (wpa_s->hw.modes[i].mode ==
5793 HOSTAPD_MODE_IEEE80211ANY)
5794 band = BAND_2_4_GHZ | BAND_5_GHZ |
5795 BAND_60_GHZ;
5796 }
5797 }
5798 }
5799
5800 return band;
5801}
5802
5803
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005804static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5805 const char *rn)
5806{
5807 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5808 struct wpa_radio *radio;
5809
5810 while (rn && iface) {
5811 radio = iface->radio;
5812 if (radio && os_strcmp(rn, radio->name) == 0) {
5813 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5814 wpa_s->ifname, rn);
5815 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5816 return radio;
5817 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005818
5819 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005820 }
5821
5822 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5823 wpa_s->ifname, rn ? rn : "N/A");
5824 radio = os_zalloc(sizeof(*radio));
5825 if (radio == NULL)
5826 return NULL;
5827
5828 if (rn)
5829 os_strlcpy(radio->name, rn, sizeof(radio->name));
5830 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005831 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005832 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5833
5834 return radio;
5835}
5836
5837
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005838static void radio_work_free(struct wpa_radio_work *work)
5839{
5840 if (work->wpa_s->scan_work == work) {
5841 /* This should not really happen. */
5842 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5843 work->type, work, work->started);
5844 work->wpa_s->scan_work = NULL;
5845 }
5846
5847#ifdef CONFIG_P2P
5848 if (work->wpa_s->p2p_scan_work == work) {
5849 /* This should not really happen. */
5850 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5851 work->type, work, work->started);
5852 work->wpa_s->p2p_scan_work = NULL;
5853 }
5854#endif /* CONFIG_P2P */
5855
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005856 if (work->started) {
5857 work->wpa_s->radio->num_active_works--;
5858 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005859 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005860 work->type, work,
5861 work->wpa_s->radio->num_active_works);
5862 }
5863
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005864 dl_list_del(&work->list);
5865 os_free(work);
5866}
5867
5868
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005869static int radio_work_is_connect(struct wpa_radio_work *work)
5870{
5871 return os_strcmp(work->type, "sme-connect") == 0 ||
5872 os_strcmp(work->type, "connect") == 0;
5873}
5874
5875
5876static int radio_work_is_scan(struct wpa_radio_work *work)
5877{
5878 return os_strcmp(work->type, "scan") == 0 ||
5879 os_strcmp(work->type, "p2p-scan") == 0;
5880}
5881
5882
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005883static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5884{
5885 struct wpa_radio_work *active_work = NULL;
5886 struct wpa_radio_work *tmp;
5887
5888 /* Get the active work to know the type and band. */
5889 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5890 if (tmp->started) {
5891 active_work = tmp;
5892 break;
5893 }
5894 }
5895
5896 if (!active_work) {
5897 /* No active work, start one */
5898 radio->num_active_works = 0;
5899 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5900 list) {
5901 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005902 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005903 (((struct wpa_driver_scan_params *)
5904 tmp->ctx)->only_new_results ||
5905 tmp->wpa_s->clear_driver_scan_cache))
5906 continue;
5907 return tmp;
5908 }
5909 return NULL;
5910 }
5911
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005912 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005913 /*
5914 * If the active work is either connect or sme-connect,
5915 * do not parallelize them with other radio works.
5916 */
5917 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5918 "Do not parallelize radio work with %s",
5919 active_work->type);
5920 return NULL;
5921 }
5922
5923 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5924 if (tmp->started)
5925 continue;
5926
5927 /*
5928 * If connect or sme-connect are enqueued, parallelize only
5929 * those operations ahead of them in the queue.
5930 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005931 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005932 break;
5933
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005934 /* Serialize parallel scan and p2p_scan operations on the same
5935 * interface since the driver_nl80211 mechanism for tracking
5936 * scan cookies does not yet have support for this. */
5937 if (active_work->wpa_s == tmp->wpa_s &&
5938 radio_work_is_scan(active_work) &&
5939 radio_work_is_scan(tmp)) {
5940 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5941 "Do not start work '%s' when another work '%s' is already scheduled",
5942 tmp->type, active_work->type);
5943 continue;
5944 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005945 /*
5946 * Check that the radio works are distinct and
5947 * on different bands.
5948 */
5949 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5950 (active_work->bands != tmp->bands)) {
5951 /*
5952 * If a scan has to be scheduled through nl80211 scan
5953 * interface and if an external scan is already running,
5954 * do not schedule the scan since it is likely to get
5955 * rejected by kernel.
5956 */
5957 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005958 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005959 (((struct wpa_driver_scan_params *)
5960 tmp->ctx)->only_new_results ||
5961 tmp->wpa_s->clear_driver_scan_cache))
5962 continue;
5963
5964 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5965 "active_work:%s new_work:%s",
5966 active_work->type, tmp->type);
5967 return tmp;
5968 }
5969 }
5970
5971 /* Did not find a radio work to schedule in parallel. */
5972 return NULL;
5973}
5974
5975
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005976static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5977{
5978 struct wpa_radio *radio = eloop_ctx;
5979 struct wpa_radio_work *work;
5980 struct os_reltime now, diff;
5981 struct wpa_supplicant *wpa_s;
5982
5983 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005984 if (work == NULL) {
5985 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005986 return;
5987 }
5988
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005989 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5990 radio_list);
5991
5992 if (!(wpa_s &&
5993 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5994 if (work->started)
5995 return; /* already started and still in progress */
5996
Hai Shalom60840252021-02-19 19:02:11 -08005997 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005998 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5999 return;
6000 }
6001 } else {
6002 work = NULL;
6003 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6004 /* get the work to schedule next */
6005 work = radio_work_get_next_work(radio);
6006 }
6007 if (!work)
6008 return;
6009 }
6010
6011 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006012 os_get_reltime(&now);
6013 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006014 wpa_dbg(wpa_s, MSG_DEBUG,
6015 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006016 work->type, work, diff.sec, diff.usec);
6017 work->started = 1;
6018 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006019 radio->num_active_works++;
6020
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006021 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006022
6023 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6024 radio->num_active_works < MAX_ACTIVE_WORKS)
6025 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006026}
6027
6028
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006029/*
6030 * This function removes both started and pending radio works running on
6031 * the provided interface's radio.
6032 * Prior to the removal of the radio work, its callback (cb) is called with
6033 * deinit set to be 1. Each work's callback is responsible for clearing its
6034 * internal data and restoring to a correct state.
6035 * @wpa_s: wpa_supplicant data
6036 * @type: type of works to be removed
6037 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6038 * this interface's works.
6039 */
6040void radio_remove_works(struct wpa_supplicant *wpa_s,
6041 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006042{
6043 struct wpa_radio_work *work, *tmp;
6044 struct wpa_radio *radio = wpa_s->radio;
6045
6046 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6047 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006048 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006049 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006050
6051 /* skip other ifaces' works */
6052 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006053 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006054
6055 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6056 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006057 work->cb(work, 1);
6058 radio_work_free(work);
6059 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006060
6061 /* in case we removed the started work */
6062 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006063}
6064
6065
Roshan Pius3a1667e2018-07-03 15:17:14 -07006066void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6067{
6068 struct wpa_radio_work *work;
6069 struct wpa_radio *radio = wpa_s->radio;
6070
6071 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6072 if (work->ctx != ctx)
6073 continue;
6074 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6075 work->type, work, work->started ? " (started)" : "");
6076 radio_work_free(work);
6077 break;
6078 }
6079}
6080
6081
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006082static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6083{
6084 struct wpa_radio *radio = wpa_s->radio;
6085
6086 if (!radio)
6087 return;
6088
6089 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6090 wpa_s->ifname, radio->name);
6091 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006092 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006093 /* If the interface that triggered the external scan was removed, the
6094 * external scan is no longer running. */
6095 if (wpa_s == radio->external_scan_req_interface)
6096 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006097 wpa_s->radio = NULL;
6098 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006099 return; /* Interfaces remain for this radio */
6100
6101 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006102 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006103 os_free(radio);
6104}
6105
6106
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006107void radio_work_check_next(struct wpa_supplicant *wpa_s)
6108{
6109 struct wpa_radio *radio = wpa_s->radio;
6110
6111 if (dl_list_empty(&radio->work))
6112 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006113 if (wpa_s->ext_work_in_progress) {
6114 wpa_printf(MSG_DEBUG,
6115 "External radio work in progress - delay start of pending item");
6116 return;
6117 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006118 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6119 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6120}
6121
6122
6123/**
6124 * radio_add_work - Add a radio work item
6125 * @wpa_s: Pointer to wpa_supplicant data
6126 * @freq: Frequency of the offchannel operation in MHz or 0
6127 * @type: Unique identifier for each type of work
6128 * @next: Force as the next work to be executed
6129 * @cb: Callback function for indicating when radio is available
6130 * @ctx: Context pointer for the work (work->ctx in cb())
6131 * Returns: 0 on success, -1 on failure
6132 *
6133 * This function is used to request time for an operation that requires
6134 * exclusive radio control. Once the radio is available, the registered callback
6135 * function will be called. radio_work_done() must be called once the exclusive
6136 * radio operation has been completed, so that the radio is freed for other
6137 * operations. The special case of deinit=1 is used to free the context data
6138 * during interface removal. That does not allow the callback function to start
6139 * the radio operation, i.e., it must free any resources allocated for the radio
6140 * work and return.
6141 *
6142 * The @freq parameter can be used to indicate a single channel on which the
6143 * offchannel operation will occur. This may allow multiple radio work
6144 * operations to be performed in parallel if they apply for the same channel.
6145 * Setting this to 0 indicates that the work item may use multiple channels or
6146 * requires exclusive control of the radio.
6147 */
6148int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6149 const char *type, int next,
6150 void (*cb)(struct wpa_radio_work *work, int deinit),
6151 void *ctx)
6152{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006153 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006154 struct wpa_radio_work *work;
6155 int was_empty;
6156
6157 work = os_zalloc(sizeof(*work));
6158 if (work == NULL)
6159 return -1;
6160 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6161 os_get_reltime(&work->time);
6162 work->freq = freq;
6163 work->type = type;
6164 work->wpa_s = wpa_s;
6165 work->cb = cb;
6166 work->ctx = ctx;
6167
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006168 if (freq)
6169 work->bands = wpas_freq_to_band(freq);
6170 else if (os_strcmp(type, "scan") == 0 ||
6171 os_strcmp(type, "p2p-scan") == 0)
6172 work->bands = wpas_get_bands(wpa_s,
6173 ((struct wpa_driver_scan_params *)
6174 ctx)->freqs);
6175 else
6176 work->bands = wpas_get_bands(wpa_s, NULL);
6177
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006178 was_empty = dl_list_empty(&wpa_s->radio->work);
6179 if (next)
6180 dl_list_add(&wpa_s->radio->work, &work->list);
6181 else
6182 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6183 if (was_empty) {
6184 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6185 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006186 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6187 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6188 wpa_dbg(wpa_s, MSG_DEBUG,
6189 "Try to schedule a radio work (num_active_works=%u)",
6190 radio->num_active_works);
6191 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006192 }
6193
6194 return 0;
6195}
6196
6197
6198/**
6199 * radio_work_done - Indicate that a radio work item has been completed
6200 * @work: Completed work
6201 *
6202 * This function is called once the callback function registered with
6203 * radio_add_work() has completed its work.
6204 */
6205void radio_work_done(struct wpa_radio_work *work)
6206{
6207 struct wpa_supplicant *wpa_s = work->wpa_s;
6208 struct os_reltime now, diff;
6209 unsigned int started = work->started;
6210
6211 os_get_reltime(&now);
6212 os_reltime_sub(&now, &work->time, &diff);
6213 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6214 work->type, work, started ? "done" : "canceled",
6215 diff.sec, diff.usec);
6216 radio_work_free(work);
6217 if (started)
6218 radio_work_check_next(wpa_s);
6219}
6220
6221
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006222struct wpa_radio_work *
6223radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006224{
6225 struct wpa_radio_work *work;
6226 struct wpa_radio *radio = wpa_s->radio;
6227
6228 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6229 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006230 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006231 }
6232
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006233 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006234}
6235
6236
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006237static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006238 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006239{
6240 const char *ifname, *driver, *rn;
6241
6242 driver = iface->driver;
6243next_driver:
6244 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6245 return -1;
6246
6247 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6248 if (wpa_s->drv_priv == NULL) {
6249 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006250 int level = MSG_ERROR;
6251
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006252 pos = driver ? os_strchr(driver, ',') : NULL;
6253 if (pos) {
6254 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6255 "driver interface - try next driver wrapper");
6256 driver = pos + 1;
6257 goto next_driver;
6258 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006259
6260#ifdef CONFIG_MATCH_IFACE
6261 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6262 level = MSG_DEBUG;
6263#endif /* CONFIG_MATCH_IFACE */
6264 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006265 return -1;
6266 }
6267 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6268 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6269 "driver_param '%s'", wpa_s->conf->driver_param);
6270 return -1;
6271 }
6272
6273 ifname = wpa_drv_get_ifname(wpa_s);
6274 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6275 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6276 "interface name with '%s'", ifname);
6277 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6278 }
6279
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006280 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006281 if (rn && rn[0] == '\0')
6282 rn = NULL;
6283
6284 wpa_s->radio = radio_add_interface(wpa_s, rn);
6285 if (wpa_s->radio == NULL)
6286 return -1;
6287
6288 return 0;
6289}
6290
6291
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006292#ifdef CONFIG_GAS_SERVER
6293
6294static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6295 unsigned int freq, const u8 *dst,
6296 const u8 *src, const u8 *bssid,
6297 const u8 *data, size_t data_len,
6298 enum offchannel_send_action_result result)
6299{
6300 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6301 " result=%s",
6302 freq, MAC2STR(dst),
6303 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6304 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6305 "FAILED"));
6306 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6307 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6308}
6309
6310
6311static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6312 struct wpabuf *buf, unsigned int wait_time)
6313{
6314 struct wpa_supplicant *wpa_s = ctx;
6315 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6316
6317 if (wait_time > wpa_s->max_remain_on_chan)
6318 wait_time = wpa_s->max_remain_on_chan;
6319
6320 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6321 wpabuf_head(buf), wpabuf_len(buf),
6322 wait_time, wpas_gas_server_tx_status, 0);
6323}
6324
6325#endif /* CONFIG_GAS_SERVER */
6326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006327static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006328 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006329{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006330 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006331 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006332 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006333
6334 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6335 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6336 iface->confname ? iface->confname : "N/A",
6337 iface->driver ? iface->driver : "default",
6338 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6339 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6340
6341 if (iface->confname) {
6342#ifdef CONFIG_BACKEND_FILE
6343 wpa_s->confname = os_rel2abs_path(iface->confname);
6344 if (wpa_s->confname == NULL) {
6345 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6346 "for configuration file '%s'.",
6347 iface->confname);
6348 return -1;
6349 }
6350 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6351 iface->confname, wpa_s->confname);
6352#else /* CONFIG_BACKEND_FILE */
6353 wpa_s->confname = os_strdup(iface->confname);
6354#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006355 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006356 if (wpa_s->conf == NULL) {
6357 wpa_printf(MSG_ERROR, "Failed to read or parse "
6358 "configuration '%s'.", wpa_s->confname);
6359 return -1;
6360 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006361 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006362 if (wpa_s->confanother &&
6363 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6364 wpa_printf(MSG_ERROR,
6365 "Failed to read or parse configuration '%s'.",
6366 wpa_s->confanother);
6367 return -1;
6368 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006369
6370 /*
6371 * Override ctrl_interface and driver_param if set on command
6372 * line.
6373 */
6374 if (iface->ctrl_interface) {
6375 os_free(wpa_s->conf->ctrl_interface);
6376 wpa_s->conf->ctrl_interface =
6377 os_strdup(iface->ctrl_interface);
6378 }
6379
6380 if (iface->driver_param) {
6381 os_free(wpa_s->conf->driver_param);
6382 wpa_s->conf->driver_param =
6383 os_strdup(iface->driver_param);
6384 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006385
6386 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6387 os_free(wpa_s->conf->ctrl_interface);
6388 wpa_s->conf->ctrl_interface = NULL;
6389 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006390 } else
6391 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6392 iface->driver_param);
6393
6394 if (wpa_s->conf == NULL) {
6395 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6396 return -1;
6397 }
6398
6399 if (iface->ifname == NULL) {
6400 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6401 return -1;
6402 }
6403 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6404 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6405 iface->ifname);
6406 return -1;
6407 }
6408 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006409#ifdef CONFIG_MATCH_IFACE
6410 wpa_s->matched = iface->matched;
6411#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006412
6413 if (iface->bridge_ifname) {
6414 if (os_strlen(iface->bridge_ifname) >=
6415 sizeof(wpa_s->bridge_ifname)) {
6416 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6417 "name '%s'.", iface->bridge_ifname);
6418 return -1;
6419 }
6420 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6421 sizeof(wpa_s->bridge_ifname));
6422 }
6423
6424 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006425 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6426 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006427
6428 /* Initialize driver interface and register driver event handler before
6429 * L2 receive handler so that association events are processed before
6430 * EAPOL-Key packets if both become available for the same select()
6431 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006432 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006433 return -1;
6434
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006435 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6436 return -1;
6437
6438 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6439 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6440 NULL);
6441 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6442
6443 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6444 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6445 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6446 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6447 "dot11RSNAConfigPMKLifetime");
6448 return -1;
6449 }
6450
6451 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6452 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6453 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6454 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6455 "dot11RSNAConfigPMKReauthThreshold");
6456 return -1;
6457 }
6458
6459 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6460 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6461 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6462 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6463 "dot11RSNAConfigSATimeout");
6464 return -1;
6465 }
6466
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006467 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6468 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006469 &wpa_s->hw.flags,
6470 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006471 if (wpa_s->hw.modes) {
6472 u16 i;
6473
6474 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6475 if (wpa_s->hw.modes[i].vht_capab) {
6476 wpa_s->hw_capab = CAPAB_VHT;
6477 break;
6478 }
6479
6480 if (wpa_s->hw.modes[i].ht_capab &
6481 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6482 wpa_s->hw_capab = CAPAB_HT40;
6483 else if (wpa_s->hw.modes[i].ht_capab &&
6484 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6485 wpa_s->hw_capab = CAPAB_HT;
6486 }
6487 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006488
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006489 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6490 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006491 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006492 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006493 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006494 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006495 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006496 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006497 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006498 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006499 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6500 wpa_s->max_sched_scan_plan_interval =
6501 capa.max_sched_scan_plan_interval;
6502 wpa_s->max_sched_scan_plan_iterations =
6503 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006504 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6505 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006506 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6507 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006508 wpa_s->extended_capa = capa.extended_capa;
6509 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6510 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006511 wpa_s->num_multichan_concurrent =
6512 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006513 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6514
6515 if (capa.mac_addr_rand_scan_supported)
6516 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6517 if (wpa_s->sched_scan_supported &&
6518 capa.mac_addr_rand_sched_scan_supported)
6519 wpa_s->mac_addr_rand_supported |=
6520 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006521
6522 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6523 if (wpa_s->extended_capa &&
6524 wpa_s->extended_capa_len >= 3 &&
6525 wpa_s->extended_capa[2] & 0x40)
6526 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006527 }
6528 if (wpa_s->max_remain_on_chan == 0)
6529 wpa_s->max_remain_on_chan = 1000;
6530
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006531 /*
6532 * Only take p2p_mgmt parameters when P2P Device is supported.
6533 * Doing it here as it determines whether l2_packet_init() will be done
6534 * during wpa_supplicant_driver_init().
6535 */
6536 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6537 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006538
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006539 if (wpa_s->num_multichan_concurrent == 0)
6540 wpa_s->num_multichan_concurrent = 1;
6541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006542 if (wpa_supplicant_driver_init(wpa_s) < 0)
6543 return -1;
6544
6545#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006546 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006547 return -1;
6548#endif /* CONFIG_TDLS */
6549
6550 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6551 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6552 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6553 return -1;
6554 }
6555
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006556#ifdef CONFIG_FST
6557 if (wpa_s->conf->fst_group_id) {
6558 struct fst_iface_cfg cfg;
6559 struct fst_wpa_obj iface_obj;
6560
6561 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6562 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6563 sizeof(cfg.group_id));
6564 cfg.priority = wpa_s->conf->fst_priority;
6565 cfg.llt = wpa_s->conf->fst_llt;
6566
6567 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6568 &iface_obj, &cfg);
6569 if (!wpa_s->fst) {
6570 wpa_msg(wpa_s, MSG_ERROR,
6571 "FST: Cannot attach iface %s to group %s",
6572 wpa_s->ifname, cfg.group_id);
6573 return -1;
6574 }
6575 }
6576#endif /* CONFIG_FST */
6577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006578 if (wpas_wps_init(wpa_s))
6579 return -1;
6580
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006581#ifdef CONFIG_GAS_SERVER
6582 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6583 if (!wpa_s->gas_server) {
6584 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6585 return -1;
6586 }
6587#endif /* CONFIG_GAS_SERVER */
6588
6589#ifdef CONFIG_DPP
6590 if (wpas_dpp_init(wpa_s) < 0)
6591 return -1;
6592#endif /* CONFIG_DPP */
6593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006594 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6595 return -1;
6596 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6597
6598 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6599 if (wpa_s->ctrl_iface == NULL) {
6600 wpa_printf(MSG_ERROR,
6601 "Failed to initialize control interface '%s'.\n"
6602 "You may have another wpa_supplicant process "
6603 "already running or the file was\n"
6604 "left by an unclean termination of wpa_supplicant "
6605 "in which case you will need\n"
6606 "to manually remove this file before starting "
6607 "wpa_supplicant again.\n",
6608 wpa_s->conf->ctrl_interface);
6609 return -1;
6610 }
6611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006612 wpa_s->gas = gas_query_init(wpa_s);
6613 if (wpa_s->gas == NULL) {
6614 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6615 return -1;
6616 }
6617
Roshan Pius3a1667e2018-07-03 15:17:14 -07006618 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6619 wpa_s->p2p_mgmt) &&
6620 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006621 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6622 return -1;
6623 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006624
6625 if (wpa_bss_init(wpa_s) < 0)
6626 return -1;
6627
Paul Stewart092955c2017-02-06 09:13:09 -08006628#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6629#ifdef CONFIG_MESH
6630 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6631#endif /* CONFIG_MESH */
6632#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6633
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006634 /*
6635 * Set Wake-on-WLAN triggers, if configured.
6636 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6637 * have effect anyway when the interface is down).
6638 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006639 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006640 return -1;
6641
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006642#ifdef CONFIG_EAP_PROXY
6643{
6644 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006645 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6646 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006647 if (wpa_s->mnc_len > 0) {
6648 wpa_s->imsi[len] = '\0';
6649 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6650 wpa_s->imsi, wpa_s->mnc_len);
6651 } else {
6652 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6653 }
6654}
6655#endif /* CONFIG_EAP_PROXY */
6656
Dmitry Shmidt04949592012-07-19 12:16:46 -07006657 if (pcsc_reader_init(wpa_s) < 0)
6658 return -1;
6659
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006660 if (wpas_init_ext_pw(wpa_s) < 0)
6661 return -1;
6662
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006663 wpas_rrm_reset(wpa_s);
6664
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006665 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6666
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006667#ifdef CONFIG_HS20
6668 hs20_init(wpa_s);
6669#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006670#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006671 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006672 if ((wpa_s->conf->oce & OCE_STA) &&
6673 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6674 wpa_s->enable_oce = OCE_STA;
6675 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6676 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6677 /* TODO: Need to add STA-CFON support */
6678 wpa_printf(MSG_ERROR,
6679 "OCE STA-CFON feature is not yet supported");
6680 }
6681 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006682 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6683#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006684
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006685 wpa_supplicant_set_default_scan_ies(wpa_s);
6686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006687 return 0;
6688}
6689
6690
6691static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006692 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006693{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006694 struct wpa_global *global = wpa_s->global;
6695 struct wpa_supplicant *iface, *prev;
6696
Jimmy Chen0e73c002021-08-18 13:21:30 +08006697 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006698 wpas_p2p_group_remove(wpa_s, "*");
6699
6700 iface = global->ifaces;
6701 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006702 if (iface->p2pdev == wpa_s)
6703 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006704 if (iface == wpa_s || iface->parent != wpa_s) {
6705 iface = iface->next;
6706 continue;
6707 }
6708 wpa_printf(MSG_DEBUG,
6709 "Remove remaining child interface %s from parent %s",
6710 iface->ifname, wpa_s->ifname);
6711 prev = iface;
6712 iface = iface->next;
6713 wpa_supplicant_remove_iface(global, prev, terminate);
6714 }
6715
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006716 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006717 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006718 /*
6719 * Don't deauthenticate if WoWLAN is enable and not explicitly
6720 * been configured to disconnect.
6721 */
6722 if (!wpa_drv_get_wowlan(wpa_s) ||
6723 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006724 wpa_supplicant_deauthenticate(
6725 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006726
Hai Shalomfdcde762020-04-02 11:19:20 -07006727 wpa_drv_set_countermeasures(wpa_s, 0);
6728 wpa_clear_keys(wpa_s, NULL);
6729 } else {
6730 wpa_msg(wpa_s, MSG_INFO,
6731 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6732 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006733 }
6734
6735 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006736 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006737
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006738 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006739 radio_remove_interface(wpa_s);
6740
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006741#ifdef CONFIG_FST
6742 if (wpa_s->fst) {
6743 fst_detach(wpa_s->fst);
6744 wpa_s->fst = NULL;
6745 }
6746 if (wpa_s->received_mb_ies) {
6747 wpabuf_free(wpa_s->received_mb_ies);
6748 wpa_s->received_mb_ies = NULL;
6749 }
6750#endif /* CONFIG_FST */
6751
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006752 if (wpa_s->drv_priv)
6753 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006754
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006755 if (notify)
6756 wpas_notify_iface_removed(wpa_s);
6757
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006758 if (terminate)
6759 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006760
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02006761 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
6762 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006763
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006764#ifdef CONFIG_MESH
6765 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08006766 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006767 wpa_s->ifmsh = NULL;
6768 }
6769#endif /* CONFIG_MESH */
6770
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006771 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006772 wpa_config_free(wpa_s->conf);
6773 wpa_s->conf = NULL;
6774 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006775
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006776 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006777 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006778
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006779 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006780}
6781
6782
Dmitry Shmidte4663042016-04-04 10:07:49 -07006783#ifdef CONFIG_MATCH_IFACE
6784
6785/**
6786 * wpa_supplicant_match_iface - Match an interface description to a name
6787 * @global: Pointer to global data from wpa_supplicant_init()
6788 * @ifname: Name of the interface to match
6789 * Returns: Pointer to the created interface description or %NULL on failure
6790 */
6791struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6792 const char *ifname)
6793{
6794 int i;
6795 struct wpa_interface *iface, *miface;
6796
6797 for (i = 0; i < global->params.match_iface_count; i++) {
6798 miface = &global->params.match_ifaces[i];
6799 if (!miface->ifname ||
6800 fnmatch(miface->ifname, ifname, 0) == 0) {
6801 iface = os_zalloc(sizeof(*iface));
6802 if (!iface)
6803 return NULL;
6804 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07006805 if (!miface->ifname)
6806 iface->matched = WPA_IFACE_MATCHED_NULL;
6807 else
6808 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006809 iface->ifname = ifname;
6810 return iface;
6811 }
6812 }
6813
6814 return NULL;
6815}
6816
6817
6818/**
6819 * wpa_supplicant_match_existing - Match existing interfaces
6820 * @global: Pointer to global data from wpa_supplicant_init()
6821 * Returns: 0 on success, -1 on failure
6822 */
6823static int wpa_supplicant_match_existing(struct wpa_global *global)
6824{
6825 struct if_nameindex *ifi, *ifp;
6826 struct wpa_supplicant *wpa_s;
6827 struct wpa_interface *iface;
6828
6829 ifp = if_nameindex();
6830 if (!ifp) {
6831 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6832 return -1;
6833 }
6834
6835 for (ifi = ifp; ifi->if_name; ifi++) {
6836 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6837 if (wpa_s)
6838 continue;
6839 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6840 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08006841 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006842 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006843 }
6844 }
6845
6846 if_freenameindex(ifp);
6847 return 0;
6848}
6849
6850#endif /* CONFIG_MATCH_IFACE */
6851
6852
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006853/**
6854 * wpa_supplicant_add_iface - Add a new network interface
6855 * @global: Pointer to global data from wpa_supplicant_init()
6856 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006857 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006858 * Returns: Pointer to the created interface or %NULL on failure
6859 *
6860 * This function is used to add new network interfaces for %wpa_supplicant.
6861 * This can be called before wpa_supplicant_run() to add interfaces before the
6862 * main event loop has been started. In addition, new interfaces can be added
6863 * dynamically while %wpa_supplicant is already running. This could happen,
6864 * e.g., when a hotplug network adapter is inserted.
6865 */
6866struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006867 struct wpa_interface *iface,
6868 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006869{
6870 struct wpa_supplicant *wpa_s;
6871 struct wpa_interface t_iface;
6872 struct wpa_ssid *ssid;
6873
6874 if (global == NULL || iface == NULL)
6875 return NULL;
6876
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006877 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006878 if (wpa_s == NULL)
6879 return NULL;
6880
6881 wpa_s->global = global;
6882
6883 t_iface = *iface;
6884 if (global->params.override_driver) {
6885 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6886 "('%s' -> '%s')",
6887 iface->driver, global->params.override_driver);
6888 t_iface.driver = global->params.override_driver;
6889 }
6890 if (global->params.override_ctrl_interface) {
6891 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6892 "ctrl_interface ('%s' -> '%s')",
6893 iface->ctrl_interface,
6894 global->params.override_ctrl_interface);
6895 t_iface.ctrl_interface =
6896 global->params.override_ctrl_interface;
6897 }
6898 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6899 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6900 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006901 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006902 return NULL;
6903 }
6904
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006905 /* Notify the control interfaces about new iface */
6906 if (wpas_notify_iface_added(wpa_s)) {
6907 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6908 return NULL;
6909 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006910
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006911 /* Notify the control interfaces about new networks for non p2p mgmt
6912 * ifaces. */
6913 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006914 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6915 wpas_notify_network_added(wpa_s, ssid);
6916 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006917
6918 wpa_s->next = global->ifaces;
6919 global->ifaces = wpa_s;
6920
6921 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006922 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006923
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006924#ifdef CONFIG_P2P
6925 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006926 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006927 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006928 wpas_p2p_add_p2pdev_interface(
6929 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006930 wpa_printf(MSG_INFO,
6931 "P2P: Failed to enable P2P Device interface");
6932 /* Try to continue without. P2P will be disabled. */
6933 }
6934#endif /* CONFIG_P2P */
6935
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006936 return wpa_s;
6937}
6938
6939
6940/**
6941 * wpa_supplicant_remove_iface - Remove a network interface
6942 * @global: Pointer to global data from wpa_supplicant_init()
6943 * @wpa_s: Pointer to the network interface to be removed
6944 * Returns: 0 if interface was removed, -1 if interface was not found
6945 *
6946 * This function can be used to dynamically remove network interfaces from
6947 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6948 * addition, this function is used to remove all remaining interfaces when
6949 * %wpa_supplicant is terminated.
6950 */
6951int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006952 struct wpa_supplicant *wpa_s,
6953 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954{
6955 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006956#ifdef CONFIG_MESH
6957 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6958 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006959 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006960#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006961
6962 /* Remove interface from the global list of interfaces */
6963 prev = global->ifaces;
6964 if (prev == wpa_s) {
6965 global->ifaces = wpa_s->next;
6966 } else {
6967 while (prev && prev->next != wpa_s)
6968 prev = prev->next;
6969 if (prev == NULL)
6970 return -1;
6971 prev->next = wpa_s->next;
6972 }
6973
6974 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6975
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006976#ifdef CONFIG_MESH
6977 if (mesh_if_created) {
6978 ifname = os_strdup(wpa_s->ifname);
6979 if (ifname == NULL) {
6980 wpa_dbg(wpa_s, MSG_ERROR,
6981 "mesh: Failed to malloc ifname");
6982 return -1;
6983 }
6984 }
6985#endif /* CONFIG_MESH */
6986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006987 if (global->p2p_group_formation == wpa_s)
6988 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006989 if (global->p2p_invite_group == wpa_s)
6990 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006991 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006992
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006993#ifdef CONFIG_MESH
6994 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006995 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006996 os_free(ifname);
6997 }
6998#endif /* CONFIG_MESH */
6999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007000 return 0;
7001}
7002
7003
7004/**
7005 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7006 * @wpa_s: Pointer to the network interface
7007 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7008 */
7009const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7010{
7011 const char *eapol_method;
7012
7013 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7014 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7015 return "NO-EAP";
7016 }
7017
7018 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7019 if (eapol_method == NULL)
7020 return "UNKNOWN-EAP";
7021
7022 return eapol_method;
7023}
7024
7025
7026/**
7027 * wpa_supplicant_get_iface - Get a new network interface
7028 * @global: Pointer to global data from wpa_supplicant_init()
7029 * @ifname: Interface name
7030 * Returns: Pointer to the interface or %NULL if not found
7031 */
7032struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7033 const char *ifname)
7034{
7035 struct wpa_supplicant *wpa_s;
7036
7037 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7038 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7039 return wpa_s;
7040 }
7041 return NULL;
7042}
7043
7044
7045#ifndef CONFIG_NO_WPA_MSG
7046static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7047{
7048 struct wpa_supplicant *wpa_s = ctx;
7049 if (wpa_s == NULL)
7050 return NULL;
7051 return wpa_s->ifname;
7052}
7053#endif /* CONFIG_NO_WPA_MSG */
7054
7055
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007056#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7057#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7058#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7059
7060/* Periodic cleanup tasks */
7061static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7062{
7063 struct wpa_global *global = eloop_ctx;
7064 struct wpa_supplicant *wpa_s;
7065
7066 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7067 wpas_periodic, global, NULL);
7068
7069#ifdef CONFIG_P2P
7070 if (global->p2p)
7071 p2p_expire_peers(global->p2p);
7072#endif /* CONFIG_P2P */
7073
7074 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7075 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7076#ifdef CONFIG_AP
7077 ap_periodic(wpa_s);
7078#endif /* CONFIG_AP */
7079 }
7080}
7081
7082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007083/**
7084 * wpa_supplicant_init - Initialize %wpa_supplicant
7085 * @params: Parameters for %wpa_supplicant
7086 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7087 *
7088 * This function is used to initialize %wpa_supplicant. After successful
7089 * initialization, the returned data pointer can be used to add and remove
7090 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7091 */
7092struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7093{
7094 struct wpa_global *global;
7095 int ret, i;
7096
7097 if (params == NULL)
7098 return NULL;
7099
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007100#ifdef CONFIG_DRIVER_NDIS
7101 {
7102 void driver_ndis_init_ops(void);
7103 driver_ndis_init_ops();
7104 }
7105#endif /* CONFIG_DRIVER_NDIS */
7106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007107#ifndef CONFIG_NO_WPA_MSG
7108 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7109#endif /* CONFIG_NO_WPA_MSG */
7110
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007111 if (params->wpa_debug_file_path)
7112 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007113 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007114 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007115 if (params->wpa_debug_syslog)
7116 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007117 if (params->wpa_debug_tracing) {
7118 ret = wpa_debug_open_linux_tracing();
7119 if (ret) {
7120 wpa_printf(MSG_ERROR,
7121 "Failed to enable trace logging");
7122 return NULL;
7123 }
7124 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007125
7126 ret = eap_register_methods();
7127 if (ret) {
7128 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7129 if (ret == -2)
7130 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7131 "the same EAP type.");
7132 return NULL;
7133 }
7134
7135 global = os_zalloc(sizeof(*global));
7136 if (global == NULL)
7137 return NULL;
7138 dl_list_init(&global->p2p_srv_bonjour);
7139 dl_list_init(&global->p2p_srv_upnp);
7140 global->params.daemonize = params->daemonize;
7141 global->params.wait_for_monitor = params->wait_for_monitor;
7142 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7143 if (params->pid_file)
7144 global->params.pid_file = os_strdup(params->pid_file);
7145 if (params->ctrl_interface)
7146 global->params.ctrl_interface =
7147 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007148 if (params->ctrl_interface_group)
7149 global->params.ctrl_interface_group =
7150 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007151 if (params->override_driver)
7152 global->params.override_driver =
7153 os_strdup(params->override_driver);
7154 if (params->override_ctrl_interface)
7155 global->params.override_ctrl_interface =
7156 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007157#ifdef CONFIG_MATCH_IFACE
7158 global->params.match_iface_count = params->match_iface_count;
7159 if (params->match_iface_count) {
7160 global->params.match_ifaces =
7161 os_calloc(params->match_iface_count,
7162 sizeof(struct wpa_interface));
7163 os_memcpy(global->params.match_ifaces,
7164 params->match_ifaces,
7165 params->match_iface_count *
7166 sizeof(struct wpa_interface));
7167 }
7168#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007169#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007170 if (params->conf_p2p_dev)
7171 global->params.conf_p2p_dev =
7172 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007173#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007174 wpa_debug_level = global->params.wpa_debug_level =
7175 params->wpa_debug_level;
7176 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7177 params->wpa_debug_show_keys;
7178 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7179 params->wpa_debug_timestamp;
7180
Hai Shalomfdcde762020-04-02 11:19:20 -07007181 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007182
7183 if (eloop_init()) {
7184 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7185 wpa_supplicant_deinit(global);
7186 return NULL;
7187 }
7188
Jouni Malinen75ecf522011-06-27 15:19:46 -07007189 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007190
7191 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7192 if (global->ctrl_iface == NULL) {
7193 wpa_supplicant_deinit(global);
7194 return NULL;
7195 }
7196
7197 if (wpas_notify_supplicant_initialized(global)) {
7198 wpa_supplicant_deinit(global);
7199 return NULL;
7200 }
7201
7202 for (i = 0; wpa_drivers[i]; i++)
7203 global->drv_count++;
7204 if (global->drv_count == 0) {
7205 wpa_printf(MSG_ERROR, "No drivers enabled");
7206 wpa_supplicant_deinit(global);
7207 return NULL;
7208 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007209 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210 if (global->drv_priv == NULL) {
7211 wpa_supplicant_deinit(global);
7212 return NULL;
7213 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007214
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007215#ifdef CONFIG_WIFI_DISPLAY
7216 if (wifi_display_init(global) < 0) {
7217 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7218 wpa_supplicant_deinit(global);
7219 return NULL;
7220 }
7221#endif /* CONFIG_WIFI_DISPLAY */
7222
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007223 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7224 wpas_periodic, global, NULL);
7225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007226 return global;
7227}
7228
7229
7230/**
7231 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7232 * @global: Pointer to global data from wpa_supplicant_init()
7233 * Returns: 0 after successful event loop run, -1 on failure
7234 *
7235 * This function starts the main event loop and continues running as long as
7236 * there are any remaining events. In most cases, this function is running as
7237 * long as the %wpa_supplicant process in still in use.
7238 */
7239int wpa_supplicant_run(struct wpa_global *global)
7240{
7241 struct wpa_supplicant *wpa_s;
7242
7243 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007244 (wpa_supplicant_daemon(global->params.pid_file) ||
7245 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007246 return -1;
7247
Dmitry Shmidte4663042016-04-04 10:07:49 -07007248#ifdef CONFIG_MATCH_IFACE
7249 if (wpa_supplicant_match_existing(global))
7250 return -1;
7251#endif
7252
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007253 if (global->params.wait_for_monitor) {
7254 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007255 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007256 wpa_supplicant_ctrl_iface_wait(
7257 wpa_s->ctrl_iface);
7258 }
7259
7260 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7261 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7262
7263 eloop_run();
7264
7265 return 0;
7266}
7267
7268
7269/**
7270 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7271 * @global: Pointer to global data from wpa_supplicant_init()
7272 *
7273 * This function is called to deinitialize %wpa_supplicant and to free all
7274 * allocated resources. Remaining network interfaces will also be removed.
7275 */
7276void wpa_supplicant_deinit(struct wpa_global *global)
7277{
7278 int i;
7279
7280 if (global == NULL)
7281 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007282
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007283 eloop_cancel_timeout(wpas_periodic, global, NULL);
7284
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007285#ifdef CONFIG_WIFI_DISPLAY
7286 wifi_display_deinit(global);
7287#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007288
7289 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007290 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007291
7292 if (global->ctrl_iface)
7293 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7294
7295 wpas_notify_supplicant_deinitialized(global);
7296
7297 eap_peer_unregister_methods();
7298#ifdef CONFIG_AP
7299 eap_server_unregister_methods();
7300#endif /* CONFIG_AP */
7301
7302 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7303 if (!global->drv_priv[i])
7304 continue;
7305 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7306 }
7307 os_free(global->drv_priv);
7308
7309 random_deinit();
7310
7311 eloop_destroy();
7312
7313 if (global->params.pid_file) {
7314 os_daemonize_terminate(global->params.pid_file);
7315 os_free(global->params.pid_file);
7316 }
7317 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007318 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007319 os_free(global->params.override_driver);
7320 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007321#ifdef CONFIG_MATCH_IFACE
7322 os_free(global->params.match_ifaces);
7323#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007324#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007325 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007326#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007327
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007328 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007329 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007330 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007332 os_free(global);
7333 wpa_debug_close_syslog();
7334 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007335 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007336}
7337
7338
7339void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7340{
7341 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7342 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7343 char country[3];
7344 country[0] = wpa_s->conf->country[0];
7345 country[1] = wpa_s->conf->country[1];
7346 country[2] = '\0';
7347 if (wpa_drv_set_country(wpa_s, country) < 0) {
7348 wpa_printf(MSG_ERROR, "Failed to set country code "
7349 "'%s'", country);
7350 }
7351 }
7352
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007353 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7354 wpas_init_ext_pw(wpa_s);
7355
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007356 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7357 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7358
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007359 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7360 struct wpa_driver_capa capa;
7361 int res = wpa_drv_get_capa(wpa_s, &capa);
7362
7363 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7364 wpa_printf(MSG_ERROR,
7365 "Failed to update wowlan_triggers to '%s'",
7366 wpa_s->conf->wowlan_triggers);
7367 }
7368
Hai Shalom81f62d82019-07-22 12:10:00 -07007369 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7370 wpa_supplicant_set_default_scan_ies(wpa_s);
7371
Hai Shalom899fcc72020-10-19 14:38:18 -07007372#ifdef CONFIG_BGSCAN
7373 /*
7374 * We default to global bgscan parameters only when per-network bgscan
7375 * parameters aren't set. Only bother resetting bgscan parameters if
7376 * this is the case.
7377 */
7378 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7379 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7380 wpa_s->wpa_state == WPA_COMPLETED)
7381 wpa_supplicant_reset_bgscan(wpa_s);
7382#endif /* CONFIG_BGSCAN */
7383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007384#ifdef CONFIG_WPS
7385 wpas_wps_update_config(wpa_s);
7386#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007387 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007388 wpa_s->conf->changed_parameters = 0;
7389}
7390
7391
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007392void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007393{
7394 int i;
7395
7396 for (i = 0; i < *num_freqs; i++) {
7397 if (freqs[i] == freq)
7398 return;
7399 }
7400
7401 freqs[*num_freqs] = freq;
7402 (*num_freqs)++;
7403}
7404
7405
7406static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7407{
7408 struct wpa_bss *bss, *cbss;
7409 const int max_freqs = 10;
7410 int *freqs;
7411 int num_freqs = 0;
7412
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007413 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007414 if (freqs == NULL)
7415 return NULL;
7416
7417 cbss = wpa_s->current_bss;
7418
7419 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7420 if (bss == cbss)
7421 continue;
7422 if (bss->ssid_len == cbss->ssid_len &&
7423 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007424 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007425 add_freq(freqs, &num_freqs, bss->freq);
7426 if (num_freqs == max_freqs)
7427 break;
7428 }
7429 }
7430
7431 if (num_freqs == 0) {
7432 os_free(freqs);
7433 freqs = NULL;
7434 }
7435
7436 return freqs;
7437}
7438
7439
7440void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7441{
7442 int timeout;
7443 int count;
7444 int *freqs = NULL;
7445
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007446 wpas_connect_work_done(wpa_s);
7447
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007448 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007449 * Remove possible authentication timeout since the connection failed.
7450 */
7451 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7452
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007453 /*
Hai Shalom60840252021-02-19 19:02:11 -08007454 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007455 * generated based on local request to disconnect.
7456 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007457 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007458 wpa_s->own_disconnect_req = 0;
7459 wpa_dbg(wpa_s, MSG_DEBUG,
7460 "Ignore connection failure due to local request to disconnect");
7461 return;
7462 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007463 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007464 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7465 "indication since interface has been put into "
7466 "disconnected state");
7467 return;
7468 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007469 if (wpa_s->auto_reconnect_disabled) {
7470 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7471 "indication since auto connect is disabled");
7472 return;
7473 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007474
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007475 /*
Hai Shalom60840252021-02-19 19:02:11 -08007476 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007477 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007478 */
Hai Shalom60840252021-02-19 19:02:11 -08007479 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007480 if (count == 1 && wpa_s->current_bss) {
7481 /*
Hai Shalom60840252021-02-19 19:02:11 -08007482 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483 * another BSS available for the same ESS, we should try that
7484 * next. Otherwise, we may as well try this one once more
7485 * before allowing other, likely worse, ESSes to be considered.
7486 */
7487 freqs = get_bss_freqs_in_ess(wpa_s);
7488 if (freqs) {
7489 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7490 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007491 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007492 /*
7493 * On the next scan, go through only the known channels
7494 * used in this ESS based on previous scans to speed up
7495 * common load balancing use case.
7496 */
7497 os_free(wpa_s->next_scan_freqs);
7498 wpa_s->next_scan_freqs = freqs;
7499 }
7500 }
7501
Hai Shalom899fcc72020-10-19 14:38:18 -07007502 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007503
Hai Shalom899fcc72020-10-19 14:38:18 -07007504 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007505 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7506 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007507 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007508 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007509 /*
7510 * Multiple consecutive connection failures mean that other APs are
7511 * either not available or have already been tried, so we can start
7512 * increasing the delay here to avoid constant scanning.
7513 */
7514 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007515 case 1:
7516 timeout = 100;
7517 break;
7518 case 2:
7519 timeout = 500;
7520 break;
7521 case 3:
7522 timeout = 1000;
7523 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007524 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007525 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007526 break;
7527 default:
7528 timeout = 10000;
7529 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007530 }
7531
Hai Shalom899fcc72020-10-19 14:38:18 -07007532 wpa_dbg(wpa_s, MSG_DEBUG,
7533 "Consecutive connection failures: %d --> request scan in %d ms",
7534 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007536 /*
7537 * TODO: if more than one possible AP is available in scan results,
7538 * could try the other ones before requesting a new scan.
7539 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007540
7541 /* speed up the connection attempt with normal scan */
7542 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007543 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7544 1000 * (timeout % 1000));
7545}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007546
7547
Hai Shalomce48b4a2018-09-05 11:41:35 -07007548#ifdef CONFIG_FILS
7549void fils_connection_failure(struct wpa_supplicant *wpa_s)
7550{
7551 struct wpa_ssid *ssid = wpa_s->current_ssid;
7552 const u8 *realm, *username, *rrk;
7553 size_t realm_len, username_len, rrk_len;
7554 u16 next_seq_num;
7555
7556 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7557 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7558 &username, &username_len,
7559 &realm, &realm_len, &next_seq_num,
7560 &rrk, &rrk_len) != 0 ||
7561 !realm)
7562 return;
7563
7564 wpa_hexdump_ascii(MSG_DEBUG,
7565 "FILS: Store last connection failure realm",
7566 realm, realm_len);
7567 os_free(wpa_s->last_con_fail_realm);
7568 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7569 if (wpa_s->last_con_fail_realm) {
7570 wpa_s->last_con_fail_realm_len = realm_len;
7571 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7572 }
7573}
7574#endif /* CONFIG_FILS */
7575
7576
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007577int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7578{
7579 return wpa_s->conf->ap_scan == 2 ||
7580 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7581}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007582
Dmitry Shmidt04949592012-07-19 12:16:46 -07007583
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007584#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007585int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7586 struct wpa_ssid *ssid,
7587 const char *field,
7588 const char *value)
7589{
7590#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007591 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007592
7593 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7594 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7595 (const u8 *) value, os_strlen(value));
7596
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007597 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007598 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007599#else /* IEEE8021X_EAPOL */
7600 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7601 return -1;
7602#endif /* IEEE8021X_EAPOL */
7603}
7604
7605int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7606 struct wpa_ssid *ssid,
7607 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007608 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007609{
7610#ifdef IEEE8021X_EAPOL
7611 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007612 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007613
7614 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007615 case WPA_CTRL_REQ_EAP_IDENTITY:
7616 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007617 os_free(eap->imsi_identity);
7618 if (value == NULL)
7619 return -1;
7620 identity = os_strchr(value, ':');
7621 if (identity == NULL) {
7622 /* plain identity */
7623 eap->identity = (u8 *)os_strdup(value);
7624 eap->identity_len = os_strlen(value);
7625 } else {
7626 /* have both plain identity and encrypted identity */
7627 imsi_identity = value;
7628 *identity++ = '\0';
7629 /* plain identity */
7630 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7631 eap->imsi_identity_len = strlen(imsi_identity);
7632 /* encrypted identity */
7633 eap->identity = (u8 *)dup_binstr(identity,
7634 value_len - strlen(imsi_identity) - 1);
7635 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7636 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007637 eap->pending_req_identity = 0;
7638 if (ssid == wpa_s->current_ssid)
7639 wpa_s->reassociate = 1;
7640 break;
7641 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007642 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007643 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007644 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007645 eap->pending_req_password = 0;
7646 if (ssid == wpa_s->current_ssid)
7647 wpa_s->reassociate = 1;
7648 break;
7649 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007650 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007651 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007652 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007653 eap->pending_req_new_password = 0;
7654 if (ssid == wpa_s->current_ssid)
7655 wpa_s->reassociate = 1;
7656 break;
7657 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007658 str_clear_free(eap->cert.pin);
7659 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007660 eap->pending_req_pin = 0;
7661 if (ssid == wpa_s->current_ssid)
7662 wpa_s->reassociate = 1;
7663 break;
7664 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007665 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007666 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007667 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007668 os_free(eap->pending_req_otp);
7669 eap->pending_req_otp = NULL;
7670 eap->pending_req_otp_len = 0;
7671 break;
7672 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007673 str_clear_free(eap->cert.private_key_passwd);
7674 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007675 eap->pending_req_passphrase = 0;
7676 if (ssid == wpa_s->current_ssid)
7677 wpa_s->reassociate = 1;
7678 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007679 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007680 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007681 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007682 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007683 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007684 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7685 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7686 return -1;
7687 ssid->mem_only_psk = 1;
7688 if (ssid->passphrase)
7689 wpa_config_update_psk(ssid);
7690 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7691 wpa_supplicant_req_scan(wpa_s, 0, 0);
7692 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007693 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7694 if (eap->pending_ext_cert_check != PENDING_CHECK)
7695 return -1;
7696 if (os_strcmp(value, "good") == 0)
7697 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7698 else if (os_strcmp(value, "bad") == 0)
7699 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7700 else
7701 return -1;
7702 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007703 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007704 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007705 return -1;
7706 }
7707
7708 return 0;
7709#else /* IEEE8021X_EAPOL */
7710 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7711 return -1;
7712#endif /* IEEE8021X_EAPOL */
7713}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007714#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007715
7716
7717int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7718{
Hai Shalomfdcde762020-04-02 11:19:20 -07007719#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007720 int i;
7721 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007722#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007723
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007724 if (wpa_s->p2p_mgmt)
7725 return 1; /* no normal network profiles on p2p_mgmt interface */
7726
Dmitry Shmidt04949592012-07-19 12:16:46 -07007727 if (ssid == NULL)
7728 return 1;
7729
7730 if (ssid->disabled)
7731 return 1;
7732
Hai Shalomfdcde762020-04-02 11:19:20 -07007733#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007734 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007735 drv_enc = wpa_s->drv_enc;
7736 else
7737 drv_enc = (unsigned int) -1;
7738
7739 for (i = 0; i < NUM_WEP_KEYS; i++) {
7740 size_t len = ssid->wep_key_len[i];
7741 if (len == 0)
7742 continue;
7743 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7744 continue;
7745 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7746 continue;
7747 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7748 continue;
7749 return 1; /* invalid WEP key */
7750 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007751#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007752
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007753 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007754 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007755 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007756 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007757 return 1;
7758
Dmitry Shmidt04949592012-07-19 12:16:46 -07007759 return 0;
7760}
7761
7762
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007763int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7764{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007765 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7766 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7767 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7768 /*
7769 * Driver does not support BIP -- ignore pmf=1 default
7770 * since the connection with PMF would fail and the
7771 * configuration does not require PMF to be enabled.
7772 */
7773 return NO_MGMT_FRAME_PROTECTION;
7774 }
7775
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007776 if (ssid &&
7777 (ssid->key_mgmt &
7778 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7779 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7780 /*
7781 * Do not use the default PMF value for non-RSN networks
7782 * since PMF is available only with RSN and pmf=2
7783 * configuration would otherwise prevent connections to
7784 * all open networks.
7785 */
7786 return NO_MGMT_FRAME_PROTECTION;
7787 }
7788
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007789 return wpa_s->conf->pmf;
7790 }
7791
7792 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007793}
7794
7795
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007796int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007797{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007798 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007799 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007800 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007801 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007802 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007803}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007804
7805
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007806void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007807{
7808 struct wpa_ssid *ssid = wpa_s->current_ssid;
7809 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007810 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007811
7812 if (ssid == NULL) {
7813 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7814 "SSID block");
7815 return;
7816 }
7817
7818 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7819 return;
7820
7821 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007822
7823#ifdef CONFIG_P2P
7824 if (ssid->p2p_group &&
7825 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7826 /*
7827 * Skip the wait time since there is a short timeout on the
7828 * connection to a P2P group.
7829 */
7830 return;
7831 }
7832#endif /* CONFIG_P2P */
7833
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007834 if (ssid->auth_failures > 50)
7835 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007836 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007837 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007838 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007839 dur = 90;
7840 else if (ssid->auth_failures > 3)
7841 dur = 60;
7842 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007843 dur = 30;
7844 else if (ssid->auth_failures > 1)
7845 dur = 20;
7846 else
7847 dur = 10;
7848
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007849 if (ssid->auth_failures > 1 &&
7850 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7851 dur += os_random() % (ssid->auth_failures * 10);
7852
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007853 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007854 if (now.sec + dur <= ssid->disabled_until.sec)
7855 return;
7856
7857 ssid->disabled_until.sec = now.sec + dur;
7858
7859 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007860 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007861 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007862 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007863}
7864
7865
7866void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7867 struct wpa_ssid *ssid, int clear_failures)
7868{
7869 if (ssid == NULL)
7870 return;
7871
7872 if (ssid->disabled_until.sec) {
7873 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7874 "id=%d ssid=\"%s\"",
7875 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7876 }
7877 ssid->disabled_until.sec = 0;
7878 ssid->disabled_until.usec = 0;
7879 if (clear_failures)
7880 ssid->auth_failures = 0;
7881}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007882
7883
7884int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7885{
7886 size_t i;
7887
7888 if (wpa_s->disallow_aps_bssid == NULL)
7889 return 0;
7890
7891 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7892 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7893 bssid, ETH_ALEN) == 0)
7894 return 1;
7895 }
7896
7897 return 0;
7898}
7899
7900
7901int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7902 size_t ssid_len)
7903{
7904 size_t i;
7905
7906 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7907 return 0;
7908
7909 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7910 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7911 if (ssid_len == s->ssid_len &&
7912 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7913 return 1;
7914 }
7915
7916 return 0;
7917}
7918
7919
7920/**
7921 * wpas_request_connection - Request a new connection
7922 * @wpa_s: Pointer to the network interface
7923 *
7924 * This function is used to request a new connection to be found. It will mark
7925 * the interface to allow reassociation and request a new scan to find a
7926 * suitable network to connect to.
7927 */
7928void wpas_request_connection(struct wpa_supplicant *wpa_s)
7929{
7930 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007931 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007932 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007933 wpa_s->disconnected = 0;
7934 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007935 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007936
7937 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7938 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007939 else
7940 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007941}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007942
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007943
Roshan Pius02242d72016-08-09 15:31:48 -07007944/**
7945 * wpas_request_disconnection - Request disconnection
7946 * @wpa_s: Pointer to the network interface
7947 *
7948 * This function is used to request disconnection from the currently connected
7949 * network. This will stop any ongoing scans and initiate deauthentication.
7950 */
7951void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7952{
7953#ifdef CONFIG_SME
7954 wpa_s->sme.prev_bssid_set = 0;
7955#endif /* CONFIG_SME */
7956 wpa_s->reassociate = 0;
7957 wpa_s->disconnected = 1;
7958 wpa_supplicant_cancel_sched_scan(wpa_s);
7959 wpa_supplicant_cancel_scan(wpa_s);
7960 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7961 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007962 radio_remove_works(wpa_s, "connect", 0);
7963 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007964}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007965
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007966
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007967void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7968 struct wpa_used_freq_data *freqs_data,
7969 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007970{
7971 unsigned int i;
7972
7973 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7974 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007975 for (i = 0; i < len; i++) {
7976 struct wpa_used_freq_data *cur = &freqs_data[i];
7977 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7978 i, cur->freq, cur->flags);
7979 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007980}
7981
7982
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007983/*
7984 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007985 * are using the same radio as the current interface, and in addition, get
7986 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007987 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007988int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7989 struct wpa_used_freq_data *freqs_data,
7990 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007991{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007992 struct wpa_supplicant *ifs;
7993 u8 bssid[ETH_ALEN];
7994 int freq;
7995 unsigned int idx = 0, i;
7996
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007997 wpa_dbg(wpa_s, MSG_DEBUG,
7998 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007999 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008000
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008001 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8002 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008003 if (idx == len)
8004 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008005
8006 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8007 continue;
8008
8009 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008010 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8011 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008012 freq = ifs->current_ssid->frequency;
8013 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8014 freq = ifs->assoc_freq;
8015 else
8016 continue;
8017
8018 /* Hold only distinct freqs */
8019 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008020 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008021 break;
8022
8023 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008024 freqs_data[idx++].freq = freq;
8025
8026 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008027 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008028 WPA_FREQ_USED_BY_P2P_CLIENT :
8029 WPA_FREQ_USED_BY_INFRA_STATION;
8030 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008031 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008032
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008033 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008034 return idx;
8035}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008036
8037
8038/*
8039 * Find the operating frequencies of any of the virtual interfaces that
8040 * are using the same radio as the current interface.
8041 */
8042int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8043 int *freq_array, unsigned int len)
8044{
8045 struct wpa_used_freq_data *freqs_data;
8046 int num, i;
8047
8048 os_memset(freq_array, 0, sizeof(int) * len);
8049
8050 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8051 if (!freqs_data)
8052 return -1;
8053
8054 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8055 for (i = 0; i < num; i++)
8056 freq_array[i] = freqs_data[i].freq;
8057
8058 os_free(freqs_data);
8059
8060 return num;
8061}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008062
8063
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008064struct wpa_supplicant *
8065wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8066{
8067 switch (frame) {
8068#ifdef CONFIG_P2P
8069 case VENDOR_ELEM_PROBE_REQ_P2P:
8070 case VENDOR_ELEM_PROBE_RESP_P2P:
8071 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8072 case VENDOR_ELEM_BEACON_P2P_GO:
8073 case VENDOR_ELEM_P2P_PD_REQ:
8074 case VENDOR_ELEM_P2P_PD_RESP:
8075 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8076 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8077 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8078 case VENDOR_ELEM_P2P_INV_REQ:
8079 case VENDOR_ELEM_P2P_INV_RESP:
8080 case VENDOR_ELEM_P2P_ASSOC_REQ:
8081 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008082 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008083#endif /* CONFIG_P2P */
8084 default:
8085 return wpa_s;
8086 }
8087}
8088
8089
8090void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8091{
8092 unsigned int i;
8093 char buf[30];
8094
8095 wpa_printf(MSG_DEBUG, "Update vendor elements");
8096
8097 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8098 if (wpa_s->vendor_elem[i]) {
8099 int res;
8100
8101 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8102 if (!os_snprintf_error(sizeof(buf), res)) {
8103 wpa_hexdump_buf(MSG_DEBUG, buf,
8104 wpa_s->vendor_elem[i]);
8105 }
8106 }
8107 }
8108
8109#ifdef CONFIG_P2P
8110 if (wpa_s->parent == wpa_s &&
8111 wpa_s->global->p2p &&
8112 !wpa_s->global->p2p_disabled)
8113 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8114#endif /* CONFIG_P2P */
8115}
8116
8117
8118int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8119 const u8 *elem, size_t len)
8120{
8121 u8 *ie, *end;
8122
8123 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8124 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8125
8126 for (; ie + 1 < end; ie += 2 + ie[1]) {
8127 if (ie + len > end)
8128 break;
8129 if (os_memcmp(ie, elem, len) != 0)
8130 continue;
8131
8132 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8133 wpabuf_free(wpa_s->vendor_elem[frame]);
8134 wpa_s->vendor_elem[frame] = NULL;
8135 } else {
8136 os_memmove(ie, ie + len, end - (ie + len));
8137 wpa_s->vendor_elem[frame]->used -= len;
8138 }
8139 wpas_vendor_elem_update(wpa_s);
8140 return 0;
8141 }
8142
8143 return -1;
8144}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008145
8146
8147struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008148 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008149 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008150{
8151 u16 i;
8152
8153 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008154 if (modes[i].mode != mode ||
8155 !modes[i].num_channels || !modes[i].channels)
8156 continue;
8157 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8158 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008159 return &modes[i];
8160 }
8161
8162 return NULL;
8163}
8164
8165
8166static struct
8167wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8168 const u8 *bssid)
8169{
8170 struct wpa_bss_tmp_disallowed *bss;
8171
8172 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8173 struct wpa_bss_tmp_disallowed, list) {
8174 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8175 return bss;
8176 }
8177
8178 return NULL;
8179}
8180
8181
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008182static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8183{
8184 struct wpa_bss_tmp_disallowed *tmp;
8185 unsigned int num_bssid = 0;
8186 u8 *bssids;
8187 int ret;
8188
8189 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8190 if (!bssids)
8191 return -1;
8192 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8193 struct wpa_bss_tmp_disallowed, list) {
8194 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8195 ETH_ALEN);
8196 num_bssid++;
8197 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008198 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008199 os_free(bssids);
8200 return ret;
8201}
8202
8203
8204static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8205{
8206 struct wpa_supplicant *wpa_s = eloop_ctx;
8207 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8208
8209 /* Make sure the bss is not already freed */
8210 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8211 struct wpa_bss_tmp_disallowed, list) {
8212 if (bss == tmp) {
8213 dl_list_del(&tmp->list);
8214 os_free(tmp);
8215 wpa_set_driver_tmp_disallow_list(wpa_s);
8216 break;
8217 }
8218 }
8219}
8220
8221
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008222void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008223 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008224{
8225 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008226
8227 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8228 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008229 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008230 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008231 }
8232
8233 bss = os_malloc(sizeof(*bss));
8234 if (!bss) {
8235 wpa_printf(MSG_DEBUG,
8236 "Failed to allocate memory for temp disallow BSS");
8237 return;
8238 }
8239
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008240 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8241 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008242 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008243
8244finish:
8245 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008246 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8247 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008248}
8249
8250
Hai Shalom74f70d42019-02-11 14:42:39 -08008251int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8252 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008253{
Hai Shalom74f70d42019-02-11 14:42:39 -08008254 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008255
8256 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8257 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008258 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8259 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008260 break;
8261 }
8262 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008263 if (!disallowed)
8264 return 0;
8265
8266 if (disallowed->rssi_threshold != 0 &&
8267 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008268 return 0;
8269
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008270 return 1;
8271}
Hai Shalom81f62d82019-07-22 12:10:00 -07008272
8273
8274int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8275 unsigned int type, const u8 *addr,
8276 const u8 *mask)
8277{
8278 if ((addr && !mask) || (!addr && mask)) {
8279 wpa_printf(MSG_INFO,
8280 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8281 return -1;
8282 }
8283
8284 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8285 wpa_printf(MSG_INFO,
8286 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8287 return -1;
8288 }
8289
8290 if (type & MAC_ADDR_RAND_SCAN) {
8291 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8292 addr, mask))
8293 return -1;
8294 }
8295
8296 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8297 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8298 addr, mask))
8299 return -1;
8300
8301 if (wpa_s->sched_scanning && !wpa_s->pno)
8302 wpas_scan_restart_sched_scan(wpa_s);
8303 }
8304
8305 if (type & MAC_ADDR_RAND_PNO) {
8306 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8307 addr, mask))
8308 return -1;
8309
8310 if (wpa_s->pno) {
8311 wpas_stop_pno(wpa_s);
8312 wpas_start_pno(wpa_s);
8313 }
8314 }
8315
8316 return 0;
8317}
8318
8319
8320int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8321 unsigned int type)
8322{
8323 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8324 if (wpa_s->pno) {
8325 if (type & MAC_ADDR_RAND_PNO) {
8326 wpas_stop_pno(wpa_s);
8327 wpas_start_pno(wpa_s);
8328 }
8329 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8330 wpas_scan_restart_sched_scan(wpa_s);
8331 }
8332
8333 return 0;
8334}
Hai Shalomfdcde762020-04-02 11:19:20 -07008335
8336
8337int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8338 struct wpa_signal_info *si)
8339{
8340 int res;
8341
8342 if (!wpa_s->driver->signal_poll)
8343 return -1;
8344
8345 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8346
8347#ifdef CONFIG_TESTING_OPTIONS
8348 if (res == 0) {
8349 struct driver_signal_override *dso;
8350
8351 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8352 struct driver_signal_override, list) {
8353 if (os_memcmp(wpa_s->bssid, dso->bssid,
8354 ETH_ALEN) != 0)
8355 continue;
8356 wpa_printf(MSG_DEBUG,
8357 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8358 si->current_signal,
8359 dso->si_current_signal,
8360 si->avg_signal,
8361 dso->si_avg_signal,
8362 si->avg_beacon_signal,
8363 dso->si_avg_beacon_signal,
8364 si->current_noise,
8365 dso->si_current_noise);
8366 si->current_signal = dso->si_current_signal;
8367 si->avg_signal = dso->si_avg_signal;
8368 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8369 si->current_noise = dso->si_current_noise;
8370 break;
8371 }
8372 }
8373#endif /* CONFIG_TESTING_OPTIONS */
8374
8375 return res;
8376}
8377
8378
8379struct wpa_scan_results *
8380wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8381{
8382 struct wpa_scan_results *scan_res;
8383#ifdef CONFIG_TESTING_OPTIONS
8384 size_t idx;
8385#endif /* CONFIG_TESTING_OPTIONS */
8386
8387 if (!wpa_s->driver->get_scan_results2)
8388 return NULL;
8389
8390 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8391
8392#ifdef CONFIG_TESTING_OPTIONS
8393 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8394 struct driver_signal_override *dso;
8395 struct wpa_scan_res *res = scan_res->res[idx];
8396
8397 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8398 struct driver_signal_override, list) {
8399 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8400 continue;
8401 wpa_printf(MSG_DEBUG,
8402 "Override driver scan signal level %d->%d for "
8403 MACSTR,
8404 res->level, dso->scan_level,
8405 MAC2STR(res->bssid));
8406 res->flags |= WPA_SCAN_QUAL_INVALID;
8407 if (dso->scan_level < 0)
8408 res->flags |= WPA_SCAN_LEVEL_DBM;
8409 else
8410 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8411 res->level = dso->scan_level;
8412 break;
8413 }
8414 }
8415#endif /* CONFIG_TESTING_OPTIONS */
8416
8417 return scan_res;
8418}