blob: 685f8975f48f77612ac9548084ae3c07efcbc0fc [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalomc1a21442022-02-04 13:43:00 -08003 * Copyright (c) 2003-2022, 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"
Sunil8cd6f4d2022-06-28 18:40:46 +000020#include "crypto/crypto.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070023#include "eapol_supp/eapol_supp_sm.h"
24#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070025#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "eap_server/eap_methods.h"
27#include "rsn_supp/wpa.h"
28#include "eloop.h"
29#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070030#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031#include "l2_packet/l2_packet.h"
32#include "wpa_supplicant_i.h"
33#include "driver_i.h"
34#include "ctrl_iface.h"
35#include "pcsc_funcs.h"
36#include "common/version.h"
37#include "rsn_supp/preauth.h"
38#include "rsn_supp/pmksa_cache.h"
39#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070040#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080042#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070044#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080045#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080048#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "wpas_glue.h"
50#include "wps_supplicant.h"
51#include "ibss_rsn.h"
52#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054#include "ap.h"
55#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070056#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057#include "notify.h"
58#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060#include "bss.h"
61#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080062#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070063#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070064#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070065#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080066#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070067#include "dpp_supplicant.h"
68#ifdef CONFIG_MESH
69#include "ap/ap_config.h"
70#include "ap/hostapd.h"
71#endif /* CONFIG_MESH */
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -070072#include "aidl/aidl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070074const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080076"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"This software may be distributed under the terms of the BSD license.\n"
80"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070081#ifdef EAP_TLS_OPENSSL
82"\nThis product includes software developed by the OpenSSL Project\n"
83"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
84#endif /* EAP_TLS_OPENSSL */
85;
86
87#ifndef CONFIG_NO_STDOUT_DEBUG
88/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070091const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080092"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070093"\n"
94"Redistribution and use in source and binary forms, with or without\n"
95"modification, are permitted provided that the following conditions are\n"
96"met:\n"
97"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070098const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099"1. Redistributions of source code must retain the above copyright\n"
100" notice, this list of conditions and the following disclaimer.\n"
101"\n"
102"2. Redistributions in binary form must reproduce the above copyright\n"
103" notice, this list of conditions and the following disclaimer in the\n"
104" documentation and/or other materials provided with the distribution.\n"
105"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700106const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
108" names of its contributors may be used to endorse or promote products\n"
109" derived from this software without specific prior written permission.\n"
110"\n"
111"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
112"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
113"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
114"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700115const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700116"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
117"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
118"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
119"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
120"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
121"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
122"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
123"\n";
124#endif /* CONFIG_NO_STDOUT_DEBUG */
125
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700126
127static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
128#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
129static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
130#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700131#ifdef CONFIG_OWE
132static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
133#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700134
135
Hai Shalomfdcde762020-04-02 11:19:20 -0700136#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700137/* Configure default/group WEP keys for static WEP */
138int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
139{
140 int i, set = 0;
141
142 for (i = 0; i < NUM_WEP_KEYS; i++) {
143 if (ssid->wep_key_len[i] == 0)
144 continue;
145
146 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000147 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700148 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700149 ssid->wep_key[i], ssid->wep_key_len[i],
150 i == ssid->wep_tx_keyidx ?
151 KEY_FLAG_GROUP_RX_TX_DEFAULT :
152 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700153 }
154
155 return set;
156}
Hai Shalomfdcde762020-04-02 11:19:20 -0700157#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158
159
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700160int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
161 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700162{
163 u8 key[32];
164 size_t keylen;
165 enum wpa_alg alg;
166 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800167 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700168
169 /* IBSS/WPA-None uses only one key (Group) for both receiving and
170 * sending unicast and multicast packets. */
171
172 if (ssid->mode != WPAS_MODE_IBSS) {
173 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
174 "IBSS/ad-hoc) for WPA-None", ssid->mode);
175 return -1;
176 }
177
178 if (!ssid->psk_set) {
179 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
180 "WPA-None");
181 return -1;
182 }
183
184 switch (wpa_s->group_cipher) {
185 case WPA_CIPHER_CCMP:
186 os_memcpy(key, ssid->psk, 16);
187 keylen = 16;
188 alg = WPA_ALG_CCMP;
189 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700190 case WPA_CIPHER_GCMP:
191 os_memcpy(key, ssid->psk, 16);
192 keylen = 16;
193 alg = WPA_ALG_GCMP;
194 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700195 case WPA_CIPHER_TKIP:
196 /* WPA-None uses the same Michael MIC key for both TX and RX */
197 os_memcpy(key, ssid->psk, 16 + 8);
198 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
199 keylen = 32;
200 alg = WPA_ALG_TKIP;
201 break;
202 default:
203 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
204 "WPA-None", wpa_s->group_cipher);
205 return -1;
206 }
207
208 /* TODO: should actually remember the previously used seq#, both for TX
209 * and RX from each STA.. */
210
Sunil Ravi77d572f2023-01-17 23:58:31 +0000211 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700212 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800213 os_memset(key, 0, sizeof(key));
214 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700215}
216
217
218static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
219{
220 struct wpa_supplicant *wpa_s = eloop_ctx;
221 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700222 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
223 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
224 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225 bssid = wpa_s->pending_bssid;
226 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
227 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800228 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700229 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800231 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 wpa_s->reassociate = 1;
233
234 /*
235 * If we timed out, the AP or the local radio may be busy.
236 * So, wait a second until scanning again.
237 */
238 wpa_supplicant_req_scan(wpa_s, 1, 0);
239}
240
241
242/**
243 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
244 * @wpa_s: Pointer to wpa_supplicant data
245 * @sec: Number of seconds after which to time out authentication
246 * @usec: Number of microseconds after which to time out authentication
247 *
248 * This function is used to schedule a timeout for the current authentication
249 * attempt.
250 */
251void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
252 int sec, int usec)
253{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700254 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
256 return;
257
258 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
259 "%d usec", sec, usec);
260 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700261 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
263}
264
265
Roshan Pius3a1667e2018-07-03 15:17:14 -0700266/*
267 * wpas_auth_timeout_restart - Restart and change timeout for authentication
268 * @wpa_s: Pointer to wpa_supplicant data
269 * @sec_diff: difference in seconds applied to original timeout value
270 */
271void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
272{
273 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
274
275 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
276 wpa_dbg(wpa_s, MSG_DEBUG,
277 "Authentication timeout restart: %d sec", new_sec);
278 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
279 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
280 wpa_s, NULL);
281 }
282}
283
284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285/**
286 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
287 * @wpa_s: Pointer to wpa_supplicant data
288 *
289 * This function is used to cancel authentication timeout scheduled with
290 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
291 * been completed.
292 */
293void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
294{
295 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
296 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800297 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700298 os_free(wpa_s->last_con_fail_realm);
299 wpa_s->last_con_fail_realm = NULL;
300 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700301}
302
303
304/**
305 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
306 * @wpa_s: Pointer to wpa_supplicant data
307 *
308 * This function is used to configure EAPOL state machine based on the selected
309 * authentication mode.
310 */
311void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
312{
313#ifdef IEEE8021X_EAPOL
314 struct eapol_config eapol_conf;
315 struct wpa_ssid *ssid = wpa_s->current_ssid;
316
317#ifdef CONFIG_IBSS_RSN
318 if (ssid->mode == WPAS_MODE_IBSS &&
319 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
320 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
321 /*
322 * RSN IBSS authentication is per-STA and we can disable the
323 * per-BSSID EAPOL authentication.
324 */
325 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700326 eapol_sm_notify_eap_success(wpa_s->eapol, true);
327 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328 return;
329 }
330#endif /* CONFIG_IBSS_RSN */
331
Hai Shalome21d4e82020-04-29 16:34:06 -0700332 eapol_sm_notify_eap_success(wpa_s->eapol, false);
333 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700334
335 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
336 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
337 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
338 else
339 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
340
341 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
342 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
343 eapol_conf.accept_802_1x_keys = 1;
344 eapol_conf.required_keys = 0;
345 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
346 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
347 }
348 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
349 eapol_conf.required_keys |=
350 EAPOL_REQUIRE_KEY_BROADCAST;
351 }
352
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700353 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 eapol_conf.required_keys = 0;
355 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700356 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700357 eapol_conf.workaround = ssid->eap_workaround;
358 eapol_conf.eap_disabled =
359 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
360 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
361 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700362 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800363
364#ifdef CONFIG_WPS
365 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
366 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
367 if (wpa_s->current_bss) {
368 struct wpabuf *ie;
369 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
370 WPS_IE_VENDOR_TYPE);
371 if (ie) {
372 if (wps_is_20(ie))
373 eapol_conf.wps |=
374 EAPOL_PEER_IS_WPS20_AP;
375 wpabuf_free(ie);
376 }
377 }
378 }
379#endif /* CONFIG_WPS */
380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700381 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700382
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800383#ifdef CONFIG_MACSEC
384 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
385 ieee802_1x_create_preshared_mka(wpa_s, ssid);
386 else
387 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
388#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800389#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700390}
391
392
393/**
394 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
395 * @wpa_s: Pointer to wpa_supplicant data
396 * @ssid: Configuration data for the network
397 *
398 * This function is used to configure WPA state machine and related parameters
399 * to a mode where WPA is not enabled. This is called as part of the
400 * authentication configuration when the selected network does not use WPA.
401 */
402void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
403 struct wpa_ssid *ssid)
404{
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700407#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000408 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700409
410 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
411 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
412 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
413 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
414 else
415 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
416 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
417 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700418 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700420 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
421 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
423 wpa_s->group_cipher = WPA_CIPHER_NONE;
424 wpa_s->mgmt_group_cipher = 0;
425
Hai Shalomfdcde762020-04-02 11:19:20 -0700426#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 for (i = 0; i < NUM_WEP_KEYS; i++) {
428 if (ssid->wep_key_len[i] > 5) {
429 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
430 wpa_s->group_cipher = WPA_CIPHER_WEP104;
431 break;
432 } else if (ssid->wep_key_len[i] > 0) {
433 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
434 wpa_s->group_cipher = WPA_CIPHER_WEP40;
435 break;
436 }
437 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700438#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
443 wpa_s->pairwise_cipher);
444 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
446 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447
448 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000449 os_memset(&mlo, 0, sizeof(mlo));
450 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451}
452
453
Dmitry Shmidt04949592012-07-19 12:16:46 -0700454void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800455{
456 int i;
457 if (wpa_s->hw.modes == NULL)
458 return;
459
460 for (i = 0; i < wpa_s->hw.num_modes; i++) {
461 os_free(wpa_s->hw.modes[i].channels);
462 os_free(wpa_s->hw.modes[i].rates);
463 }
464
465 os_free(wpa_s->hw.modes);
466 wpa_s->hw.modes = NULL;
467}
468
469
Hai Shalomc1a21442022-02-04 13:43:00 -0800470static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
471 struct wpa_bss_tmp_disallowed *bss)
472{
473 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
474 dl_list_del(&bss->list);
475 os_free(bss);
476}
477
478
Hai Shalom74f70d42019-02-11 14:42:39 -0800479void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800480{
481 struct wpa_bss_tmp_disallowed *bss, *prev;
482
483 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800484 struct wpa_bss_tmp_disallowed, list)
485 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800486}
487
488
Paul Stewart092955c2017-02-06 09:13:09 -0800489void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
490{
491 struct fils_hlp_req *req;
492
493 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
494 list)) != NULL) {
495 dl_list_del(&req->list);
496 wpabuf_free(req->pkt);
497 os_free(req);
498 }
499}
500
501
Hai Shalomfdcde762020-04-02 11:19:20 -0700502void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
503{
504 struct wpa_supplicant *wpa_s = eloop_ctx;
505
506 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
507 return;
508 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
509 wpa_bss_flush(wpa_s);
510}
511
512
513#ifdef CONFIG_TESTING_OPTIONS
514void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
515{
516 struct driver_signal_override *dso;
517
518 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
519 struct driver_signal_override, list))) {
520 dl_list_del(&dso->list);
521 os_free(dso);
522 }
523}
524#endif /* CONFIG_TESTING_OPTIONS */
525
526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
528{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700529 int i;
530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700532 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533 scard_deinit(wpa_s->scard);
534 wpa_s->scard = NULL;
535 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
536 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
537 l2_packet_deinit(wpa_s->l2);
538 wpa_s->l2 = NULL;
539 if (wpa_s->l2_br) {
540 l2_packet_deinit(wpa_s->l2_br);
541 wpa_s->l2_br = NULL;
542 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800543#ifdef CONFIG_TESTING_OPTIONS
544 l2_packet_deinit(wpa_s->l2_test);
545 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800546 os_free(wpa_s->get_pref_freq_list_override);
547 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700548 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
549 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800550 os_free(wpa_s->extra_sae_rejected_groups);
551 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700552 wpabuf_free(wpa_s->rsne_override_eapol);
553 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800554 wpabuf_free(wpa_s->rsnxe_override_assoc);
555 wpa_s->rsnxe_override_assoc = NULL;
556 wpabuf_free(wpa_s->rsnxe_override_eapol);
557 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700558 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800559#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 if (wpa_s->conf != NULL) {
562 struct wpa_ssid *ssid;
563 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
564 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 }
566
567 os_free(wpa_s->confname);
568 wpa_s->confname = NULL;
569
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700570 os_free(wpa_s->confanother);
571 wpa_s->confanother = NULL;
572
Hai Shalomce48b4a2018-09-05 11:41:35 -0700573 os_free(wpa_s->last_con_fail_realm);
574 wpa_s->last_con_fail_realm = NULL;
575 wpa_s->last_con_fail_realm_len = 0;
576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 wpa_sm_set_eapol(wpa_s->wpa, NULL);
578 eapol_sm_deinit(wpa_s->eapol);
579 wpa_s->eapol = NULL;
580
581 rsn_preauth_deinit(wpa_s->wpa);
582
583#ifdef CONFIG_TDLS
584 wpa_tdls_deinit(wpa_s->wpa);
585#endif /* CONFIG_TDLS */
586
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800587 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800589 ptksa_cache_deinit(wpa_s->ptksa);
590 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_sm_deinit(wpa_s->wpa);
592 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800593 wpa_bssid_ignore_clear(wpa_s);
594
595#ifdef CONFIG_PASN
596 wpas_pasn_auth_stop(wpa_s);
597#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
599 wpa_bss_deinit(wpa_s);
600
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700601 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpa_supplicant_cancel_scan(wpa_s);
603 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800604 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
605#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
606 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
607 wpa_s, NULL);
608#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700610 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700611 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 wpas_wps_deinit(wpa_s);
614
615 wpabuf_free(wpa_s->pending_eapol_rx);
616 wpa_s->pending_eapol_rx = NULL;
617
618#ifdef CONFIG_IBSS_RSN
619 ibss_rsn_deinit(wpa_s->ibss_rsn);
620 wpa_s->ibss_rsn = NULL;
621#endif /* CONFIG_IBSS_RSN */
622
623 sme_deinit(wpa_s);
624
625#ifdef CONFIG_AP
626 wpa_supplicant_ap_deinit(wpa_s);
627#endif /* CONFIG_AP */
628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800631#ifdef CONFIG_OFFCHANNEL
632 offchannel_deinit(wpa_s);
633#endif /* CONFIG_OFFCHANNEL */
634
635 wpa_supplicant_cancel_sched_scan(wpa_s);
636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 os_free(wpa_s->next_scan_freqs);
638 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800639
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800640 os_free(wpa_s->manual_scan_freqs);
641 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700642 os_free(wpa_s->select_network_scan_freqs);
643 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800644
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700645 os_free(wpa_s->manual_sched_scan_freqs);
646 wpa_s->manual_sched_scan_freqs = NULL;
647
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800648 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
649
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700650 /*
651 * Need to remove any pending gas-query radio work before the
652 * gas_query_deinit() call because gas_query::work has not yet been set
653 * for works that have not been started. gas_query_free() will be unable
654 * to cancel such pending radio works and once the pending gas-query
655 * radio work eventually gets removed, the deinit notification call to
656 * gas_query_start_cb() would result in dereferencing freed memory.
657 */
658 if (wpa_s->radio)
659 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660 gas_query_deinit(wpa_s->gas);
661 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700662 gas_server_deinit(wpa_s->gas_server);
663 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800664
665 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700666
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700667 ieee802_1x_dealloc_kay_sm(wpa_s);
668
Dmitry Shmidt04949592012-07-19 12:16:46 -0700669 os_free(wpa_s->bssid_filter);
670 wpa_s->bssid_filter = NULL;
671
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800672 os_free(wpa_s->disallow_aps_bssid);
673 wpa_s->disallow_aps_bssid = NULL;
674 os_free(wpa_s->disallow_aps_ssid);
675 wpa_s->disallow_aps_ssid = NULL;
676
Dmitry Shmidt04949592012-07-19 12:16:46 -0700677 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700678#ifdef CONFIG_WNM
679 wnm_deallocate_memory(wpa_s);
680#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700681
682 ext_password_deinit(wpa_s->ext_pw);
683 wpa_s->ext_pw = NULL;
684
685 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800686 wpa_s->last_gas_resp = NULL;
687 wpabuf_free(wpa_s->prev_gas_resp);
688 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700689
690 os_free(wpa_s->last_scan_res);
691 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800692
693#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700694 if (wpa_s->drv_priv)
695 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700696 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800697#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700698
699 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
700 wpabuf_free(wpa_s->vendor_elem[i]);
701 wpa_s->vendor_elem[i] = NULL;
702 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800703
704 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800705
706 wpa_s->sched_scan_plans_num = 0;
707 os_free(wpa_s->sched_scan_plans);
708 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800709
710#ifdef CONFIG_MBO
711 wpa_s->non_pref_chan_num = 0;
712 os_free(wpa_s->non_pref_chan);
713 wpa_s->non_pref_chan = NULL;
714#endif /* CONFIG_MBO */
715
716 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700717
718 wpabuf_free(wpa_s->lci);
719 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800720 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800721
722#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
723#ifdef CONFIG_MESH
724 {
725 struct external_pmksa_cache *entry;
726
727 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
728 struct external_pmksa_cache,
729 list)) != NULL) {
730 dl_list_del(&entry->list);
731 os_free(entry->pmksa_cache);
732 os_free(entry);
733 }
734 }
735#endif /* CONFIG_MESH */
736#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
737
738 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800739
740 wpabuf_free(wpa_s->ric_ies);
741 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700742
743#ifdef CONFIG_DPP
744 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700745 dpp_global_deinit(wpa_s->dpp);
746 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700747#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800748
749#ifdef CONFIG_PASN
750 wpas_pasn_auth_stop(wpa_s);
751#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800752 wpas_scs_deinit(wpa_s);
753 wpas_dscp_deinit(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000754
755#ifdef CONFIG_OWE
756 os_free(wpa_s->owe_trans_scan_freq);
757 wpa_s->owe_trans_scan_freq = NULL;
758#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759}
760
761
762/**
763 * wpa_clear_keys - Clear keys configured for the driver
764 * @wpa_s: Pointer to wpa_supplicant data
765 * @addr: Previously used BSSID or %NULL if not available
766 *
767 * This function clears the encryption keys that has been previously configured
768 * for the driver.
769 */
770void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
771{
Hai Shalomc3565922019-10-28 11:58:20 -0700772 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773
774 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800775 for (i = 0; i < max; i++) {
776 if (wpa_s->keys_cleared & BIT(i))
777 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000778 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700779 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800780 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700781 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
782 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800783 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700784 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000785 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
786 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700787 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000788 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
789 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 /* MLME-SETPROTECTION.request(None) */
791 wpa_drv_mlme_setprotection(
792 wpa_s, addr,
793 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
794 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
795 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800796 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797}
798
799
800/**
801 * wpa_supplicant_state_txt - Get the connection state name as a text string
802 * @state: State (wpa_state; WPA_*)
803 * Returns: The state name as a printable text string
804 */
805const char * wpa_supplicant_state_txt(enum wpa_states state)
806{
807 switch (state) {
808 case WPA_DISCONNECTED:
809 return "DISCONNECTED";
810 case WPA_INACTIVE:
811 return "INACTIVE";
812 case WPA_INTERFACE_DISABLED:
813 return "INTERFACE_DISABLED";
814 case WPA_SCANNING:
815 return "SCANNING";
816 case WPA_AUTHENTICATING:
817 return "AUTHENTICATING";
818 case WPA_ASSOCIATING:
819 return "ASSOCIATING";
820 case WPA_ASSOCIATED:
821 return "ASSOCIATED";
822 case WPA_4WAY_HANDSHAKE:
823 return "4WAY_HANDSHAKE";
824 case WPA_GROUP_HANDSHAKE:
825 return "GROUP_HANDSHAKE";
826 case WPA_COMPLETED:
827 return "COMPLETED";
828 default:
829 return "UNKNOWN";
830 }
831}
832
833
834#ifdef CONFIG_BGSCAN
835
Hai Shalom899fcc72020-10-19 14:38:18 -0700836static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
837{
838 if (wpa_s->bgscan_ssid) {
839 bgscan_deinit(wpa_s);
840 wpa_s->bgscan_ssid = NULL;
841 }
842}
843
844
845/**
846 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
847 * @wpa_s: Pointer to the wpa_supplicant data
848 *
849 * Stop, start, or reconfigure the scan parameters depending on the method.
850 */
851void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800853 const char *name;
854
855 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
856 name = wpa_s->current_ssid->bgscan;
857 else
858 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700859 if (!name || name[0] == '\0') {
860 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800861 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700862 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800863 if (wpas_driver_bss_selection(wpa_s))
864 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800865#ifdef CONFIG_P2P
866 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
867 return;
868#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869
870 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800871 if (wpa_s->current_ssid) {
872 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
874 "bgscan");
875 /*
876 * Live without bgscan; it is only used as a roaming
877 * optimization, so the initial connection is not
878 * affected.
879 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700880 } else {
881 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700883 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
884 0);
885 if (scan_res) {
886 bgscan_notify_scan(wpa_s, scan_res);
887 wpa_scan_results_free(scan_res);
888 }
889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 } else
891 wpa_s->bgscan_ssid = NULL;
892}
893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700894#endif /* CONFIG_BGSCAN */
895
896
Dmitry Shmidt04949592012-07-19 12:16:46 -0700897static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
898{
899 if (autoscan_init(wpa_s, 0))
900 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
901}
902
903
904static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
905{
906 autoscan_deinit(wpa_s);
907}
908
909
910void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
911{
912 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
913 wpa_s->wpa_state == WPA_SCANNING) {
914 autoscan_deinit(wpa_s);
915 wpa_supplicant_start_autoscan(wpa_s);
916 }
917}
918
919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920/**
921 * wpa_supplicant_set_state - Set current connection state
922 * @wpa_s: Pointer to wpa_supplicant data
923 * @state: The new connection state
924 *
925 * This function is called whenever the connection state changes, e.g.,
926 * association is completed for WPA/WPA2 4-Way Handshake is started.
927 */
928void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
929 enum wpa_states state)
930{
931 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700932#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700933 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700934#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935
936 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
937 wpa_supplicant_state_txt(wpa_s->wpa_state),
938 wpa_supplicant_state_txt(state));
939
Hai Shalom74f70d42019-02-11 14:42:39 -0800940 if (state == WPA_COMPLETED &&
941 os_reltime_initialized(&wpa_s->roam_start)) {
942 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
943 wpa_s->roam_start.sec = 0;
944 wpa_s->roam_start.usec = 0;
945 wpas_notify_auth_changed(wpa_s);
946 wpas_notify_roam_time(wpa_s);
947 wpas_notify_roam_complete(wpa_s);
948 } else if (state == WPA_DISCONNECTED &&
949 os_reltime_initialized(&wpa_s->roam_start)) {
950 wpa_s->roam_start.sec = 0;
951 wpa_s->roam_start.usec = 0;
952 wpa_s->roam_time.sec = 0;
953 wpa_s->roam_time.usec = 0;
954 wpas_notify_roam_complete(wpa_s);
955 }
956
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800957 if (state == WPA_INTERFACE_DISABLED) {
958 /* Assure normal scan when interface is restored */
959 wpa_s->normal_scans = 0;
960 }
961
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700962 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800963 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700964 /* Reinitialize normal_scan counter */
965 wpa_s->normal_scans = 0;
966 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800967
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700968#ifdef CONFIG_P2P
969 /*
970 * P2PS client has to reply to Probe Request frames received on the
971 * group operating channel. Enable Probe Request frame reporting for
972 * P2P connected client in case p2p_cli_probe configuration property is
973 * set to 1.
974 */
975 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
976 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
977 wpa_s->current_ssid->p2p_group) {
978 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
979 wpa_dbg(wpa_s, MSG_DEBUG,
980 "P2P: Enable CLI Probe Request RX reporting");
981 wpa_s->p2p_cli_probe =
982 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
983 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
984 wpa_dbg(wpa_s, MSG_DEBUG,
985 "P2P: Disable CLI Probe Request RX reporting");
986 wpa_s->p2p_cli_probe = 0;
987 wpa_drv_probe_req_report(wpa_s, 0);
988 }
989 }
990#endif /* CONFIG_P2P */
991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700992 if (state != WPA_SCANNING)
993 wpa_supplicant_notify_scanning(wpa_s, 0);
994
995 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700997 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -0700998 char mld_addr[50];
999
1000 mld_addr[0] = '\0';
1001 if (wpa_s->valid_links)
1002 os_snprintf(mld_addr, sizeof(mld_addr),
1003 " ap_mld_addr=" MACSTR,
1004 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001005
1006#ifdef CONFIG_SME
1007 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1008 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1009 fils_hlp_sent = 1;
1010#endif /* CONFIG_SME */
1011 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1012 wpa_auth_alg_fils(wpa_s->auth_alg))
1013 fils_hlp_sent = 1;
1014
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001015#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001017 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001018 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001020 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001021 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001023 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001024 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 wpa_drv_set_operstate(wpa_s, 1);
1027#ifndef IEEE8021X_EAPOL
1028 wpa_drv_set_supp_port(wpa_s, 1);
1029#endif /* IEEE8021X_EAPOL */
1030 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001031 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001033
1034 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001035
1036#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1037 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001038 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001039#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001040#ifdef CONFIG_OWE
1041 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1042 wpas_update_owe_connect_params(wpa_s);
1043#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001044#ifdef CONFIG_HS20
1045 hs20_configure_frame_filters(wpa_s);
1046#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1048 state == WPA_ASSOCIATED) {
1049 wpa_s->new_connection = 1;
1050 wpa_drv_set_operstate(wpa_s, 0);
1051#ifndef IEEE8021X_EAPOL
1052 wpa_drv_set_supp_port(wpa_s, 0);
1053#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001054 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055 }
1056 wpa_s->wpa_state = state;
1057
1058#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001059 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1060 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001061 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 wpa_supplicant_stop_bgscan(wpa_s);
1063#endif /* CONFIG_BGSCAN */
1064
Hai Shalom5f92bc92019-04-18 11:54:11 -07001065 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001066 wpa_supplicant_stop_autoscan(wpa_s);
1067
1068 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1069 wpa_supplicant_start_autoscan(wpa_s);
1070
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001071 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1072 wmm_ac_notify_disassoc(wpa_s);
1073
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 if (wpa_s->wpa_state != old_state) {
1075 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1076
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001077 /*
1078 * Notify the P2P Device interface about a state change in one
1079 * of the interfaces.
1080 */
1081 wpas_p2p_indicate_state_change(wpa_s);
1082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083 if (wpa_s->wpa_state == WPA_COMPLETED ||
1084 old_state == WPA_COMPLETED)
1085 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001086#ifdef CONFIG_DPP2
1087 if (wpa_s->wpa_state == WPA_COMPLETED)
1088 wpas_dpp_connected(wpa_s);
1089#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 }
Hai Shalomc3565922019-10-28 11:58:20 -07001091#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1092 if (update_fils_connect_params)
1093 wpas_update_fils_connect_params(wpa_s);
1094#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095}
1096
1097
1098void wpa_supplicant_terminate_proc(struct wpa_global *global)
1099{
1100 int pending = 0;
1101#ifdef CONFIG_WPS
1102 struct wpa_supplicant *wpa_s = global->ifaces;
1103 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001104 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001105 if (wpas_wps_terminate_pending(wpa_s) == 1)
1106 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001107#ifdef CONFIG_P2P
1108 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1109 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1110 wpas_p2p_disconnect(wpa_s);
1111#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001112 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113 }
1114#endif /* CONFIG_WPS */
1115 if (pending)
1116 return;
1117 eloop_terminate();
1118}
1119
1120
1121static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1122{
1123 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001124 wpa_supplicant_terminate_proc(global);
1125}
1126
1127
1128void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1129{
1130 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001131 enum wpa_states new_state;
1132
1133 if (old_state == WPA_SCANNING)
1134 new_state = WPA_SCANNING;
1135 else
1136 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137
1138 wpa_s->pairwise_cipher = 0;
1139 wpa_s->group_cipher = 0;
1140 wpa_s->mgmt_group_cipher = 0;
1141 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001142 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001144 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145
1146 if (wpa_s->wpa_state != old_state)
1147 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1148}
1149
1150
1151/**
1152 * wpa_supplicant_reload_configuration - Reload configuration data
1153 * @wpa_s: Pointer to wpa_supplicant data
1154 * Returns: 0 on success or -1 if configuration parsing failed
1155 *
1156 * This function can be used to request that the configuration data is reloaded
1157 * (e.g., after configuration file change). This function is reloading
1158 * configuration only for one interface, so this may need to be called multiple
1159 * times if %wpa_supplicant is controlling multiple interfaces and all
1160 * interfaces need reconfiguration.
1161 */
1162int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1163{
1164 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 int reconf_ctrl;
1166 int old_ap_scan;
1167
1168 if (wpa_s->confname == NULL)
1169 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001170 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171 if (conf == NULL) {
1172 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1173 "file '%s' - exiting", wpa_s->confname);
1174 return -1;
1175 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001176 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001177 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001178 wpa_msg(wpa_s, MSG_ERROR,
1179 "Failed to parse the configuration file '%s' - exiting",
1180 wpa_s->confanother);
1181 return -1;
1182 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 conf->changed_parameters = (unsigned int) -1;
1185
1186 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1187 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1188 os_strcmp(conf->ctrl_interface,
1189 wpa_s->conf->ctrl_interface) != 0);
1190
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001191 if (reconf_ctrl) {
1192 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 wpa_s->ctrl_iface = NULL;
1194 }
1195
1196 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001197 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001198 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1199 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001200 wpa_supplicant_deauthenticate(wpa_s,
1201 WLAN_REASON_DEAUTH_LEAVING);
1202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203
1204 /*
1205 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001206 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001208 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1209 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1210 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 /*
1212 * Clear forced success to clear EAP state for next
1213 * authentication.
1214 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001215 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 }
1217 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1218 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001219 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1221 rsn_preauth_deinit(wpa_s->wpa);
1222
1223 old_ap_scan = wpa_s->conf->ap_scan;
1224 wpa_config_free(wpa_s->conf);
1225 wpa_s->conf = conf;
1226 if (old_ap_scan != wpa_s->conf->ap_scan)
1227 wpas_notify_ap_scan_changed(wpa_s);
1228
1229 if (reconf_ctrl)
1230 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1231
1232 wpa_supplicant_update_config(wpa_s);
1233
1234 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001235 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 wpa_s->reassociate = 1;
1237 wpa_supplicant_req_scan(wpa_s, 0, 0);
1238 }
Hai Shalom60840252021-02-19 19:02:11 -08001239 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1241 return 0;
1242}
1243
1244
1245static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1246{
1247 struct wpa_global *global = signal_ctx;
1248 struct wpa_supplicant *wpa_s;
1249 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1250 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1251 sig);
1252 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1253 wpa_supplicant_terminate_proc(global);
1254 }
1255 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001256
1257 if (wpa_debug_reopen_file() < 0) {
1258 /* Ignore errors since we cannot really do much to fix this */
1259 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261}
1262
1263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001264static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1265 struct wpa_ssid *ssid,
1266 struct wpa_ie_data *ie)
1267{
1268 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1269 if (ret) {
1270 if (ret == -2) {
1271 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1272 "from association info");
1273 }
1274 return -1;
1275 }
1276
1277 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1278 "cipher suites");
1279 if (!(ie->group_cipher & ssid->group_cipher)) {
1280 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1281 "cipher 0x%x (mask 0x%x) - reject",
1282 ie->group_cipher, ssid->group_cipher);
1283 return -1;
1284 }
1285 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1286 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1287 "cipher 0x%x (mask 0x%x) - reject",
1288 ie->pairwise_cipher, ssid->pairwise_cipher);
1289 return -1;
1290 }
1291 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1292 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1293 "management 0x%x (mask 0x%x) - reject",
1294 ie->key_mgmt, ssid->key_mgmt);
1295 return -1;
1296 }
1297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001299 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1301 "that does not support management frame protection - "
1302 "reject");
1303 return -1;
1304 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305
1306 return 0;
1307}
1308
1309
Hai Shalom021b0b52019-04-10 11:17:58 -07001310static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1311 int freq)
1312{
1313 if (!ie->has_group)
1314 ie->group_cipher = wpa_default_rsn_cipher(freq);
1315 if (!ie->has_pairwise)
1316 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1317 return (ie->group_cipher & ssid->group_cipher) &&
1318 (ie->pairwise_cipher & ssid->pairwise_cipher);
1319}
1320
1321
Hai Shalomc1a21442022-02-04 13:43:00 -08001322void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1323 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1324{
1325 int sel;
1326
1327 sel = ie->mgmt_group_cipher;
1328 if (ssid->group_mgmt_cipher)
1329 sel &= ssid->group_mgmt_cipher;
1330 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1331 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1332 sel = 0;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1335 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1336 if (sel & WPA_CIPHER_AES_128_CMAC) {
1337 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1338 wpa_dbg(wpa_s, MSG_DEBUG,
1339 "WPA: using MGMT group cipher AES-128-CMAC");
1340 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1341 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1342 wpa_dbg(wpa_s, MSG_DEBUG,
1343 "WPA: using MGMT group cipher BIP-GMAC-128");
1344 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1345 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1346 wpa_dbg(wpa_s, MSG_DEBUG,
1347 "WPA: using MGMT group cipher BIP-GMAC-256");
1348 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1349 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1350 wpa_dbg(wpa_s, MSG_DEBUG,
1351 "WPA: using MGMT group cipher BIP-CMAC-256");
1352 } else {
1353 wpa_s->mgmt_group_cipher = 0;
1354 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1355 }
1356 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1357 wpa_s->mgmt_group_cipher);
1358 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1359 wpas_get_ssid_pmf(wpa_s, ssid));
1360}
1361
Sunil Ravi77d572f2023-01-17 23:58:31 +00001362/**
1363 * wpa_supplicant_get_psk - Get PSK from config or external database
1364 * @wpa_s: Pointer to wpa_supplicant data
1365 * @bss: Scan results for the selected BSS, or %NULL if not available
1366 * @ssid: Configuration data for the selected network
1367 * @psk: Buffer for the PSK
1368 * Returns: 0 on success or -1 if configuration parsing failed
1369 *
1370 * This function obtains the PSK for a network, either included inline in the
1371 * config or retrieved from an external database.
1372 */
1373static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1374 struct wpa_bss *bss, struct wpa_ssid *ssid,
1375 u8 *psk)
1376{
1377 if (ssid->psk_set) {
1378 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1379 ssid->psk, PMK_LEN);
1380 os_memcpy(psk, ssid->psk, PMK_LEN);
1381 return 0;
1382 }
1383
1384#ifndef CONFIG_NO_PBKDF2
1385 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1386 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1387 4096, psk, PMK_LEN) != 0) {
1388 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1389 return -1;
1390 }
1391 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1392 psk, PMK_LEN);
1393 return 0;
1394 }
1395#endif /* CONFIG_NO_PBKDF2 */
1396
1397#ifdef CONFIG_EXT_PASSWORD
1398 if (ssid->ext_psk) {
1399 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1400 ssid->ext_psk);
1401 char pw_str[64 + 1];
1402
1403 if (!pw) {
1404 wpa_msg(wpa_s, MSG_INFO,
1405 "EXT PW: No PSK found from external storage");
1406 return -1;
1407 }
1408
1409 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1410 wpa_msg(wpa_s, MSG_INFO,
1411 "EXT PW: Unexpected PSK length %d in external storage",
1412 (int) wpabuf_len(pw));
1413 ext_password_free(pw);
1414 return -1;
1415 }
1416
1417 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1418 pw_str[wpabuf_len(pw)] = '\0';
1419
1420#ifndef CONFIG_NO_PBKDF2
1421 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1422 {
1423 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1424 4096, psk, PMK_LEN) != 0) {
1425 wpa_msg(wpa_s, MSG_WARNING,
1426 "Error in pbkdf2_sha1()");
1427 forced_memzero(pw_str, sizeof(pw_str));
1428 ext_password_free(pw);
1429 return -1;
1430 }
1431 wpa_hexdump_key(MSG_MSGDUMP,
1432 "PSK (from external passphrase)",
1433 psk, PMK_LEN);
1434 } else
1435#endif /* CONFIG_NO_PBKDF2 */
1436 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1437 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1438 wpa_msg(wpa_s, MSG_INFO,
1439 "EXT PW: Invalid PSK hex string");
1440 forced_memzero(pw_str, sizeof(pw_str));
1441 ext_password_free(pw);
1442 return -1;
1443 }
1444 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1445 psk, PMK_LEN);
1446 } else {
1447 wpa_msg(wpa_s, MSG_INFO,
1448 "EXT PW: No suitable PSK available");
1449 forced_memzero(pw_str, sizeof(pw_str));
1450 ext_password_free(pw);
1451 return -1;
1452 }
1453
1454 forced_memzero(pw_str, sizeof(pw_str));
1455 ext_password_free(pw);
1456
1457 return 0;
1458 }
1459#endif /* CONFIG_EXT_PASSWORD */
1460
1461 return -1;
1462}
1463
Hai Shalomc1a21442022-02-04 13:43:00 -08001464
Sunil Ravi89eba102022-09-13 21:04:37 -07001465static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1466 struct wpa_ssid *ssid)
1467{
1468 int akm_count = wpa_s->max_num_akms;
1469 u8 capab = 0;
1470
1471 if (akm_count < 2)
1472 return;
1473
1474 akm_count--;
1475 wpa_s->allowed_key_mgmts = 0;
1476 switch (wpa_s->key_mgmt) {
1477 case WPA_KEY_MGMT_PSK:
1478 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1479 akm_count--;
1480 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1481 }
1482 if (!akm_count)
1483 break;
1484 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1485 akm_count--;
1486 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1487 }
1488 if (!akm_count)
1489 break;
1490 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1491 wpa_s->allowed_key_mgmts |=
1492 WPA_KEY_MGMT_PSK_SHA256;
1493 break;
1494 case WPA_KEY_MGMT_PSK_SHA256:
1495 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1496 akm_count--;
1497 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1498 }
1499 if (!akm_count)
1500 break;
1501 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1502 akm_count--;
1503 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1504 }
1505 if (!akm_count)
1506 break;
1507 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1508 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1509 break;
1510 case WPA_KEY_MGMT_SAE:
1511 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1512 akm_count--;
1513 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1514 }
1515 if (!akm_count)
1516 break;
1517 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1518 akm_count--;
1519 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1520 }
1521 if (!akm_count)
1522 break;
1523 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1524 wpa_s->allowed_key_mgmts |=
1525 WPA_KEY_MGMT_PSK_SHA256;
1526 break;
1527 case WPA_KEY_MGMT_SAE_EXT_KEY:
1528 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1529 akm_count--;
1530 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1531 }
1532 if (!akm_count)
1533 break;
1534 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1535 akm_count--;
1536 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1537 }
1538 if (!akm_count)
1539 break;
1540 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1541 wpa_s->allowed_key_mgmts |=
1542 WPA_KEY_MGMT_PSK_SHA256;
1543 break;
1544 default:
1545 return;
1546 }
1547
Sunil Ravi77d572f2023-01-17 23:58:31 +00001548 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1549 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001550 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1551#ifdef CONFIG_SAE_PK
1552 if (ssid->sae_pk)
1553 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1554#endif /* CONFIG_SAE_PK */
1555
1556 if (!((wpa_s->allowed_key_mgmts &
1557 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1558 return;
1559
1560 if (!wpa_s->rsnxe_len) {
1561 wpa_s->rsnxe_len = 3;
1562 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1563 wpa_s->rsnxe[1] = 1;
1564 wpa_s->rsnxe[2] = 0;
1565 }
1566
1567 wpa_s->rsnxe[2] |= capab;
1568}
1569
1570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001571/**
1572 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1573 * @wpa_s: Pointer to wpa_supplicant data
1574 * @bss: Scan results for the selected BSS, or %NULL if not available
1575 * @ssid: Configuration data for the selected network
1576 * @wpa_ie: Buffer for the WPA/RSN IE
1577 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1578 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001579 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 * Returns: 0 on success or -1 on failure
1581 *
1582 * This function is used to configure authentication and encryption parameters
1583 * based on the network configuration and scan result for the selected BSS (if
1584 * available).
1585 */
1586int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1587 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001588 u8 *wpa_ie, size_t *wpa_ie_len,
1589 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590{
1591 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001592 int sel, proto;
1593 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001594 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001595 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001596
1597 if (bss) {
1598 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1599 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001600 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001601 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001602 } else {
1603 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1604 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605
1606 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1607 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001608 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 (ie.key_mgmt & ssid->key_mgmt)) {
1610 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1611 proto = WPA_PROTO_RSN;
1612 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001613 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614 (ie.group_cipher & ssid->group_cipher) &&
1615 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1616 (ie.key_mgmt & ssid->key_mgmt)) {
1617 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1618 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001619#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001620 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1621 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1622 (ie.group_cipher & ssid->group_cipher) &&
1623 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1624 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001625 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001626 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001627 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1628 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1629 (ie.group_cipher & ssid->group_cipher) &&
1630 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1631 (ie.key_mgmt & ssid->key_mgmt)) {
1632 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1633 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001634#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 } else if (bss) {
1636 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001637 wpa_dbg(wpa_s, MSG_DEBUG,
1638 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1639 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1640 ssid->key_mgmt);
1641 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1642 MAC2STR(bss->bssid),
1643 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1644 bss_wpa ? " WPA" : "",
1645 bss_rsn ? " RSN" : "",
1646 bss_osen ? " OSEN" : "");
1647 if (bss_rsn) {
1648 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1649 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1650 wpa_dbg(wpa_s, MSG_DEBUG,
1651 "Could not parse RSN element");
1652 } else {
1653 wpa_dbg(wpa_s, MSG_DEBUG,
1654 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1655 ie.pairwise_cipher, ie.group_cipher,
1656 ie.key_mgmt);
1657 }
1658 }
1659 if (bss_wpa) {
1660 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1661 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1662 wpa_dbg(wpa_s, MSG_DEBUG,
1663 "Could not parse WPA element");
1664 } else {
1665 wpa_dbg(wpa_s, MSG_DEBUG,
1666 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1667 ie.pairwise_cipher, ie.group_cipher,
1668 ie.key_mgmt);
1669 }
1670 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671 return -1;
1672 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001673 if (ssid->proto & WPA_PROTO_OSEN)
1674 proto = WPA_PROTO_OSEN;
1675 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001676 proto = WPA_PROTO_RSN;
1677 else
1678 proto = WPA_PROTO_WPA;
1679 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1680 os_memset(&ie, 0, sizeof(ie));
1681 ie.group_cipher = ssid->group_cipher;
1682 ie.pairwise_cipher = ssid->pairwise_cipher;
1683 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001684 ie.mgmt_group_cipher = 0;
1685 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1686 if (ssid->group_mgmt_cipher &
1687 WPA_CIPHER_BIP_GMAC_256)
1688 ie.mgmt_group_cipher =
1689 WPA_CIPHER_BIP_GMAC_256;
1690 else if (ssid->group_mgmt_cipher &
1691 WPA_CIPHER_BIP_CMAC_256)
1692 ie.mgmt_group_cipher =
1693 WPA_CIPHER_BIP_CMAC_256;
1694 else if (ssid->group_mgmt_cipher &
1695 WPA_CIPHER_BIP_GMAC_128)
1696 ie.mgmt_group_cipher =
1697 WPA_CIPHER_BIP_GMAC_128;
1698 else
1699 ie.mgmt_group_cipher =
1700 WPA_CIPHER_AES_128_CMAC;
1701 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001702#ifdef CONFIG_OWE
1703 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1704 !ssid->owe_only &&
1705 !bss_wpa && !bss_rsn && !bss_osen) {
1706 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1707 wpa_s->wpa_proto = 0;
1708 *wpa_ie_len = 0;
1709 return 0;
1710 }
1711#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001712 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1713 "based on configuration");
1714 } else
1715 proto = ie.proto;
1716 }
1717
1718 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1719 "pairwise %d key_mgmt %d proto %d",
1720 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 if (ssid->ieee80211w) {
1722 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1723 ie.mgmt_group_cipher);
1724 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001726 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1728 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001729 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730
1731 if (bss || !wpa_s->ap_ies_from_associnfo) {
1732 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1733 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1734 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001735 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1736 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1737 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001738 return -1;
1739 }
1740
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001741#ifdef CONFIG_NO_WPA
1742 wpa_s->group_cipher = WPA_CIPHER_NONE;
1743 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1744#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001746 wpa_dbg(wpa_s, MSG_DEBUG,
1747 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1748 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001749 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1750 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1752 "cipher");
1753 return -1;
1754 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001755 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1756 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757
1758 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001759 wpa_dbg(wpa_s, MSG_DEBUG,
1760 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1761 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001762 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1763 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1765 "cipher");
1766 return -1;
1767 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001768 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1769 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001770#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001771
1772 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001773#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001774 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1775 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001776 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001777 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1778 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001779#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001780#ifdef CONFIG_IEEE80211R
1781 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1782 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1783 sel &= ~WPA_KEY_MGMT_FT;
1784#endif /* CONFIG_IEEE80211R */
1785 wpa_dbg(wpa_s, MSG_DEBUG,
1786 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1787 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001789#ifdef CONFIG_IEEE80211R
1790#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001791 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1792 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001793 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1794 wpa_dbg(wpa_s, MSG_DEBUG,
1795 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001796 if (!ssid->ft_eap_pmksa_caching &&
1797 pmksa_cache_get_current(wpa_s->wpa)) {
1798 /* PMKSA caching with FT may have interoperability
1799 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001800 wpa_dbg(wpa_s, MSG_DEBUG,
1801 "WPA: Disable PMKSA caching for FT/802.1X connection");
1802 pmksa_cache_clear_current(wpa_s->wpa);
1803 }
1804#endif /* CONFIG_SHA384 */
1805#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001806#ifdef CONFIG_SUITEB192
1807 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1808 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1809 wpa_dbg(wpa_s, MSG_DEBUG,
1810 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1811#endif /* CONFIG_SUITEB192 */
1812#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001813 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1814 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1815 wpa_dbg(wpa_s, MSG_DEBUG,
1816 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001817#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001818#ifdef CONFIG_SHA384
1819 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1820 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1821 wpa_dbg(wpa_s, MSG_DEBUG,
1822 "WPA: using KEY_MGMT 802.1X with SHA384");
1823#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001824#ifdef CONFIG_FILS
1825#ifdef CONFIG_IEEE80211R
1826 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1827 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1828 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001829#endif /* CONFIG_IEEE80211R */
1830 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1831 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1832 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001833#ifdef CONFIG_IEEE80211R
1834 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1835 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1836 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1837#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001838 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1839 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1840 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1841#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001843 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1844 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1846 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001847 if (!ssid->ft_eap_pmksa_caching &&
1848 pmksa_cache_get_current(wpa_s->wpa)) {
1849 /* PMKSA caching with FT may have interoperability
1850 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001851 wpa_dbg(wpa_s, MSG_DEBUG,
1852 "WPA: Disable PMKSA caching for FT/802.1X connection");
1853 pmksa_cache_clear_current(wpa_s->wpa);
1854 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001855#endif /* CONFIG_IEEE80211R */
1856#ifdef CONFIG_DPP
1857 } else if (sel & WPA_KEY_MGMT_DPP) {
1858 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1859 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1860#endif /* CONFIG_DPP */
1861#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001862 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1863 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1864 wpa_dbg(wpa_s, MSG_DEBUG,
1865 "RSN: using KEY_MGMT FT/SAE (ext key)");
1866 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1867 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1868 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001869 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1870 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1871 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1872 } else if (sel & WPA_KEY_MGMT_SAE) {
1873 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1874 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1875#endif /* CONFIG_SAE */
1876#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1878 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1879 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1880#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1882 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1883 wpa_dbg(wpa_s, MSG_DEBUG,
1884 "WPA: using KEY_MGMT 802.1X with SHA256");
1885 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1886 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1887 wpa_dbg(wpa_s, MSG_DEBUG,
1888 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1890 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1891 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1892 } else if (sel & WPA_KEY_MGMT_PSK) {
1893 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1894 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1895 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1896 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1897 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001898#ifdef CONFIG_HS20
1899 } else if (sel & WPA_KEY_MGMT_OSEN) {
1900 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1901 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1902#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001903#ifdef CONFIG_OWE
1904 } else if (sel & WPA_KEY_MGMT_OWE) {
1905 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1906 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1907#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001908 } else {
1909 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1910 "authenticated key management type");
1911 return -1;
1912 }
1913
1914 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1915 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1916 wpa_s->pairwise_cipher);
1917 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1918
Hai Shalomc3565922019-10-28 11:58:20 -07001919 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001920 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1921 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001922 wpa_msg(wpa_s, MSG_INFO,
1923 "RSN: Management frame protection required but the selected AP does not enable it");
1924 return -1;
1925 }
1926
Hai Shalomc1a21442022-02-04 13:43:00 -08001927 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001928#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001929 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1930 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1931 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001932#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001933 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001934 if ((ssid->sae_password_id ||
1935 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001936 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1937 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1938 if (bss && is_6ghz_freq(bss->freq) &&
1939 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1940 wpa_dbg(wpa_s, MSG_DEBUG,
1941 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1942 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001943 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001944 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001945#ifdef CONFIG_SAE_PK
1946 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1947 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1948 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1949 ((ssid->sae_password &&
1950 sae_pk_valid_password(ssid->sae_password)) ||
1951 (!ssid->sae_password && ssid->passphrase &&
1952 sae_pk_valid_password(ssid->passphrase))));
1953#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001954 if (bss && is_6ghz_freq(bss->freq) &&
1955 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1956 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1957 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1958 MGMT_FRAME_PROTECTION_REQUIRED);
1959 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001960#ifdef CONFIG_TESTING_OPTIONS
1961 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1962 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001963 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1964 wpa_s->oci_freq_override_eapol);
1965 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1966 wpa_s->oci_freq_override_eapol_g2);
1967 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1968 wpa_s->oci_freq_override_ft_assoc);
1969 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1970 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001971 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1972 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001973#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001974
1975 /* Extended Key ID is only supported in infrastructure BSS so far */
1976 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1977 (ssid->proto & WPA_PROTO_RSN) &&
1978 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1979 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1980 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1981 int use_ext_key_id = 0;
1982
1983 wpa_msg(wpa_s, MSG_DEBUG,
1984 "WPA: Enable Extended Key ID support");
1985 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1986 wpa_s->conf->extended_key_id);
1987 if (bss_rsn &&
1988 wpa_s->conf->extended_key_id &&
1989 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1990 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1991 use_ext_key_id = 1;
1992 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1993 use_ext_key_id);
1994 } else {
1995 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1996 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1997 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998
Sunil Ravi640215c2023-06-28 23:08:09 +00001999 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2000 * appropriate advertisement of the supported number of PTKSA receive
2001 * counters. In theory, this could be based on a driver capability, but
2002 * in practice all cases using WMM support at least eight replay
2003 * counters, so use a hardcoded value for now since there is no explicit
2004 * driver capability indication for this.
2005 *
2006 * In addition, claim WMM to be enabled if the AP supports it since it
2007 * is far more likely for any current device to support WMM. */
2008 wmm = wpa_s->connection_set &&
2009 (wpa_s->connection_ht || wpa_s->connection_vht ||
2010 wpa_s->connection_he || wpa_s->connection_eht);
2011 if (!wmm && bss)
2012 wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
2013 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2014
Sunil Ravi77d572f2023-01-17 23:58:31 +00002015 if (!skip_default_rsne) {
2016 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2017 wpa_ie_len)) {
2018 wpa_msg(wpa_s, MSG_WARNING,
2019 "RSN: Failed to generate RSNE/WPA IE");
2020 return -1;
2021 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022
Sunil Ravi77d572f2023-01-17 23:58:31 +00002023 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2024 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2025 &wpa_s->rsnxe_len)) {
2026 wpa_msg(wpa_s, MSG_WARNING,
2027 "RSN: Failed to generate RSNXE");
2028 return -1;
2029 }
Hai Shalomc3565922019-10-28 11:58:20 -07002030 }
2031
Hai Shalom021b0b52019-04-10 11:17:58 -07002032 if (0) {
2033#ifdef CONFIG_DPP
2034 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2035 /* Use PMK from DPP network introduction (PMKSA entry) */
2036 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002037#ifdef CONFIG_DPP2
2038 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2039#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002040#endif /* CONFIG_DPP */
2041 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002042 int psk_set = 0;
2043
Sunil Ravi77d572f2023-01-17 23:58:31 +00002044 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2045 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002046
Sunil Ravi77d572f2023-01-17 23:58:31 +00002047 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2048 psk) == 0) {
2049 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2050 NULL);
2051 psk_set = 1;
2052 }
2053 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002054 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002055
Roshan Pius3a1667e2018-07-03 15:17:14 -07002056 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002057 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002058 psk_set = 1;
2059
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002060 if (!psk_set) {
2061 wpa_msg(wpa_s, MSG_INFO,
2062 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002063 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002064 return -1;
2065 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002066#ifdef CONFIG_OWE
2067 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2068 /* OWE Diffie-Hellman exchange in (Re)Association
2069 * Request/Response frames set the PMK, so do not override it
2070 * here. */
2071#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002072 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2074
Hai Shalomfdcde762020-04-02 11:19:20 -07002075 if (ssid->mode != WPAS_MODE_IBSS &&
2076 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2077 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2078 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2079 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2080 wpa_msg(wpa_s, MSG_INFO,
2081 "Disable PTK0 rekey support - replaced with reconnect");
2082 wpa_s->deny_ptk0_rekey = 1;
2083 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2084 } else {
2085 wpa_s->deny_ptk0_rekey = 0;
2086 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2087 }
2088
Winnie Chen4138eec2022-11-10 16:32:53 +08002089#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302090 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002091 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2092 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002093 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2094 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302095 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2096 wpa_dbg(wpa_s, MSG_INFO,
2097 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2098 }
Sunil Ravif42be322022-11-04 03:31:21 +00002099#else
2100 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2101 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2102 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002103#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302104
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002105 return 0;
2106}
2107
2108
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002109static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2110 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002111{
Hai Shalomc1a21442022-02-04 13:43:00 -08002112 bool scs = true, mscs = true;
2113
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002114 *pos = 0x00;
2115
2116 switch (idx) {
2117 case 0: /* Bits 0-7 */
2118 break;
2119 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002120 if (wpa_s->conf->coloc_intf_reporting) {
2121 /* Bit 13 - Collocated Interference Reporting */
2122 *pos |= 0x20;
2123 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002124 break;
2125 case 2: /* Bits 16-23 */
2126#ifdef CONFIG_WNM
2127 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002128 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002129 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002130#endif /* CONFIG_WNM */
2131 break;
2132 case 3: /* Bits 24-31 */
2133#ifdef CONFIG_WNM
2134 *pos |= 0x02; /* Bit 25 - SSID List */
2135#endif /* CONFIG_WNM */
2136#ifdef CONFIG_INTERWORKING
2137 if (wpa_s->conf->interworking)
2138 *pos |= 0x80; /* Bit 31 - Interworking */
2139#endif /* CONFIG_INTERWORKING */
2140 break;
2141 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002142#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002143 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002144 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002145#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002146 break;
2147 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002148#ifdef CONFIG_HS20
2149 if (wpa_s->conf->hs20)
2150 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2151#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002152#ifdef CONFIG_MBO
2153 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2154#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002155 break;
2156 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002157#ifdef CONFIG_TESTING_OPTIONS
2158 if (wpa_s->disable_scs_support)
2159 scs = false;
2160#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002161 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2162 /* Drop own SCS capability indication since the AP does
2163 * not support it. This is needed to avoid
2164 * interoperability issues with APs that get confused
2165 * with Extended Capabilities element. */
2166 scs = false;
2167 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002168 if (scs)
2169 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002170 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002171 case 7: /* Bits 56-63 */
2172 break;
2173 case 8: /* Bits 64-71 */
2174 if (wpa_s->conf->ftm_responder)
2175 *pos |= 0x40; /* Bit 70 - FTM responder */
2176 if (wpa_s->conf->ftm_initiator)
2177 *pos |= 0x80; /* Bit 71 - FTM initiator */
2178 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002179 case 9: /* Bits 72-79 */
2180#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002181 if (!wpa_s->disable_fils)
2182 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002183#endif /* CONFIG_FILS */
2184 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002185 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002186#ifdef CONFIG_TESTING_OPTIONS
2187 if (wpa_s->disable_mscs_support)
2188 mscs = false;
2189#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002190 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2191 /* Drop own MSCS capability indication since the AP does
2192 * not support it. This is needed to avoid
2193 * interoperability issues with APs that get confused
2194 * with Extended Capabilities element. */
2195 mscs = false;
2196 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002197 if (mscs)
2198 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002199 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002200 }
2201}
2202
2203
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002204int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2205 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002206{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002207 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002208 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002209
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002210 if (len < wpa_s->extended_capa_len)
2211 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002212 if (buflen < (size_t) len + 2) {
2213 wpa_printf(MSG_INFO,
2214 "Not enough room for building extended capabilities element");
2215 return -1;
2216 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002217
2218 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002219 *pos++ = len;
2220 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002221 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002222
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002223 if (i < wpa_s->extended_capa_len) {
2224 *pos &= ~wpa_s->extended_capa_mask[i];
2225 *pos |= wpa_s->extended_capa[i];
2226 }
2227 }
2228
2229 while (len > 0 && buf[1 + len] == 0) {
2230 len--;
2231 buf[1] = len;
2232 }
2233 if (len == 0)
2234 return 0;
2235
2236 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002237}
2238
2239
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002240static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2241 struct wpa_bss *test_bss)
2242{
2243 struct wpa_bss *bss;
2244
2245 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2246 if (bss == test_bss)
2247 return 1;
2248 }
2249
2250 return 0;
2251}
2252
2253
2254static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2255 struct wpa_ssid *test_ssid)
2256{
2257 struct wpa_ssid *ssid;
2258
2259 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2260 if (ssid == test_ssid)
2261 return 1;
2262 }
2263
2264 return 0;
2265}
2266
2267
2268int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2269 struct wpa_ssid *test_ssid)
2270{
2271 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2272 return 0;
2273
2274 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2275}
2276
2277
2278void wpas_connect_work_free(struct wpa_connect_work *cwork)
2279{
2280 if (cwork == NULL)
2281 return;
2282 os_free(cwork);
2283}
2284
2285
2286void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2287{
2288 struct wpa_connect_work *cwork;
2289 struct wpa_radio_work *work = wpa_s->connect_work;
2290
2291 if (!work)
2292 return;
2293
2294 wpa_s->connect_work = NULL;
2295 cwork = work->ctx;
2296 work->ctx = NULL;
2297 wpas_connect_work_free(cwork);
2298 radio_work_done(work);
2299}
2300
2301
Sunil Ravi77d572f2023-01-17 23:58:31 +00002302int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2303 enum wpas_mac_addr_style style,
2304 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002305{
2306 struct os_reltime now;
2307 u8 addr[ETH_ALEN];
2308
2309 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002310 /* Random addresses are valid within a given ESS so check
2311 * expiration/value only when continuing to use the same ESS. */
2312 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2313 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2314 /* Pregenerated addresses do not expire but their value
2315 * might have changed, so let's check that. */
2316 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2317 ETH_ALEN) == 0)
2318 return 0;
2319 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2320 wpa_s->last_mac_addr_change.usec != 0) &&
2321 !os_reltime_expired(
2322 &now,
2323 &wpa_s->last_mac_addr_change,
2324 wpa_s->conf->rand_addr_lifetime)) {
2325 wpa_msg(wpa_s, MSG_DEBUG,
2326 "Previously selected random MAC address has not yet expired");
2327 return 0;
2328 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002329 }
2330
2331 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002332 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002333 if (random_mac_addr(addr) < 0)
2334 return -1;
2335 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002336 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002337 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2338 if (random_mac_addr_keep_oui(addr) < 0)
2339 return -1;
2340 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002341 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2342 if (!ssid) {
2343 wpa_msg(wpa_s, MSG_INFO,
2344 "Invalid 'ssid' for address policy 3");
2345 return -1;
2346 }
2347 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2348 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002349 default:
2350 return -1;
2351 }
2352
2353 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2354 wpa_msg(wpa_s, MSG_INFO,
2355 "Failed to set random MAC address");
2356 return -1;
2357 }
2358
2359 os_get_reltime(&wpa_s->last_mac_addr_change);
2360 wpa_s->mac_addr_changed = 1;
2361 wpa_s->last_mac_addr_style = style;
2362
2363 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2364 wpa_msg(wpa_s, MSG_INFO,
2365 "Could not update MAC address information");
2366 return -1;
2367 }
2368
2369 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2370 MAC2STR(addr));
2371
Sunil Ravi77d572f2023-01-17 23:58:31 +00002372 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002373}
2374
2375
2376int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2377{
2378 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2379 !wpa_s->conf->preassoc_mac_addr)
2380 return 0;
2381
Sunil Ravi77d572f2023-01-17 23:58:31 +00002382 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2383 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002384}
2385
2386
Sunil Ravi036cec52023-03-29 11:35:17 -07002387void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2388 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002389{
2390#ifdef CONFIG_SAE
2391 int *groups = conf->sae_groups;
2392 int default_groups[] = { 19, 20, 21, 0 };
2393 const char *password;
2394
2395 if (!groups || groups[0] <= 0)
2396 groups = default_groups;
2397
2398 password = ssid->sae_password;
2399 if (!password)
2400 password = ssid->passphrase;
2401
Hai Shalom899fcc72020-10-19 14:38:18 -07002402 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002403 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002404 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002405 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002406 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002407 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002408 /* PT derivation not needed */
2409 sae_deinit_pt(ssid->pt);
2410 ssid->pt = NULL;
2411 return;
2412 }
2413
2414 if (ssid->pt)
2415 return; /* PT already derived */
2416 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2417 (const u8 *) password, os_strlen(password),
2418 ssid->sae_password_id);
2419#endif /* CONFIG_SAE */
2420}
2421
2422
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002423static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2424{
2425#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2426 os_free(wpa_s->sme.sae_rejected_groups);
2427 wpa_s->sme.sae_rejected_groups = NULL;
2428#ifdef CONFIG_TESTING_OPTIONS
2429 if (wpa_s->extra_sae_rejected_groups) {
2430 int i, *groups = wpa_s->extra_sae_rejected_groups;
2431
2432 for (i = 0; groups[i]; i++) {
2433 wpa_printf(MSG_DEBUG,
2434 "TESTING: Indicate rejection of an extra SAE group %d",
2435 groups[i]);
2436 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2437 groups[i]);
2438 }
2439 }
2440#endif /* CONFIG_TESTING_OPTIONS */
2441#endif /* CONFIG_SAE && CONFIG_SME */
2442}
2443
2444
Hai Shalom60840252021-02-19 19:02:11 -08002445int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2446{
2447 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2448 wpa_msg(wpa_s, MSG_INFO,
2449 "Could not restore permanent MAC address");
2450 return -1;
2451 }
2452 wpa_s->mac_addr_changed = 0;
2453 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2454 wpa_msg(wpa_s, MSG_INFO,
2455 "Could not update MAC address information");
2456 return -1;
2457 }
2458 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2459 return 0;
2460}
2461
2462
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002463static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2464
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465/**
2466 * wpa_supplicant_associate - Request association
2467 * @wpa_s: Pointer to wpa_supplicant data
2468 * @bss: Scan results for the selected BSS, or %NULL if not available
2469 * @ssid: Configuration data for the selected network
2470 *
2471 * This function is used to request %wpa_supplicant to associate with a BSS.
2472 */
2473void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2474 struct wpa_bss *bss, struct wpa_ssid *ssid)
2475{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002476 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002477 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002478
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002479 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002480 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002481
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002482 /*
2483 * If we are starting a new connection, any previously pending EAPOL
2484 * RX cannot be valid anymore.
2485 */
2486 wpabuf_free(wpa_s->pending_eapol_rx);
2487 wpa_s->pending_eapol_rx = NULL;
2488
Sunil Ravi77d572f2023-01-17 23:58:31 +00002489 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002490 rand_style = wpa_s->conf->mac_addr;
2491 else
2492 rand_style = ssid->mac_addr;
2493
Sunil Ravia04bd252022-05-02 22:54:18 -07002494 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002495 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002496 wmm_ac_clear_saved_tspecs(wpa_s);
2497 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002498 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002499#ifdef CONFIG_TESTING_OPTIONS
2500 wpa_s->testing_resend_assoc = 0;
2501#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002502
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002503 if (wpa_s->last_ssid == ssid) {
2504 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002505 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002506 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2507 wmm_ac_save_tspecs(wpa_s);
2508 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002509 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2510 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002511 }
Hai Shalomc3565922019-10-28 11:58:20 -07002512 } else {
2513#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002514 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002515#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002516 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002517#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002518 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002519#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002520
Sunil Ravi77d572f2023-01-17 23:58:31 +00002521 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2522 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2523
2524 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002525 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002526 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2527 status > 0) /* MAC changed */
2528 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2529 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2530 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002531 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002532 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002533 }
2534 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535
2536#ifdef CONFIG_IBSS_RSN
2537 ibss_rsn_deinit(wpa_s->ibss_rsn);
2538 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002539#else /* CONFIG_IBSS_RSN */
2540 if (ssid->mode == WPAS_MODE_IBSS &&
2541 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2542 wpa_msg(wpa_s, MSG_INFO,
2543 "IBSS RSN not supported in the build");
2544 return;
2545 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546#endif /* CONFIG_IBSS_RSN */
2547
2548 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2549 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2550#ifdef CONFIG_AP
2551 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2552 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2553 "mode");
2554 return;
2555 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002556 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2557 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302558 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2559 ssid->mode == WPAS_MODE_P2P_GO) {
2560 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002561 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302562 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002563 return;
2564 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 wpa_s->current_bss = bss;
2566#else /* CONFIG_AP */
2567 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2568 "the build");
2569#endif /* CONFIG_AP */
2570 return;
2571 }
2572
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002573 if (ssid->mode == WPAS_MODE_MESH) {
2574#ifdef CONFIG_MESH
2575 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2576 wpa_msg(wpa_s, MSG_INFO,
2577 "Driver does not support mesh mode");
2578 return;
2579 }
2580 if (bss)
2581 ssid->frequency = bss->freq;
2582 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002583 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002584 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2585 return;
2586 }
2587 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002588#else /* CONFIG_MESH */
2589 wpa_msg(wpa_s, MSG_ERROR,
2590 "mesh mode support not included in the build");
2591#endif /* CONFIG_MESH */
2592 return;
2593 }
2594
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002595 /*
2596 * Set WPA state machine configuration to match the selected network now
2597 * so that the information is available before wpas_start_assoc_cb()
2598 * gets called. This is needed at least for RSN pre-authentication where
2599 * candidate APs are added to a list based on scan result processing
2600 * before completion of the first association.
2601 */
2602 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2603
2604#ifdef CONFIG_DPP
2605 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2606 return;
2607#endif /* CONFIG_DPP */
2608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609#ifdef CONFIG_TDLS
2610 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002611 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612#endif /* CONFIG_TDLS */
2613
Hai Shalomc3565922019-10-28 11:58:20 -07002614#ifdef CONFIG_MBO
2615 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2616#endif /* CONFIG_MBO */
2617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002619 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 sme_authenticate(wpa_s, bss, ssid);
2621 return;
2622 }
2623
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002624 if (wpa_s->connect_work) {
2625 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2626 return;
2627 }
2628
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002629 if (radio_work_pending(wpa_s, "connect")) {
2630 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2631 return;
2632 }
2633
Dmitry Shmidt29333592017-01-09 12:27:11 -08002634#ifdef CONFIG_SME
2635 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2636 /* Clear possibly set auth_alg, if any, from last attempt. */
2637 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2638 }
2639#endif /* CONFIG_SME */
2640
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002641 wpas_abort_ongoing_scan(wpa_s);
2642
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002643 cwork = os_zalloc(sizeof(*cwork));
2644 if (cwork == NULL)
2645 return;
2646
2647 cwork->bss = bss;
2648 cwork->ssid = ssid;
2649
2650 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2651 wpas_start_assoc_cb, cwork) < 0) {
2652 os_free(cwork);
2653 }
2654}
2655
2656
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002657static int bss_is_ibss(struct wpa_bss *bss)
2658{
2659 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2660 IEEE80211_CAP_IBSS;
2661}
2662
2663
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002664static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2665 const struct wpa_ssid *ssid)
2666{
2667 enum hostapd_hw_mode hw_mode;
2668 struct hostapd_hw_modes *mode = NULL;
2669 u8 channel;
2670 int i;
2671
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002672 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2673 if (hw_mode == NUM_HOSTAPD_MODES)
2674 return 0;
2675 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2676 if (wpa_s->hw.modes[i].mode == hw_mode) {
2677 mode = &wpa_s->hw.modes[i];
2678 break;
2679 }
2680 }
2681
2682 if (!mode)
2683 return 0;
2684
2685 return mode->vht_capab != 0;
2686}
2687
2688
Hai Shalomc1a21442022-02-04 13:43:00 -08002689static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2690{
2691 int i;
2692
2693 for (i = channel; i < channel + 16; i += 4) {
2694 struct hostapd_channel_data *chan;
2695
2696 chan = hw_get_channel_chan(mode, i, NULL);
2697 if (!chan ||
2698 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2699 return false;
2700 }
2701
2702 return true;
2703}
2704
2705
Sunil Ravi036cec52023-03-29 11:35:17 -07002706static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2707 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002708{
Sunil Ravi036cec52023-03-29 11:35:17 -07002709 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002710
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002711 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2712 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2713
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002714 if (!bss_is_ibss(bss))
2715 continue;
2716
2717 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002718 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2719 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002720 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002721 return NULL;
2722}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002723
Sunil Ravi036cec52023-03-29 11:35:17 -07002724
2725static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2726 const struct wpa_ssid *ssid,
2727 struct hostapd_hw_modes *mode)
2728{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002729 /* For IBSS check HT_IBSS flag */
2730 if (ssid->mode == WPAS_MODE_IBSS &&
2731 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002732 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002733
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002734 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2735 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2736 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2737 wpa_printf(MSG_DEBUG,
2738 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002739 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002740 }
2741
Sunil Ravi036cec52023-03-29 11:35:17 -07002742 if (!ht_supported(mode))
2743 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002744
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002745#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002746 if (ssid->disable_ht)
2747 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002748#endif /* CONFIG_HT_OVERRIDES */
2749
Sunil Ravi036cec52023-03-29 11:35:17 -07002750 return true;
2751}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002752
Sunil Ravi036cec52023-03-29 11:35:17 -07002753
2754static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2755 const struct wpa_ssid *ssid,
2756 struct hostapd_hw_modes *mode)
2757{
2758 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2759 return false;
2760
2761 if (!drv_supports_vht(wpa_s, ssid))
2762 return false;
2763
2764 /* For IBSS check VHT_IBSS flag */
2765 if (ssid->mode == WPAS_MODE_IBSS &&
2766 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2767 return false;
2768
2769 if (!vht_supported(mode))
2770 return false;
2771
2772#ifdef CONFIG_VHT_OVERRIDES
2773 if (ssid->disable_vht)
2774 return false;
2775#endif /* CONFIG_VHT_OVERRIDES */
2776
2777 return true;
2778}
2779
2780
2781static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2782 const struct wpa_ssid *ssid,
2783 const struct hostapd_hw_modes *mode,
2784 int ieee80211_mode)
2785{
Hai Shalomfdcde762020-04-02 11:19:20 -07002786#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002787 if (ssid->disable_he)
2788 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002789#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002790
Sunil Ravi036cec52023-03-29 11:35:17 -07002791 switch (mode->mode) {
2792 case HOSTAPD_MODE_IEEE80211G:
2793 case HOSTAPD_MODE_IEEE80211B:
2794 case HOSTAPD_MODE_IEEE80211A:
2795 return mode->he_capab[ieee80211_mode].he_supported;
2796 default:
2797 return false;
2798 }
2799}
2800
2801
2802static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2803 const struct wpa_ssid *ssid,
2804 const struct hostapd_hw_modes *mode,
2805 int ieee80211_mode)
2806{
2807 if (ssid->disable_eht)
2808 return false;
2809
2810 switch(mode->mode) {
2811 case HOSTAPD_MODE_IEEE80211G:
2812 case HOSTAPD_MODE_IEEE80211B:
2813 case HOSTAPD_MODE_IEEE80211A:
2814 return mode->eht_capab[ieee80211_mode].eht_supported;
2815 default:
2816 return false;
2817 }
2818}
2819
2820
2821static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2822 const struct wpa_ssid *ssid,
2823 struct hostapd_hw_modes *mode,
2824 struct hostapd_freq_params *freq,
2825 int obss_scan) {
2826 int chan_idx;
2827 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2828 int i, res;
2829 unsigned int j;
2830 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002831 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2832 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002833 };
2834 int ht40 = -1;
2835
2836 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002837 return;
2838
2839 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2840 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002841 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002842 break;
2843 pri_chan = NULL;
2844 }
2845 if (!pri_chan)
2846 return;
2847
2848 /* Check primary channel flags */
2849 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2850 return;
2851
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002852#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002853 if (ssid->disable_ht40)
2854 return;
2855#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002856
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002857 /* Check/setup HT40+/HT40- */
2858 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002859 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002860 ht40 = 1;
2861 break;
2862 }
2863 }
2864
2865 /* Find secondary channel */
2866 for (i = 0; i < mode->num_channels; i++) {
2867 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002868 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002869 break;
2870 sec_chan = NULL;
2871 }
2872 if (!sec_chan)
2873 return;
2874
2875 /* Check secondary channel flags */
2876 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2877 return;
2878
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002879 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002880 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2881 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002882 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002883 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2884 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002885 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002886 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002887
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002888 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002889 struct wpa_scan_results *scan_res;
2890
2891 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2892 if (scan_res == NULL) {
2893 /* Back to HT20 */
2894 freq->sec_channel_offset = 0;
2895 return;
2896 }
2897
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002898 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002899 switch (res) {
2900 case 0:
2901 /* Back to HT20 */
2902 freq->sec_channel_offset = 0;
2903 break;
2904 case 1:
2905 /* Configuration allowed */
2906 break;
2907 case 2:
2908 /* Switch pri/sec channels */
2909 freq->freq = hw_get_freq(mode, sec_chan->chan);
2910 freq->sec_channel_offset = -freq->sec_channel_offset;
2911 freq->channel = sec_chan->chan;
2912 break;
2913 default:
2914 freq->sec_channel_offset = 0;
2915 break;
2916 }
2917
2918 wpa_scan_results_free(scan_res);
2919 }
2920
2921 wpa_printf(MSG_DEBUG,
2922 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2923 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002924}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002925
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002926
Sunil Ravi036cec52023-03-29 11:35:17 -07002927static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2928 const struct wpa_ssid *ssid,
2929 struct hostapd_hw_modes *mode,
2930 struct hostapd_freq_params *freq,
2931 int ieee80211_mode, bool is_6ghz) {
2932 static const int bw80[] = {
2933 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2934 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2935 6515, 6595, 6675, 6755, 6835, 6915, 6995
2936 };
2937 static const int bw160[] = {
2938 5955, 6115, 6275, 6435, 6595, 6755, 6915
2939 };
2940 struct hostapd_freq_params vht_freq;
2941 int i;
2942 unsigned int j, k;
2943 int chwidth, seg0, seg1;
2944 u32 vht_caps = 0;
2945 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002946
Sunil Ravi036cec52023-03-29 11:35:17 -07002947 if (!freq->vht_enabled && !freq->he_enabled)
2948 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002949
Hai Shalomc1a21442022-02-04 13:43:00 -08002950 vht_freq = *freq;
2951
Sunil Ravi036cec52023-03-29 11:35:17 -07002952 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2953 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2954 seg1 = 0;
2955 if (freq->sec_channel_offset == 0) {
2956 seg0 = 0;
2957 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2958 if (freq->ht_enabled && !is_6ghz)
2959 goto skip_80mhz;
2960 }
2961 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2962 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002963
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002964 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002965 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2966 if (freq->freq >= bw80[j] &&
2967 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002968 break;
2969 }
2970
Hai Shalomc1a21442022-02-04 13:43:00 -08002971 if (j == ARRAY_SIZE(bw80) ||
2972 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002973 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002974
Sunil Ravi036cec52023-03-29 11:35:17 -07002975 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002976 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002977 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002978
Sunil8cd6f4d2022-06-28 18:40:46 +00002979 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002980 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002981 seg1 = 0;
2982
Sunil Ravi036cec52023-03-29 11:35:17 -07002983 /* In 160 MHz, the initial four 20 MHz channels were validated
2984 * above. If 160 MHz is supported, check the remaining four 20 MHz
2985 * channels for the total of 160 MHz bandwidth for 6 GHz.
2986 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002987 if ((mode->he_capab[ieee80211_mode].phy_cap[
2988 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002989 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2990 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002991 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2992 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002993 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002994 seg0 = channel + 14;
2995 break;
2996 }
2997 }
2998 }
2999
Sunil8cd6f4d2022-06-28 18:40:46 +00003000 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003001 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003002 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003003 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003004 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003005 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003006
3007 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3008 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003009 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003010
3011 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003012 struct hostapd_channel_data *chan;
3013
3014 chan = hw_get_channel_chan(mode, i, NULL);
3015 if (!chan)
3016 continue;
3017
3018 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3019 HOSTAPD_CHAN_NO_IR |
3020 HOSTAPD_CHAN_RADAR))
3021 continue;
3022
3023 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003024 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003025 if (!is_6ghz)
3026 vht_caps |=
3027 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3028 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003029 }
3030
Sunil8cd6f4d2022-06-28 18:40:46 +00003031 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003032 break;
3033 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003034 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003035 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003036 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003037 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3038 seg0 = 50;
3039 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003040 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003041 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3042 seg0 = 114;
3043 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003044 }
3045
Sunil Ravi036cec52023-03-29 11:35:17 -07003046skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003047 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003048 freq->channel, ssid->enable_edmg,
3049 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003050 freq->vht_enabled, freq->he_enabled,
3051 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003052 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003053 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003054 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003055 &mode->eht_capab[ieee80211_mode]) != 0)
3056 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003057
3058 *freq = vht_freq;
3059
3060 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3061 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003062 return true;
3063}
3064
3065
3066void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3067 const struct wpa_ssid *ssid,
3068 struct hostapd_freq_params *freq)
3069{
3070 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3071 enum hostapd_hw_mode hw_mode;
3072 struct hostapd_hw_modes *mode = NULL;
3073 int i, obss_scan = 1;
3074 u8 channel;
3075 bool is_6ghz;
3076
3077 freq->freq = ssid->frequency;
3078
3079 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3080 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3081
3082 if (bss) {
3083 wpa_printf(MSG_DEBUG,
3084 "IBSS already found in scan results, adjust control freq: %d",
3085 bss->freq);
3086 freq->freq = bss->freq;
3087 obss_scan = 0;
3088 }
3089 }
3090
3091 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3092 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3093 if (wpa_s->hw.modes[i].mode == hw_mode &&
3094 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3095 NULL) != NULL) {
3096 mode = &wpa_s->hw.modes[i];
3097 break;
3098 }
3099 }
3100
3101 if (!mode)
3102 return;
3103
3104 is_6ghz = is_6ghz_freq(freq->freq);
3105
3106 freq->ht_enabled = 0;
3107 freq->vht_enabled = 0;
3108 freq->he_enabled = 0;
3109 freq->eht_enabled = 0;
3110
3111 if (!is_6ghz)
3112 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3113 if (freq->ht_enabled)
3114 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3115 if (freq->vht_enabled || is_6ghz)
3116 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3117 ieee80211_mode);
3118 freq->channel = channel;
3119 /* Setup higher BW only for 5 GHz */
3120 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3121 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3122 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3123 ieee80211_mode, is_6ghz))
3124 freq->he_enabled = freq->vht_enabled = false;
3125 }
3126
3127 if (freq->he_enabled)
3128 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3129 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003130}
3131
3132
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003133#ifdef CONFIG_FILS
3134static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3135 size_t ie_buf_len)
3136{
3137 struct fils_hlp_req *req;
3138 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3139 const u8 *pos;
3140 u8 *buf = ie_buf;
3141
3142 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3143 list) {
3144 rem_len = ie_buf_len - ie_len;
3145 pos = wpabuf_head(req->pkt);
3146 hdr_len = 1 + 2 * ETH_ALEN + 6;
3147 hlp_len = wpabuf_len(req->pkt);
3148
3149 if (rem_len < 2 + hdr_len + hlp_len) {
3150 wpa_printf(MSG_ERROR,
3151 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3152 (unsigned long) rem_len,
3153 (unsigned long) (2 + hdr_len + hlp_len));
3154 break;
3155 }
3156
3157 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3158 /* Element ID */
3159 *buf++ = WLAN_EID_EXTENSION;
3160 /* Length */
3161 *buf++ = len;
3162 /* Element ID Extension */
3163 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3164 /* Destination MAC address */
3165 os_memcpy(buf, req->dst, ETH_ALEN);
3166 buf += ETH_ALEN;
3167 /* Source MAC address */
3168 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3169 buf += ETH_ALEN;
3170 /* LLC/SNAP Header */
3171 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3172 buf += 6;
3173 /* HLP Packet */
3174 os_memcpy(buf, pos, len - hdr_len);
3175 buf += len - hdr_len;
3176 pos += len - hdr_len;
3177
3178 hlp_len -= len - hdr_len;
3179 ie_len += 2 + len;
3180 rem_len -= 2 + len;
3181
3182 while (hlp_len) {
3183 len = (hlp_len > 255) ? 255 : hlp_len;
3184 if (rem_len < 2 + len)
3185 break;
3186 *buf++ = WLAN_EID_FRAGMENT;
3187 *buf++ = len;
3188 os_memcpy(buf, pos, len);
3189 buf += len;
3190 pos += len;
3191
3192 hlp_len -= len;
3193 ie_len += 2 + len;
3194 rem_len -= 2 + len;
3195 }
3196 }
3197
3198 return ie_len;
3199}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003200
3201
3202int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3203{
3204 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3205 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3206 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3207 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3208}
3209
3210
3211int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3212{
3213#ifdef CONFIG_FILS_SK_PFS
3214 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3215 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3216#else /* CONFIG_FILS_SK_PFS */
3217 return 0;
3218#endif /* CONFIG_FILS_SK_PFS */
3219}
3220
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003221#endif /* CONFIG_FILS */
3222
3223
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003224bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3225{
3226 const u8 *wfa_capa;
3227
3228 if (!bss)
3229 return false;
3230
3231 /* Get WFA capability from Beacon or Probe Response frame elements */
3232 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3233 if (!wfa_capa)
3234 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3235 bss, WFA_CAPA_IE_VENDOR_TYPE);
3236
3237 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3238 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3239 /* AP does not enable QM non EHT traffic description policy */
3240 return false;
3241 }
3242
3243 return true;
3244}
3245
3246
Hai Shalomc1a21442022-02-04 13:43:00 -08003247static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3248 struct wpa_bss *bss,
3249 u8 *wpa_ie, size_t wpa_ie_len,
3250 size_t max_wpa_ie_len)
3251{
3252 struct wpabuf *wfa_ie = NULL;
3253 u8 wfa_capa[1];
3254 size_t wfa_ie_len, buf_len;
3255
3256 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3257 if (wpa_s->enable_dscp_policy_capa)
3258 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3259
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003260 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3261 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3262
Hai Shalomc1a21442022-02-04 13:43:00 -08003263 if (!wfa_capa[0])
3264 return wpa_ie_len;
3265
3266 /* Wi-Fi Alliance element */
3267 buf_len = 1 + /* Element ID */
3268 1 + /* Length */
3269 3 + /* OUI */
3270 1 + /* OUI Type */
3271 1 + /* Capabilities Length */
3272 sizeof(wfa_capa); /* Capabilities */
3273 wfa_ie = wpabuf_alloc(buf_len);
3274 if (!wfa_ie)
3275 return wpa_ie_len;
3276
3277 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3278 wpabuf_put_u8(wfa_ie, buf_len - 2);
3279 wpabuf_put_be24(wfa_ie, OUI_WFA);
3280 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3281 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3282 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3283
3284 wfa_ie_len = wpabuf_len(wfa_ie);
3285 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3286 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3287 wfa_ie);
3288 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3289 wfa_ie_len);
3290 wpa_ie_len += wfa_ie_len;
3291 }
3292
3293 wpabuf_free(wfa_ie);
3294 return wpa_ie_len;
3295}
3296
3297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003298static u8 * wpas_populate_assoc_ies(
3299 struct wpa_supplicant *wpa_s,
3300 struct wpa_bss *bss, struct wpa_ssid *ssid,
3301 struct wpa_driver_associate_params *params,
3302 enum wpa_drv_update_connect_params_mask *mask)
3303{
3304 u8 *wpa_ie;
3305 size_t max_wpa_ie_len = 500;
3306 size_t wpa_ie_len;
3307 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003308#ifdef CONFIG_MBO
3309 const u8 *mbo_ie;
3310#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303311#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3312 int pmksa_cached = 0;
3313#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003314#ifdef CONFIG_FILS
3315 const u8 *realm, *username, *rrk;
3316 size_t realm_len, username_len, rrk_len;
3317 u16 next_seq_num;
3318 struct fils_hlp_req *req;
3319
3320 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3321 list) {
3322 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3323 2 + 2 * wpabuf_len(req->pkt) / 255;
3324 }
3325#endif /* CONFIG_FILS */
3326
3327 wpa_ie = os_malloc(max_wpa_ie_len);
3328 if (!wpa_ie) {
3329 wpa_printf(MSG_ERROR,
3330 "Failed to allocate connect IE buffer for %lu bytes",
3331 (unsigned long) max_wpa_ie_len);
3332 return NULL;
3333 }
3334
3335 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3336 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3337 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3338 int try_opportunistic;
3339 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003340 const u8 *addr = bss->bssid;
3341
Sunil Ravi036cec52023-03-29 11:35:17 -07003342 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3343 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3344 !is_zero_ether_addr(bss->mld_addr))
3345 addr = bss->mld_addr;
3346
3347 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3348 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003349 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003350
3351 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3352 wpa_s->conf->okc :
3353 ssid->proactive_key_caching) &&
3354 (ssid->proto & WPA_PROTO_RSN);
3355#ifdef CONFIG_FILS
3356 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3357 cache_id = wpa_bss_get_fils_cache_id(bss);
3358#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003359 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003360 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003361 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003362 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303363#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3364 pmksa_cached = 1;
3365#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003366 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003367 wpa_ie_len = max_wpa_ie_len;
3368 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003369 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003370 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3371 "key management and encryption suites");
3372 os_free(wpa_ie);
3373 return NULL;
3374 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003375#ifdef CONFIG_HS20
3376 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3377 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3378 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3379 wpa_ie_len = max_wpa_ie_len;
3380 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003381 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003382 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3383 "key management and encryption suites");
3384 os_free(wpa_ie);
3385 return NULL;
3386 }
3387#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003388 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3389 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3390 /*
3391 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3392 * use non-WPA since the scan results did not indicate that the
3393 * AP is using WPA or WPA2.
3394 */
3395 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3396 wpa_ie_len = 0;
3397 wpa_s->wpa_proto = 0;
3398 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3399 wpa_ie_len = max_wpa_ie_len;
3400 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003401 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003402 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3403 "key management and encryption suites (no "
3404 "scan results)");
3405 os_free(wpa_ie);
3406 return NULL;
3407 }
3408#ifdef CONFIG_WPS
3409 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3410 struct wpabuf *wps_ie;
3411 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3412 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3413 wpa_ie_len = wpabuf_len(wps_ie);
3414 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3415 } else
3416 wpa_ie_len = 0;
3417 wpabuf_free(wps_ie);
3418 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3419 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3420 params->wps = WPS_MODE_PRIVACY;
3421 else
3422 params->wps = WPS_MODE_OPEN;
3423 wpa_s->wpa_proto = 0;
3424#endif /* CONFIG_WPS */
3425 } else {
3426 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3427 wpa_ie_len = 0;
3428 wpa_s->wpa_proto = 0;
3429 }
3430
3431#ifdef IEEE8021X_EAPOL
3432 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3433 if (ssid->leap) {
3434 if (ssid->non_leap == 0)
3435 algs = WPA_AUTH_ALG_LEAP;
3436 else
3437 algs |= WPA_AUTH_ALG_LEAP;
3438 }
3439 }
3440
3441#ifdef CONFIG_FILS
3442 /* Clear FILS association */
3443 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3444
3445 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3446 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3447 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3448 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003449 &next_seq_num, &rrk, &rrk_len) == 0 &&
3450 (!wpa_s->last_con_fail_realm ||
3451 wpa_s->last_con_fail_realm_len != realm_len ||
3452 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003453 algs = WPA_AUTH_ALG_FILS;
3454 params->fils_erp_username = username;
3455 params->fils_erp_username_len = username_len;
3456 params->fils_erp_realm = realm;
3457 params->fils_erp_realm_len = realm_len;
3458 params->fils_erp_next_seq_num = next_seq_num;
3459 params->fils_erp_rrk = rrk;
3460 params->fils_erp_rrk_len = rrk_len;
3461
3462 if (mask)
3463 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303464 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3465 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3466 pmksa_cached) {
3467 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003468 }
3469#endif /* CONFIG_FILS */
3470#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003471#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003472 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003473 algs = WPA_AUTH_ALG_SAE;
3474#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475
3476 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3477 if (ssid->auth_alg) {
3478 algs = ssid->auth_alg;
3479 wpa_dbg(wpa_s, MSG_DEBUG,
3480 "Overriding auth_alg selection: 0x%x", algs);
3481 }
3482
Hai Shalom5f92bc92019-04-18 11:54:11 -07003483#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303484 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003485 wpa_dbg(wpa_s, MSG_DEBUG,
3486 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3487 algs = WPA_AUTH_ALG_OPEN;
3488 }
3489#endif /* CONFIG_SAE */
3490
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003491#ifdef CONFIG_P2P
3492 if (wpa_s->global->p2p) {
3493 u8 *pos;
3494 size_t len;
3495 int res;
3496 pos = wpa_ie + wpa_ie_len;
3497 len = max_wpa_ie_len - wpa_ie_len;
3498 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3499 ssid->p2p_group);
3500 if (res >= 0)
3501 wpa_ie_len += res;
3502 }
3503
3504 wpa_s->cross_connect_disallowed = 0;
3505 if (bss) {
3506 struct wpabuf *p2p;
3507 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3508 if (p2p) {
3509 wpa_s->cross_connect_disallowed =
3510 p2p_get_cross_connect_disallowed(p2p);
3511 wpabuf_free(p2p);
3512 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3513 "connection",
3514 wpa_s->cross_connect_disallowed ?
3515 "disallows" : "allows");
3516 }
3517 }
3518
3519 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3520#endif /* CONFIG_P2P */
3521
3522 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003523 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003524 wpa_ie + wpa_ie_len,
3525 max_wpa_ie_len -
3526 wpa_ie_len);
3527 }
3528
3529 /*
3530 * Workaround: Add Extended Capabilities element only if the AP
3531 * included this element in Beacon/Probe Response frames. Some older
3532 * APs seem to have interoperability issues if this element is
3533 * included, so while the standard may require us to include the
3534 * element in all cases, it is justifiable to skip it to avoid
3535 * interoperability issues.
3536 */
3537 if (ssid->p2p_group)
3538 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3539 else
3540 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3541
3542 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3543 u8 ext_capab[18];
3544 int ext_capab_len;
3545 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003546 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003547 if (ext_capab_len > 0 &&
3548 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3549 u8 *pos = wpa_ie;
3550 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3551 pos += 2 + pos[1];
3552 os_memmove(pos + ext_capab_len, pos,
3553 wpa_ie_len - (pos - wpa_ie));
3554 wpa_ie_len += ext_capab_len;
3555 os_memcpy(pos, ext_capab, ext_capab_len);
3556 }
3557 }
3558
3559#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003560 if (is_hs20_network(wpa_s, ssid, bss)
3561#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3562 && is_hs20_config(wpa_s)
3563#endif /* ANDROID */
3564 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003565 struct wpabuf *hs20;
3566
Roshan Pius3a1667e2018-07-03 15:17:14 -07003567 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003568 if (hs20) {
3569 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3570 size_t len;
3571
Hai Shalom74f70d42019-02-11 14:42:39 -08003572 wpas_hs20_add_indication(hs20, pps_mo_id,
3573 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003574 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003575 len = max_wpa_ie_len - wpa_ie_len;
3576 if (wpabuf_len(hs20) <= len) {
3577 os_memcpy(wpa_ie + wpa_ie_len,
3578 wpabuf_head(hs20), wpabuf_len(hs20));
3579 wpa_ie_len += wpabuf_len(hs20);
3580 }
3581 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003582 }
3583 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003584 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003585#endif /* CONFIG_HS20 */
3586
3587 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3588 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3589 size_t len;
3590
3591 len = max_wpa_ie_len - wpa_ie_len;
3592 if (wpabuf_len(buf) <= len) {
3593 os_memcpy(wpa_ie + wpa_ie_len,
3594 wpabuf_head(buf), wpabuf_len(buf));
3595 wpa_ie_len += wpabuf_len(buf);
3596 }
3597 }
3598
3599#ifdef CONFIG_FST
3600 if (wpa_s->fst_ies) {
3601 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3602
3603 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3604 os_memcpy(wpa_ie + wpa_ie_len,
3605 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3606 wpa_ie_len += fst_ies_len;
3607 }
3608 }
3609#endif /* CONFIG_FST */
3610
3611#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003612 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003613 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003614 int len;
3615
3616 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003617 max_wpa_ie_len - wpa_ie_len,
3618 !!mbo_attr_from_mbo_ie(mbo_ie,
3619 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620 if (len >= 0)
3621 wpa_ie_len += len;
3622 }
3623#endif /* CONFIG_MBO */
3624
3625#ifdef CONFIG_FILS
3626 if (algs == WPA_AUTH_ALG_FILS) {
3627 size_t len;
3628
3629 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3630 max_wpa_ie_len - wpa_ie_len);
3631 wpa_ie_len += len;
3632 }
3633#endif /* CONFIG_FILS */
3634
3635#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003636#ifdef CONFIG_TESTING_OPTIONS
3637 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3638 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3639 } else
3640#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003641 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003642 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3643 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003644 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003645 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003646
Roshan Pius3a1667e2018-07-03 15:17:14 -07003647 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003648 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003649 } else if (wpa_s->assoc_status_code ==
3650 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003651 if (wpa_s->last_owe_group == 19)
3652 group = 20;
3653 else if (wpa_s->last_owe_group == 20)
3654 group = 21;
3655 else
3656 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003657 } else {
3658 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003659 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003660
Roshan Pius3a1667e2018-07-03 15:17:14 -07003661 wpa_s->last_owe_group = group;
3662 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003663 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3664 if (owe_ie &&
3665 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3666 os_memcpy(wpa_ie + wpa_ie_len,
3667 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3668 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003669 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003670 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003671 }
3672#endif /* CONFIG_OWE */
3673
Hai Shalom021b0b52019-04-10 11:17:58 -07003674#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003675 if (DPP_VERSION > 1 &&
3676 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003677 ssid->dpp_netaccesskey &&
3678 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003679 struct rsn_pmksa_cache_entry *pmksa;
3680
3681 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3682 if (!pmksa || !pmksa->dpp_pfs)
3683 goto pfs_fail;
3684
Hai Shalom021b0b52019-04-10 11:17:58 -07003685 dpp_pfs_free(wpa_s->dpp_pfs);
3686 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3687 ssid->dpp_netaccesskey_len);
3688 if (!wpa_s->dpp_pfs) {
3689 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3690 /* Try to continue without PFS */
3691 goto pfs_fail;
3692 }
3693 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3694 max_wpa_ie_len - wpa_ie_len) {
3695 os_memcpy(wpa_ie + wpa_ie_len,
3696 wpabuf_head(wpa_s->dpp_pfs->ie),
3697 wpabuf_len(wpa_s->dpp_pfs->ie));
3698 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3699 }
3700 }
3701pfs_fail:
3702#endif /* CONFIG_DPP2 */
3703
Roshan Pius3a1667e2018-07-03 15:17:14 -07003704#ifdef CONFIG_IEEE80211R
3705 /*
3706 * Add MDIE under these conditions: the network profile allows FT,
3707 * the AP supports FT, and the mobility domain ID matches.
3708 */
3709 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3710 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3711
3712 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3713 size_t len = 0;
3714 const u8 *md = mdie + 2;
3715 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3716
3717 if (os_memcmp(md, wpa_md,
3718 MOBILITY_DOMAIN_ID_LEN) == 0) {
3719 /* Add mobility domain IE */
3720 len = wpa_ft_add_mdie(
3721 wpa_s->wpa, wpa_ie + wpa_ie_len,
3722 max_wpa_ie_len - wpa_ie_len, mdie);
3723 wpa_ie_len += len;
3724 }
3725#ifdef CONFIG_SME
3726 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003727 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003728 wpa_dbg(wpa_s, MSG_DEBUG,
3729 "SME: Trying to use FT over-the-air");
3730 algs |= WPA_AUTH_ALG_FT;
3731 }
3732#endif /* CONFIG_SME */
3733 }
3734 }
3735#endif /* CONFIG_IEEE80211R */
3736
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003737#ifdef CONFIG_TESTING_OPTIONS
3738 if (wpa_s->rsnxe_override_assoc &&
3739 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3740 max_wpa_ie_len - wpa_ie_len) {
3741 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3742 os_memcpy(wpa_ie + wpa_ie_len,
3743 wpabuf_head(wpa_s->rsnxe_override_assoc),
3744 wpabuf_len(wpa_s->rsnxe_override_assoc));
3745 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3746 } else
3747#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003748 if (wpa_s->rsnxe_len > 0 &&
3749 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3750 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3751 wpa_ie_len += wpa_s->rsnxe_len;
3752 }
3753
Hai Shalomc1a21442022-02-04 13:43:00 -08003754#ifdef CONFIG_TESTING_OPTIONS
3755 if (wpa_s->disable_mscs_support)
3756 goto mscs_end;
3757#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003758 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3759 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003760 struct wpabuf *mscs_ie;
3761 size_t mscs_ie_len, buf_len;
3762
Hai Shalom899fcc72020-10-19 14:38:18 -07003763 buf_len = 3 + /* MSCS descriptor IE header */
3764 1 + /* Request type */
3765 2 + /* User priority control */
3766 4 + /* Stream timeout */
3767 3 + /* TCLAS Mask IE header */
3768 wpa_s->robust_av.frame_classifier_len;
3769 mscs_ie = wpabuf_alloc(buf_len);
3770 if (!mscs_ie) {
3771 wpa_printf(MSG_INFO,
3772 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003773 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003774 }
3775
3776 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3777 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3778 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3779 mscs_ie_len = wpabuf_len(mscs_ie);
3780 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3781 mscs_ie_len);
3782 wpa_ie_len += mscs_ie_len;
3783 }
3784
3785 wpabuf_free(mscs_ie);
3786 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003787mscs_end:
3788
3789 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3790 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003791
Hai Shalom74f70d42019-02-11 14:42:39 -08003792 if (ssid->multi_ap_backhaul_sta) {
3793 size_t multi_ap_ie_len;
3794
3795 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3796 max_wpa_ie_len - wpa_ie_len,
3797 MULTI_AP_BACKHAUL_STA);
3798 if (multi_ap_ie_len == 0) {
3799 wpa_printf(MSG_ERROR,
3800 "Multi-AP: Failed to build Multi-AP IE");
3801 os_free(wpa_ie);
3802 return NULL;
3803 }
3804 wpa_ie_len += multi_ap_ie_len;
3805 }
3806
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003807 params->wpa_ie = wpa_ie;
3808 params->wpa_ie_len = wpa_ie_len;
3809 params->auth_alg = algs;
3810 if (mask)
3811 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3812
3813 return wpa_ie;
3814}
3815
3816
Hai Shalomc3565922019-10-28 11:58:20 -07003817#ifdef CONFIG_OWE
3818static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3819{
3820 struct wpa_driver_associate_params params;
3821 u8 *wpa_ie;
3822
3823 os_memset(&params, 0, sizeof(params));
3824 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3825 wpa_s->current_ssid, &params, NULL);
3826 if (!wpa_ie)
3827 return;
3828
3829 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3830 os_free(wpa_ie);
3831}
3832#endif /* CONFIG_OWE */
3833
3834
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003835#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3836static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3837{
3838 struct wpa_driver_associate_params params;
3839 enum wpa_drv_update_connect_params_mask mask = 0;
3840 u8 *wpa_ie;
3841
3842 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3843 return; /* nothing to do */
3844
3845 os_memset(&params, 0, sizeof(params));
3846 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3847 wpa_s->current_ssid, &params, &mask);
3848 if (!wpa_ie)
3849 return;
3850
Hai Shalomc1a21442022-02-04 13:43:00 -08003851 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3852 wpa_s->auth_alg = params.auth_alg;
3853 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003854 }
3855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003856 os_free(wpa_ie);
3857}
3858#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3859
3860
Hai Shalomc3565922019-10-28 11:58:20 -07003861static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3862{
3863 if (!edmg_ie || edmg_ie[1] < 6)
3864 return 0;
3865 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3866}
3867
3868
3869static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3870{
3871 if (!edmg_ie || edmg_ie[1] < 6)
3872 return 0;
3873 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3874}
3875
3876
3877/* Returns the intersection of two EDMG configurations.
3878 * Note: The current implementation is limited to CB2 only (CB1 included),
3879 * i.e., the implementation supports up to 2 contiguous channels.
3880 * For supporting non-contiguous (aggregated) channels and for supporting
3881 * CB3 and above, this function will need to be extended.
3882 */
3883static struct ieee80211_edmg_config
3884get_edmg_intersection(struct ieee80211_edmg_config a,
3885 struct ieee80211_edmg_config b,
3886 u8 primary_channel)
3887{
3888 struct ieee80211_edmg_config result;
3889 int i, contiguous = 0;
3890 int max_contiguous = 0;
3891
3892 result.channels = b.channels & a.channels;
3893 if (!result.channels) {
3894 wpa_printf(MSG_DEBUG,
3895 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3896 a.channels, b.channels);
3897 goto fail;
3898 }
3899
3900 if (!(result.channels & BIT(primary_channel - 1))) {
3901 wpa_printf(MSG_DEBUG,
3902 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3903 primary_channel, result.channels);
3904 goto fail;
3905 }
3906
3907 /* Find max contiguous channels */
3908 for (i = 0; i < 6; i++) {
3909 if (result.channels & BIT(i))
3910 contiguous++;
3911 else
3912 contiguous = 0;
3913
3914 if (contiguous > max_contiguous)
3915 max_contiguous = contiguous;
3916 }
3917
3918 /* Assuming AP and STA supports ONLY contiguous channels,
3919 * bw configuration can have value between 4-7.
3920 */
3921 if ((b.bw_config < a.bw_config))
3922 result.bw_config = b.bw_config;
3923 else
3924 result.bw_config = a.bw_config;
3925
3926 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3927 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3928 wpa_printf(MSG_DEBUG,
3929 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3930 max_contiguous);
3931 goto fail;
3932 }
3933
3934 return result;
3935
3936fail:
3937 result.channels = 0;
3938 result.bw_config = 0;
3939 return result;
3940}
3941
3942
3943static struct ieee80211_edmg_config
3944get_supported_edmg(struct wpa_supplicant *wpa_s,
3945 struct hostapd_freq_params *freq,
3946 struct ieee80211_edmg_config request_edmg)
3947{
3948 enum hostapd_hw_mode hw_mode;
3949 struct hostapd_hw_modes *mode = NULL;
3950 u8 primary_channel;
3951
3952 if (!wpa_s->hw.modes)
3953 goto fail;
3954
3955 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3956 if (hw_mode == NUM_HOSTAPD_MODES)
3957 goto fail;
3958
Hai Shalom60840252021-02-19 19:02:11 -08003959 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003960 if (!mode)
3961 goto fail;
3962
3963 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3964
3965fail:
3966 request_edmg.channels = 0;
3967 request_edmg.bw_config = 0;
3968 return request_edmg;
3969}
3970
3971
Hai Shalom021b0b52019-04-10 11:17:58 -07003972#ifdef CONFIG_MBO
3973void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3974{
3975 struct wpa_driver_associate_params params;
3976 u8 *wpa_ie;
3977
3978 /*
3979 * Update MBO connect params only in case of change of MBO attributes
3980 * when connected, if the AP support MBO.
3981 */
3982
3983 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3984 !wpa_s->current_bss ||
3985 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3986 return;
3987
3988 os_memset(&params, 0, sizeof(params));
3989 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3990 wpa_s->current_ssid, &params, NULL);
3991 if (!wpa_ie)
3992 return;
3993
3994 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3995 os_free(wpa_ie);
3996}
3997#endif /* CONFIG_MBO */
3998
3999
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004000static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4001{
4002 struct wpa_connect_work *cwork = work->ctx;
4003 struct wpa_bss *bss = cwork->bss;
4004 struct wpa_ssid *ssid = cwork->ssid;
4005 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004006 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004007 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004008 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004009 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004010 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004011 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004012#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004013 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004014#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004015 int assoc_failed = 0;
4016 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004017 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004018#ifdef CONFIG_HT_OVERRIDES
4019 struct ieee80211_ht_capabilities htcaps;
4020 struct ieee80211_ht_capabilities htcaps_mask;
4021#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004022#ifdef CONFIG_VHT_OVERRIDES
4023 struct ieee80211_vht_capabilities vhtcaps;
4024 struct ieee80211_vht_capabilities vhtcaps_mask;
4025#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004026
Hai Shalomc1a21442022-02-04 13:43:00 -08004027 wpa_s->roam_in_progress = false;
4028#ifdef CONFIG_WNM
4029 wpa_s->bss_trans_mgmt_in_progress = false;
4030#endif /* CONFIG_WNM */
4031
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004032 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004033 if (work->started) {
4034 wpa_s->connect_work = NULL;
4035
4036 /* cancel possible auth. timeout */
4037 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4038 NULL);
4039 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004040 wpas_connect_work_free(cwork);
4041 return;
4042 }
4043
4044 wpa_s->connect_work = work;
4045
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004046 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4047 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004048 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4049 wpas_connect_work_done(wpa_s);
4050 return;
4051 }
4052
Sunil Ravi640215c2023-06-28 23:08:09 +00004053 /*
4054 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4055 * (for MLO connection) as the previous BSSID for reassociation requests
4056 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4057 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4058 * will be zero.
4059 */
4060 os_memcpy(prev_bssid,
4061 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4062 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004063 os_memset(&params, 0, sizeof(params));
4064 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004065 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004066
4067 /* Starting new association, so clear the possibly used WPA IE from the
4068 * previous association. */
4069 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4070 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4071 wpa_s->rsnxe_len = 0;
4072 wpa_s->mscs_setup_done = false;
4073
4074 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4075 if (!wpa_ie) {
4076 wpas_connect_work_done(wpa_s);
4077 return;
4078 }
4079
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004080 if (bss &&
4081 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004082#ifdef CONFIG_IEEE80211R
4083 const u8 *ie, *md = NULL;
4084#endif /* CONFIG_IEEE80211R */
4085 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4086 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4087 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4088 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4089 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4090 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4091 if (bssid_changed)
4092 wpas_notify_bssid_changed(wpa_s);
4093#ifdef CONFIG_IEEE80211R
4094 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4095 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4096 md = ie + 2;
4097 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4098 if (md) {
4099 /* Prepare for the next transition */
4100 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4101 }
4102#endif /* CONFIG_IEEE80211R */
4103#ifdef CONFIG_WPS
4104 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4105 wpa_s->conf->ap_scan == 2 &&
4106 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4107 /* Use ap_scan==1 style network selection to find the network
4108 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004109 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004110 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111 wpa_s->reassociate = 1;
4112 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004113 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114 return;
4115#endif /* CONFIG_WPS */
4116 } else {
4117 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4118 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004119 if (bss)
4120 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4121 else
4122 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004123 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004124 if (!wpa_s->pno)
4125 wpa_supplicant_cancel_sched_scan(wpa_s);
4126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127 wpa_supplicant_cancel_scan(wpa_s);
4128
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4130 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004131 cipher_pairwise = wpa_s->pairwise_cipher;
4132 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004133 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4135 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4136 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4137 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004138#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 if (wpa_set_wep_keys(wpa_s, ssid)) {
4140 use_crypt = 1;
4141 wep_keys_set = 1;
4142 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004143#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 }
4145 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4146 use_crypt = 0;
4147
4148#ifdef IEEE8021X_EAPOL
4149 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4150 if ((ssid->eapol_flags &
4151 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4152 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4153 !wep_keys_set) {
4154 use_crypt = 0;
4155 } else {
4156 /* Assume that dynamic WEP-104 keys will be used and
4157 * set cipher suites in order for drivers to expect
4158 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004159 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 }
4161 }
4162#endif /* IEEE8021X_EAPOL */
4163
4164 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4165 /* Set the key before (and later after) association */
4166 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4167 }
4168
Sunil8cd6f4d2022-06-28 18:40:46 +00004169 /* Set current_ssid before changing state to ASSOCIATING, so that the
4170 * selected SSID is available to wpas_notify_state_changed(). */
4171 old_ssid = wpa_s->current_ssid;
4172 wpa_s->current_ssid = ssid;
4173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004174 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4175 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176 params.ssid = bss->ssid;
4177 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004178 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4179 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004180 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4181 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004182 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004183 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004184 ssid->bssid_set,
4185 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004186 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004187 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004188 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004189 params.bssid_hint = bss->bssid;
4190 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004191 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004192 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004193 if (ssid->bssid_hint_set)
4194 params.bssid_hint = ssid->bssid_hint;
4195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196 params.ssid = ssid->ssid;
4197 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004198 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004200
4201 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4202 wpa_s->conf->ap_scan == 2) {
4203 params.bssid = ssid->bssid;
4204 params.fixed_bssid = 1;
4205 }
4206
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004207 /* Initial frequency for IBSS/mesh */
4208 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004209 ssid->frequency > 0 && params.freq.freq == 0)
4210 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004211
4212 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004213 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004214 if (ssid->beacon_int)
4215 params.beacon_int = ssid->beacon_int;
4216 else
4217 params.beacon_int = wpa_s->conf->beacon_int;
4218 }
4219
Hai Shalomc3565922019-10-28 11:58:20 -07004220 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004221 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4222 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004223 else
4224 edmg_ie_oper = NULL;
4225
4226 if (edmg_ie_oper) {
4227 params.freq.edmg.channels =
4228 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4229 params.freq.edmg.bw_config =
4230 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4231 wpa_printf(MSG_DEBUG,
4232 "AP supports EDMG channels 0x%x, bw_config %d",
4233 params.freq.edmg.channels,
4234 params.freq.edmg.bw_config);
4235
4236 /* User may ask for specific EDMG channel for EDMG connection
4237 * (must be supported by AP)
4238 */
4239 if (ssid->edmg_channel) {
4240 struct ieee80211_edmg_config configured_edmg;
4241 enum hostapd_hw_mode hw_mode;
4242 u8 primary_channel;
4243
4244 hw_mode = ieee80211_freq_to_chan(bss->freq,
4245 &primary_channel);
4246 if (hw_mode == NUM_HOSTAPD_MODES)
4247 goto edmg_fail;
4248
4249 hostapd_encode_edmg_chan(ssid->enable_edmg,
4250 ssid->edmg_channel,
4251 primary_channel,
4252 &configured_edmg);
4253
4254 if (ieee802_edmg_is_allowed(params.freq.edmg,
4255 configured_edmg)) {
4256 params.freq.edmg = configured_edmg;
4257 wpa_printf(MSG_DEBUG,
4258 "Use EDMG channel %d for connection",
4259 ssid->edmg_channel);
4260 } else {
4261 edmg_fail:
4262 params.freq.edmg.channels = 0;
4263 params.freq.edmg.bw_config = 0;
4264 wpa_printf(MSG_WARNING,
4265 "EDMG channel %d not supported by AP, fallback to DMG",
4266 ssid->edmg_channel);
4267 }
4268 }
4269
4270 if (params.freq.edmg.channels) {
4271 wpa_printf(MSG_DEBUG,
4272 "EDMG before: channels 0x%x, bw_config %d",
4273 params.freq.edmg.channels,
4274 params.freq.edmg.bw_config);
4275 params.freq.edmg = get_supported_edmg(wpa_s,
4276 &params.freq,
4277 params.freq.edmg);
4278 wpa_printf(MSG_DEBUG,
4279 "EDMG after: channels 0x%x, bw_config %d",
4280 params.freq.edmg.channels,
4281 params.freq.edmg.bw_config);
4282 }
4283 }
4284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 params.pairwise_suite = cipher_pairwise;
4286 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004287 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004288 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004289 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004290 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004291 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004293 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004294#ifdef CONFIG_WEP
4295 {
4296 int i;
4297
4298 for (i = 0; i < NUM_WEP_KEYS; i++) {
4299 if (ssid->wep_key_len[i])
4300 params.wep_key[i] = ssid->wep_key[i];
4301 params.wep_key_len[i] = ssid->wep_key_len[i];
4302 }
4303 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004305#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004306
Hai Shalom74f70d42019-02-11 14:42:39 -08004307 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004308#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004309 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4310 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304311#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004312 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4313 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4314 (params.allowed_key_mgmts &
4315 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004316#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004318 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4319 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004320 }
4321
Hai Shalom74f70d42019-02-11 14:42:39 -08004322 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4323 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4324 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4325 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004326 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4327 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004328 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004329
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004330 if (wpa_s->conf->key_mgmt_offload) {
4331 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4332 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004333 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004334 params.key_mgmt_suite ==
4335 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4336 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004337 params.req_key_mgmt_offload =
4338 ssid->proactive_key_caching < 0 ?
4339 wpa_s->conf->okc : ssid->proactive_key_caching;
4340 else
4341 params.req_key_mgmt_offload = 1;
4342
Winnie Chen4138eec2022-11-10 16:32:53 +08004343#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004344 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004345 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4346 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004347#else
4348 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4349 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004350#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004351 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4352 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004353 }
4354
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004355 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4356 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4357 params.auth_alg = WPA_AUTH_ALG_SAE;
4358 if (ssid->sae_password) {
4359 params.sae_password = ssid->sae_password;
4360 params.sae_password_id = ssid->sae_password_id;
4361 } else if (ssid->passphrase) {
4362 params.passphrase = ssid->passphrase;
4363 }
4364 }
4365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004366 params.drop_unencrypted = use_crypt;
4367
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004368 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004369 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004370 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4371 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004372 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4373 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004374 ie.capabilities &
4375 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4376 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4377 "MFP: require MFP");
4378 params.mgmt_frame_protection =
4379 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004380#ifdef CONFIG_OWE
4381 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4382 !ssid->owe_only) {
4383 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4384#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004385 }
4386 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004387
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004388 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004389
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004390 if (wpa_s->p2pdev->set_sta_uapsd)
4391 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392 else
4393 params.uapsd = -1;
4394
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004395#ifdef CONFIG_HT_OVERRIDES
4396 os_memset(&htcaps, 0, sizeof(htcaps));
4397 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4398 params.htcaps = (u8 *) &htcaps;
4399 params.htcaps_mask = (u8 *) &htcaps_mask;
4400 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4401#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004402#ifdef CONFIG_VHT_OVERRIDES
4403 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4404 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4405 params.vhtcaps = &vhtcaps;
4406 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004407 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004408#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004409#ifdef CONFIG_HE_OVERRIDES
4410 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4411#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004412 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004413
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004414#ifdef CONFIG_P2P
4415 /*
4416 * If multi-channel concurrency is not supported, check for any
4417 * frequency conflict. In case of any frequency conflict, remove the
4418 * least prioritized connection.
4419 */
4420 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004421 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004422 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004423 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004424 wpa_printf(MSG_DEBUG,
4425 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004426 freq, params.freq.freq);
4427 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004428 wpa_s, params.freq.freq, ssid) < 0) {
4429 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004430 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004431 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004432 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004433 }
4434 }
4435#endif /* CONFIG_P2P */
4436
Dmitry Shmidte4663042016-04-04 10:07:49 -07004437 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004438 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004439 params.prev_bssid = prev_bssid;
4440
Hai Shalom60840252021-02-19 19:02:11 -08004441#ifdef CONFIG_SAE
4442 params.sae_pwe = wpa_s->conf->sae_pwe;
4443#endif /* CONFIG_SAE */
4444
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004445 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004446 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004447 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004448 if (ret < 0) {
4449 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4450 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004451 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 /*
4453 * The driver is known to mean what is saying, so we
4454 * can stop right here; the association will not
4455 * succeed.
4456 */
4457 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004458 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004459 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004460 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4462 return;
4463 }
4464 /* try to continue anyway; new association will be tried again
4465 * after timeout */
4466 assoc_failed = 1;
4467 }
4468
4469 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4470 /* Set the key after the association just in case association
4471 * cleared the previously configured key. */
4472 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4473 /* No need to timeout authentication since there is no key
4474 * management. */
4475 wpa_supplicant_cancel_auth_timeout(wpa_s);
4476 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4477#ifdef CONFIG_IBSS_RSN
4478 } else if (ssid->mode == WPAS_MODE_IBSS &&
4479 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4480 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4481 /*
4482 * RSN IBSS authentication is per-STA and we can disable the
4483 * per-BSSID authentication.
4484 */
4485 wpa_supplicant_cancel_auth_timeout(wpa_s);
4486#endif /* CONFIG_IBSS_RSN */
4487 } else {
4488 /* Timeout for IEEE 802.11 authentication and association */
4489 int timeout = 60;
4490
4491 if (assoc_failed) {
4492 /* give IBSS a bit more time */
4493 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4494 } else if (wpa_s->conf->ap_scan == 1) {
4495 /* give IBSS a bit more time */
4496 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4497 }
4498 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4499 }
4500
Hai Shalomfdcde762020-04-02 11:19:20 -07004501#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004502 if (wep_keys_set &&
4503 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 /* Set static WEP keys again */
4505 wpa_set_wep_keys(wpa_s, ssid);
4506 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004507#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508
Sunil8cd6f4d2022-06-28 18:40:46 +00004509 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004510 /*
4511 * Do not allow EAP session resumption between different
4512 * network configurations.
4513 */
4514 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4515 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004516
mtk30479d7f89782024-01-24 11:51:43 +08004517 if (!wpas_driver_bss_selection(wpa_s) ||
4518#ifdef CONFIG_P2P
4519 wpa_s->p2p_in_invitation ||
4520#endif /* CONFIG_P2P */
4521 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004522 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004523#ifdef CONFIG_HS20
4524 hs20_configure_frame_filters(wpa_s);
4525#endif /* CONFIG_HS20 */
4526 }
4527
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004528 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4529 wpa_supplicant_initiate_eapol(wpa_s);
4530 if (old_ssid != wpa_s->current_ssid)
4531 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004532 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4533 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004534}
4535
4536
4537static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4538 const u8 *addr)
4539{
4540 struct wpa_ssid *old_ssid;
4541
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004542 wpa_s->ml_connect_probe_ssid = NULL;
4543 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004544 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004545 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004547 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004548 wpa_sm_set_config(wpa_s->wpa, NULL);
4549 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4550 if (old_ssid != wpa_s->current_ssid)
4551 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004552
4553 wpas_scs_deinit(wpa_s);
4554 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004555 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4556}
4557
4558
4559/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4561 * @wpa_s: Pointer to wpa_supplicant data
4562 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4563 *
4564 * This function is used to request %wpa_supplicant to deauthenticate from the
4565 * current AP.
4566 */
4567void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004568 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004569{
4570 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004571 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004572 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004573
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004574 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004575 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004576 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004577 reason_code, reason2str(reason_code),
4578 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004579
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004580 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4581 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4582 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004583 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004584 else if (!is_zero_ether_addr(wpa_s->bssid))
4585 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004586 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4587 /*
4588 * When using driver-based BSS selection, we may not know the
4589 * BSSID with which we are currently trying to associate. We
4590 * need to notify the driver of this disconnection even in such
4591 * a case, so use the all zeros address here.
4592 */
4593 addr = wpa_s->bssid;
4594 zero_addr = 1;
4595 }
4596
Hai Shalom74f70d42019-02-11 14:42:39 -08004597 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4598 wpa_s->enabled_4addr_mode = 0;
4599
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004600#ifdef CONFIG_TDLS
4601 wpa_tdls_teardown_peers(wpa_s->wpa);
4602#endif /* CONFIG_TDLS */
4603
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004604#ifdef CONFIG_MESH
4605 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004606 struct mesh_conf *mconf;
4607
4608 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004609 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4610 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004611 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4612 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004613 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004614 }
4615#endif /* CONFIG_MESH */
4616
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004617 if (addr) {
4618 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004619 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004620 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004621 event.deauth_info.locally_generated = 1;
4622 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004623 if (zero_addr)
4624 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004625 }
4626
4627 wpa_supplicant_clear_connection(wpa_s, addr);
4628}
4629
Hai Shalomfdcde762020-04-02 11:19:20 -07004630
4631void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4632{
4633 wpa_s->own_reconnect_req = 1;
4634 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4635
4636}
4637
4638
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004639static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4640 struct wpa_ssid *ssid)
4641{
4642 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4643 return;
4644
4645 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004646 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004647 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4648 wpas_notify_network_enabled_changed(wpa_s, ssid);
4649
4650 /*
4651 * Try to reassociate since there is no current configuration and a new
4652 * network was made available.
4653 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004654 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004655 wpa_s->reassociate = 1;
4656}
4657
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004658
Roshan Pius950bec92016-07-19 09:49:24 -07004659/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004660 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004661 * @wpa_s: wpa_supplicant structure for a network interface
4662 * Returns: The new network configuration or %NULL if operation failed
4663 *
4664 * This function performs the following operations:
4665 * 1. Adds a new network.
4666 * 2. Send network addition notification.
4667 * 3. Marks the network disabled.
4668 * 4. Set network default parameters.
4669 */
4670struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4671{
4672 struct wpa_ssid *ssid;
4673
4674 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004675 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004676 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004677 wpas_notify_network_added(wpa_s, ssid);
4678 ssid->disabled = 1;
4679 wpa_config_set_network_defaults(ssid);
4680
4681 return ssid;
4682}
4683
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004684
Roshan Pius950bec92016-07-19 09:49:24 -07004685/**
4686 * wpa_supplicant_remove_network - Remove a configured network based on id
4687 * @wpa_s: wpa_supplicant structure for a network interface
4688 * @id: Unique network id to search for
4689 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4690 * could not be removed
4691 *
4692 * This function performs the following operations:
4693 * 1. Removes the network.
4694 * 2. Send network removal notification.
4695 * 3. Update internal state machines.
4696 * 4. Stop any running sched scans.
4697 */
4698int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4699{
Sunil Ravia04bd252022-05-02 22:54:18 -07004700 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004701 int was_disabled;
4702
4703 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004704 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004705 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004706 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004707
Sunil Ravia04bd252022-05-02 22:54:18 -07004708 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004709#ifdef CONFIG_SME
4710 wpa_s->sme.prev_bssid_set = 0;
4711#endif /* CONFIG_SME */
4712 /*
4713 * Invalidate the EAP session cache if the current or
4714 * previously used network is removed.
4715 */
4716 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4717 }
4718
Sunil Ravia04bd252022-05-02 22:54:18 -07004719 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004720 wpa_sm_set_config(wpa_s->wpa, NULL);
4721 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4722
4723 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4724 wpa_s->own_disconnect_req = 1;
4725 wpa_supplicant_deauthenticate(wpa_s,
4726 WLAN_REASON_DEAUTH_LEAVING);
4727 }
4728
4729 was_disabled = ssid->disabled;
4730
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004731 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004732 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004733
4734 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004735 wpa_printf(MSG_DEBUG,
4736 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004737 wpa_supplicant_cancel_sched_scan(wpa_s);
4738 wpa_supplicant_req_scan(wpa_s, 0, 0);
4739 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004740
Roshan Pius950bec92016-07-19 09:49:24 -07004741 return 0;
4742}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004743
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004745/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004746 * wpa_supplicant_remove_all_networks - Remove all configured networks
4747 * @wpa_s: wpa_supplicant structure for a network interface
4748 * Returns: 0 on success (errors are currently ignored)
4749 *
4750 * This function performs the following operations:
4751 * 1. Remove all networks.
4752 * 2. Send network removal notifications.
4753 * 3. Update internal state machines.
4754 * 4. Stop any running sched scans.
4755 */
4756int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4757{
4758 struct wpa_ssid *ssid;
4759
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304760 if (wpa_s->drv_flags2 &
4761 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4762 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4763 wpa_drv_flush_pmkid(wpa_s);
4764
Hai Shalom899fcc72020-10-19 14:38:18 -07004765 if (wpa_s->sched_scanning)
4766 wpa_supplicant_cancel_sched_scan(wpa_s);
4767
4768 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4769 if (wpa_s->current_ssid) {
4770#ifdef CONFIG_SME
4771 wpa_s->sme.prev_bssid_set = 0;
4772#endif /* CONFIG_SME */
4773 wpa_sm_set_config(wpa_s->wpa, NULL);
4774 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4775 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4776 wpa_s->own_disconnect_req = 1;
4777 wpa_supplicant_deauthenticate(
4778 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4779 }
4780 ssid = wpa_s->conf->ssid;
4781 while (ssid) {
4782 struct wpa_ssid *remove_ssid = ssid;
4783 int id;
4784
4785 id = ssid->id;
4786 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004787 wpas_notify_network_removed(wpa_s, remove_ssid);
4788 wpa_config_remove_network(wpa_s->conf, id);
4789 }
4790 return 0;
4791}
4792
4793
4794/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 * wpa_supplicant_enable_network - Mark a configured network as enabled
4796 * @wpa_s: wpa_supplicant structure for a network interface
4797 * @ssid: wpa_ssid structure for a configured network or %NULL
4798 *
4799 * Enables the specified network or all networks if no network specified.
4800 */
4801void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4802 struct wpa_ssid *ssid)
4803{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004805 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4806 wpa_supplicant_enable_one_network(wpa_s, ssid);
4807 } else
4808 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004810 if (wpa_s->reassociate && !wpa_s->disconnected &&
4811 (!wpa_s->current_ssid ||
4812 wpa_s->wpa_state == WPA_DISCONNECTED ||
4813 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004814 if (wpa_s->sched_scanning) {
4815 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4816 "new network to scan filters");
4817 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004818 }
4819
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004820 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4821 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004822 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004823 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824 }
4825}
4826
4827
4828/**
4829 * wpa_supplicant_disable_network - Mark a configured network as disabled
4830 * @wpa_s: wpa_supplicant structure for a network interface
4831 * @ssid: wpa_ssid structure for a configured network or %NULL
4832 *
4833 * Disables the specified network or all networks if no network specified.
4834 */
4835void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4836 struct wpa_ssid *ssid)
4837{
4838 struct wpa_ssid *other_ssid;
4839 int was_disabled;
4840
4841 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004842 if (wpa_s->sched_scanning)
4843 wpa_supplicant_cancel_sched_scan(wpa_s);
4844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004845 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4846 other_ssid = other_ssid->next) {
4847 was_disabled = other_ssid->disabled;
4848 if (was_disabled == 2)
4849 continue; /* do not change persistent P2P group
4850 * data */
4851
4852 other_ssid->disabled = 1;
4853
4854 if (was_disabled != other_ssid->disabled)
4855 wpas_notify_network_enabled_changed(
4856 wpa_s, other_ssid);
4857 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004858 if (wpa_s->current_ssid) {
4859 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4860 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004861 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004862 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004863 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004865 if (ssid == wpa_s->current_ssid) {
4866 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4867 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004868 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004870 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871
4872 was_disabled = ssid->disabled;
4873
4874 ssid->disabled = 1;
4875
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004876 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004877 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004878 if (wpa_s->sched_scanning) {
4879 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4880 "to remove network from filters");
4881 wpa_supplicant_cancel_sched_scan(wpa_s);
4882 wpa_supplicant_req_scan(wpa_s, 0, 0);
4883 }
4884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885 }
4886}
4887
4888
4889/**
4890 * wpa_supplicant_select_network - Attempt association with a network
4891 * @wpa_s: wpa_supplicant structure for a network interface
4892 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4893 */
4894void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4895 struct wpa_ssid *ssid)
4896{
4897
4898 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004899 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004901 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004902 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4903 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004904 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004906 disconnected = 1;
4907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004909 if (ssid)
4910 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4911
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912 /*
4913 * Mark all other networks disabled or mark all networks enabled if no
4914 * network specified.
4915 */
4916 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4917 other_ssid = other_ssid->next) {
4918 int was_disabled = other_ssid->disabled;
4919 if (was_disabled == 2)
4920 continue; /* do not change persistent P2P group data */
4921
4922 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004923 if (was_disabled && !other_ssid->disabled)
4924 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925
4926 if (was_disabled != other_ssid->disabled)
4927 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4928 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004929
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004930 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4931 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004932 /* We are already associated with the selected network */
4933 wpa_printf(MSG_DEBUG, "Already associated with the "
4934 "selected network - do nothing");
4935 return;
4936 }
4937
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004938 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004939 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004940 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004941 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004942 (ssid->mode == WPAS_MODE_MESH ||
4943 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004944
4945 /*
4946 * Don't optimize next scan freqs since a new ESS has been
4947 * selected.
4948 */
4949 os_free(wpa_s->next_scan_freqs);
4950 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004951 } else {
4952 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004953 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004954
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004955 wpa_s->disconnected = 0;
4956 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004957 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004958 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004959 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004960 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004961 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004962 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004963
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004964 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004965 wpa_supplicant_fast_associate(wpa_s) != 1) {
4966 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004967 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004968 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004969 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004970
4971 if (ssid)
4972 wpas_notify_network_selected(wpa_s, ssid);
4973}
4974
4975
4976/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004977 * wpas_remove_cred - Remove the specified credential and all the network
4978 * entries created based on the removed credential
4979 * @wpa_s: wpa_supplicant structure for a network interface
4980 * @cred: The credential to remove
4981 * Returns: 0 on success, -1 on failure
4982 */
4983int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4984{
4985 struct wpa_ssid *ssid, *next;
4986 int id;
4987
4988 if (!cred) {
4989 wpa_printf(MSG_DEBUG, "Could not find cred");
4990 return -1;
4991 }
4992
4993 id = cred->id;
4994 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4995 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4996 return -1;
4997 }
4998
4999 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5000
5001 /* Remove any network entry created based on the removed credential */
5002 ssid = wpa_s->conf->ssid;
5003 while (ssid) {
5004 next = ssid->next;
5005
5006 if (ssid->parent_cred == cred) {
5007 wpa_printf(MSG_DEBUG,
5008 "Remove network id %d since it used the removed credential",
5009 ssid->id);
5010 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5011 -1) {
5012 wpa_printf(MSG_DEBUG,
5013 "Could not find network id=%d",
5014 ssid->id);
5015 }
5016 }
5017
5018 ssid = next;
5019 }
5020
5021 return 0;
5022}
5023
5024
5025/**
5026 * wpas_remove_cred - Remove all the Interworking credentials
5027 * @wpa_s: wpa_supplicant structure for a network interface
5028 * Returns: 0 on success, -1 on failure
5029 */
5030int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5031{
5032 int res, ret = 0;
5033 struct wpa_cred *cred, *prev;
5034
5035 cred = wpa_s->conf->cred;
5036 while (cred) {
5037 prev = cred;
5038 cred = cred->next;
5039 res = wpas_remove_cred(wpa_s, prev);
5040 if (res < 0) {
5041 wpa_printf(MSG_DEBUG,
5042 "Removal of all credentials failed - failed to remove credential id=%d",
5043 prev->id);
5044 ret = -1;
5045 }
5046 }
5047
5048 return ret;
5049}
5050
5051
5052/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005053 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5054 * @wpa_s: wpa_supplicant structure for a network interface
5055 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5056 * @pkcs11_module_path: PKCS #11 module path or NULL
5057 * Returns: 0 on success; -1 on failure
5058 *
5059 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5060 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5061 * module path fails the paths will be reset to the default value (NULL).
5062 */
5063int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5064 const char *pkcs11_engine_path,
5065 const char *pkcs11_module_path)
5066{
5067 char *pkcs11_engine_path_copy = NULL;
5068 char *pkcs11_module_path_copy = NULL;
5069
5070 if (pkcs11_engine_path != NULL) {
5071 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5072 if (pkcs11_engine_path_copy == NULL)
5073 return -1;
5074 }
5075 if (pkcs11_module_path != NULL) {
5076 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005077 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005078 os_free(pkcs11_engine_path_copy);
5079 return -1;
5080 }
5081 }
5082
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005083#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005084 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005085 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005086#endif /* CONFIG_PKCS11_ENGINE_PATH */
5087#ifndef CONFIG_PKCS11_MODULE_PATH
5088 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005089 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005090#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005091
5092 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5093 eapol_sm_deinit(wpa_s->eapol);
5094 wpa_s->eapol = NULL;
5095 if (wpa_supplicant_init_eapol(wpa_s)) {
5096 /* Error -> Reset paths to the default value (NULL) once. */
5097 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5098 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5099 NULL);
5100
5101 return -1;
5102 }
5103 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5104
5105 return 0;
5106}
5107
5108
5109/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005110 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5111 * @wpa_s: wpa_supplicant structure for a network interface
5112 * @ap_scan: AP scan mode
5113 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5114 *
5115 */
5116int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5117{
5118
5119 int old_ap_scan;
5120
5121 if (ap_scan < 0 || ap_scan > 2)
5122 return -1;
5123
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005124 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5125 wpa_printf(MSG_INFO,
5126 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5127 }
5128
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005129#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005130 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5131 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5132 wpa_s->wpa_state < WPA_COMPLETED) {
5133 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5134 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005135 return 0;
5136 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005137#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005139 old_ap_scan = wpa_s->conf->ap_scan;
5140 wpa_s->conf->ap_scan = ap_scan;
5141
5142 if (old_ap_scan != wpa_s->conf->ap_scan)
5143 wpas_notify_ap_scan_changed(wpa_s);
5144
5145 return 0;
5146}
5147
5148
5149/**
5150 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5151 * @wpa_s: wpa_supplicant structure for a network interface
5152 * @expire_age: Expiration age in seconds
5153 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5154 *
5155 */
5156int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5157 unsigned int bss_expire_age)
5158{
5159 if (bss_expire_age < 10) {
5160 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5161 bss_expire_age);
5162 return -1;
5163 }
5164 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5165 bss_expire_age);
5166 wpa_s->conf->bss_expiration_age = bss_expire_age;
5167
5168 return 0;
5169}
5170
5171
5172/**
5173 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5174 * @wpa_s: wpa_supplicant structure for a network interface
5175 * @expire_count: number of scans after which an unseen BSS is reclaimed
5176 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5177 *
5178 */
5179int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5180 unsigned int bss_expire_count)
5181{
5182 if (bss_expire_count < 1) {
5183 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5184 bss_expire_count);
5185 return -1;
5186 }
5187 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5188 bss_expire_count);
5189 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5190
5191 return 0;
5192}
5193
5194
5195/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005196 * wpa_supplicant_set_scan_interval - Set scan interval
5197 * @wpa_s: wpa_supplicant structure for a network interface
5198 * @scan_interval: scan interval in seconds
5199 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5200 *
5201 */
5202int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5203 int scan_interval)
5204{
5205 if (scan_interval < 0) {
5206 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5207 scan_interval);
5208 return -1;
5209 }
5210 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5211 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005212 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005213
5214 return 0;
5215}
5216
5217
5218/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005219 * wpa_supplicant_set_debug_params - Set global debug params
5220 * @global: wpa_global structure
5221 * @debug_level: debug level
5222 * @debug_timestamp: determines if show timestamp in debug data
5223 * @debug_show_keys: determines if show keys in debug data
5224 * Returns: 0 if succeed or -1 if debug_level has wrong value
5225 */
5226int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5227 int debug_timestamp, int debug_show_keys)
5228{
5229
5230 int old_level, old_timestamp, old_show_keys;
5231
5232 /* check for allowed debuglevels */
5233 if (debug_level != MSG_EXCESSIVE &&
5234 debug_level != MSG_MSGDUMP &&
5235 debug_level != MSG_DEBUG &&
5236 debug_level != MSG_INFO &&
5237 debug_level != MSG_WARNING &&
5238 debug_level != MSG_ERROR)
5239 return -1;
5240
5241 old_level = wpa_debug_level;
5242 old_timestamp = wpa_debug_timestamp;
5243 old_show_keys = wpa_debug_show_keys;
5244
5245 wpa_debug_level = debug_level;
5246 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5247 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5248
5249 if (wpa_debug_level != old_level)
5250 wpas_notify_debug_level_changed(global);
5251 if (wpa_debug_timestamp != old_timestamp)
5252 wpas_notify_debug_timestamp_changed(global);
5253 if (wpa_debug_show_keys != old_show_keys)
5254 wpas_notify_debug_show_keys_changed(global);
5255
5256 return 0;
5257}
5258
5259
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005260#ifdef CONFIG_OWE
5261static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5262 const u8 *entry_ssid, size_t entry_ssid_len)
5263{
5264 const u8 *owe, *pos, *end;
5265 u8 ssid_len;
5266 struct wpa_bss *bss;
5267
5268 /* Check network profile SSID aganst the SSID in the
5269 * OWE Transition Mode element. */
5270
5271 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5272 if (!bss)
5273 return 0;
5274
5275 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5276 if (!owe)
5277 return 0;
5278
5279 pos = owe + 6;
5280 end = owe + 2 + owe[1];
5281
5282 if (end - pos < ETH_ALEN + 1)
5283 return 0;
5284 pos += ETH_ALEN;
5285 ssid_len = *pos++;
5286 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5287 return 0;
5288
5289 return entry_ssid_len == ssid_len &&
5290 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5291}
5292#endif /* CONFIG_OWE */
5293
5294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005295/**
5296 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5297 * @wpa_s: Pointer to wpa_supplicant data
5298 * Returns: A pointer to the current network structure or %NULL on failure
5299 */
5300struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5301{
5302 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005303 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005304 int res;
5305 size_t ssid_len;
5306 u8 bssid[ETH_ALEN];
5307 int wired;
5308
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005309 res = wpa_drv_get_ssid(wpa_s, ssid);
5310 if (res < 0) {
5311 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5312 "driver");
5313 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005314 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005315 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005316
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005317 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005318 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5319 "driver");
5320 return NULL;
5321 }
5322
5323 wired = wpa_s->conf->ap_scan == 0 &&
5324 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5325
5326 entry = wpa_s->conf->ssid;
5327 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005328 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005330 (!entry->ssid ||
5331 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5332 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005333 (!entry->bssid_set ||
5334 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5335 return entry;
5336#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005337 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005338 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5339 (entry->ssid == NULL || entry->ssid_len == 0) &&
5340 (!entry->bssid_set ||
5341 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5342 return entry;
5343#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005344
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005345#ifdef CONFIG_OWE
5346 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005347 (entry->ssid &&
5348 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5349 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005350 (!entry->bssid_set ||
5351 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5352 return entry;
5353#endif /* CONFIG_OWE */
5354
Dmitry Shmidt04949592012-07-19 12:16:46 -07005355 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005356 entry->ssid_len == 0 &&
5357 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5358 return entry;
5359
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 entry = entry->next;
5361 }
5362
5363 return NULL;
5364}
5365
5366
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005367static int select_driver(struct wpa_supplicant *wpa_s, int i)
5368{
5369 struct wpa_global *global = wpa_s->global;
5370
5371 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005372 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005373 if (global->drv_priv[i] == NULL) {
5374 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5375 "'%s'", wpa_drivers[i]->name);
5376 return -1;
5377 }
5378 }
5379
5380 wpa_s->driver = wpa_drivers[i];
5381 wpa_s->global_drv_priv = global->drv_priv[i];
5382
5383 return 0;
5384}
5385
5386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005387static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5388 const char *name)
5389{
5390 int i;
5391 size_t len;
5392 const char *pos, *driver = name;
5393
5394 if (wpa_s == NULL)
5395 return -1;
5396
5397 if (wpa_drivers[0] == NULL) {
5398 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5399 "wpa_supplicant");
5400 return -1;
5401 }
5402
5403 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005404 /* Default to first successful driver in the list */
5405 for (i = 0; wpa_drivers[i]; i++) {
5406 if (select_driver(wpa_s, i) == 0)
5407 return 0;
5408 }
5409 /* Drivers have each reported failure, so no wpa_msg() here. */
5410 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005411 }
5412
5413 do {
5414 pos = os_strchr(driver, ',');
5415 if (pos)
5416 len = pos - driver;
5417 else
5418 len = os_strlen(driver);
5419
5420 for (i = 0; wpa_drivers[i]; i++) {
5421 if (os_strlen(wpa_drivers[i]->name) == len &&
5422 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005423 0) {
5424 /* First driver that succeeds wins */
5425 if (select_driver(wpa_s, i) == 0)
5426 return 0;
5427 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005428 }
5429
5430 driver = pos + 1;
5431 } while (pos);
5432
5433 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5434 return -1;
5435}
5436
5437
5438/**
5439 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5440 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5441 * with struct wpa_driver_ops::init()
5442 * @src_addr: Source address of the EAPOL frame
5443 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5444 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005445 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005446 *
5447 * This function is called for each received EAPOL frame. Most driver
5448 * interfaces rely on more generic OS mechanism for receiving frames through
5449 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5450 * take care of received EAPOL frames and deliver them to the core supplicant
5451 * code by calling this function.
5452 */
5453void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005454 const u8 *buf, size_t len,
5455 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005456{
5457 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005458 const u8 *connected_addr = wpa_s->valid_links ?
5459 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005460
Sunil8cd6f4d2022-06-28 18:40:46 +00005461 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5462 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005463 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5464
Hai Shalomc1a21442022-02-04 13:43:00 -08005465 if (wpa_s->own_disconnect_req) {
5466 wpa_printf(MSG_DEBUG,
5467 "Drop received EAPOL frame as we are disconnecting");
5468 return;
5469 }
5470
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005471#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005472 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5473 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005474 if (wpa_s->ignore_auth_resp) {
5475 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5476 return;
5477 }
5478#endif /* CONFIG_TESTING_OPTIONS */
5479
Jouni Malinena05074c2012-12-21 21:35:35 +02005480 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5481 (wpa_s->last_eapol_matches_bssid &&
5482#ifdef CONFIG_AP
5483 !wpa_s->ap_iface &&
5484#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005485 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005486 /*
5487 * There is possible race condition between receiving the
5488 * association event and the EAPOL frame since they are coming
5489 * through different paths from the driver. In order to avoid
5490 * issues in trying to process the EAPOL frame before receiving
5491 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005492 * the association event is received. This may also be needed in
5493 * driver-based roaming case, so also use src_addr != BSSID as a
5494 * trigger if we have previously confirmed that the
5495 * Authenticator uses BSSID as the src_addr (which is not the
5496 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005498 wpa_dbg(wpa_s, MSG_DEBUG,
5499 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5500 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005501 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005502 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005503 wpabuf_free(wpa_s->pending_eapol_rx);
5504 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5505 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005506 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5508 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005509 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005510 }
5511 return;
5512 }
5513
Jouni Malinena05074c2012-12-21 21:35:35 +02005514 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005515 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005517#ifdef CONFIG_AP
5518 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005519 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5520 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005521 return;
5522 }
5523#endif /* CONFIG_AP */
5524
5525 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5526 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5527 "no key management is configured");
5528 return;
5529 }
5530
5531 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005532 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005533 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5534 wpa_s->wpa_state != WPA_COMPLETED) &&
5535 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005536 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005537 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005538 int timeout = 10;
5539
5540 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5541 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5542 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5543 /* Use longer timeout for IEEE 802.1X/EAP */
5544 timeout = 70;
5545 }
5546
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005547#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005548 if (wpa_s->current_ssid && wpa_s->current_bss &&
5549 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5550 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5551 /*
5552 * Use shorter timeout if going through WPS AP iteration
5553 * for PIN config method with an AP that does not
5554 * advertise Selected Registrar.
5555 */
5556 struct wpabuf *wps_ie;
5557
5558 wps_ie = wpa_bss_get_vendor_ie_multi(
5559 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5560 if (wps_ie &&
5561 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5562 timeout = 10;
5563 wpabuf_free(wps_ie);
5564 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005565#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005566
5567 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 }
5569 wpa_s->eapol_received++;
5570
5571 if (wpa_s->countermeasures) {
5572 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5573 "EAPOL packet");
5574 return;
5575 }
5576
5577#ifdef CONFIG_IBSS_RSN
5578 if (wpa_s->current_ssid &&
5579 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005580 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5581 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005582 return;
5583 }
5584#endif /* CONFIG_IBSS_RSN */
5585
5586 /* Source address of the incoming EAPOL frame could be compared to the
5587 * current BSSID. However, it is possible that a centralized
5588 * Authenticator could be using another MAC address than the BSSID of
5589 * an AP, so just allow any address to be used for now. The replies are
5590 * still sent to the current BSSID (if available), though. */
5591
5592 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5593 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005594 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5595 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005596 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5597 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005598 return;
5599 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005600 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005601 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005602 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5603 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005604 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005605 * handshake processing which would normally set portValid. We
5606 * need this to allow the EAPOL state machines to be completed
5607 * without going through EAPOL-Key handshake.
5608 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005609 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610 }
5611}
5612
5613
Sunil8cd6f4d2022-06-28 18:40:46 +00005614static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5615 const u8 *buf, size_t len)
5616{
5617 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5618 FRAME_ENCRYPTION_UNKNOWN);
5619}
5620
5621
Hai Shalomb755a2a2020-04-23 21:49:02 -07005622static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5623{
5624 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5625 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5626}
5627
5628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005629int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005630{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005631 u8 prev_mac_addr[ETH_ALEN];
5632
5633 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5634
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005635 if ((!wpa_s->p2p_mgmt ||
5636 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5637 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005638 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005639 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5640 wpa_drv_get_mac_addr(wpa_s),
5641 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005642 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005643 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005644 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645 if (wpa_s->l2 == NULL)
5646 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005647
5648 if (l2_packet_set_packet_filter(wpa_s->l2,
5649 L2_PACKET_FILTER_PKTTYPE))
5650 wpa_dbg(wpa_s, MSG_DEBUG,
5651 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005652
5653 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5654 wpa_msg(wpa_s, MSG_ERROR,
5655 "Failed to get own L2 address");
5656 return -1;
5657 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005658 } else {
5659 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5660 if (addr)
5661 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5662 }
5663
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005664 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005665 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005666
Hai Shalomc3565922019-10-28 11:58:20 -07005667#ifdef CONFIG_FST
5668 if (wpa_s->fst)
5669 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5670#endif /* CONFIG_FST */
5671
Sunil Ravi77d572f2023-01-17 23:58:31 +00005672 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5673 wpas_notify_mac_address_changed(wpa_s);
5674
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005675 return 0;
5676}
5677
5678
Dmitry Shmidt04949592012-07-19 12:16:46 -07005679static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5680 const u8 *buf, size_t len)
5681{
5682 struct wpa_supplicant *wpa_s = ctx;
5683 const struct l2_ethhdr *eth;
5684
5685 if (len < sizeof(*eth))
5686 return;
5687 eth = (const struct l2_ethhdr *) buf;
5688
5689 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5690 !(eth->h_dest[0] & 0x01)) {
5691 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5692 " (bridge - not for this interface - ignore)",
5693 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5694 return;
5695 }
5696
5697 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5698 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5699 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005700 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005701}
5702
5703
Hai Shalom899fcc72020-10-19 14:38:18 -07005704int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5705 const char *bridge_ifname)
5706{
5707 if (wpa_s->wpa_state > WPA_SCANNING)
5708 return -EBUSY;
5709
5710 if (bridge_ifname &&
5711 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5712 return -EINVAL;
5713
5714 if (!bridge_ifname)
5715 bridge_ifname = "";
5716
5717 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5718 return 0;
5719
5720 if (wpa_s->l2_br) {
5721 l2_packet_deinit(wpa_s->l2_br);
5722 wpa_s->l2_br = NULL;
5723 }
5724
5725 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5726 sizeof(wpa_s->bridge_ifname));
5727
5728 if (wpa_s->bridge_ifname[0]) {
5729 wpa_dbg(wpa_s, MSG_DEBUG,
5730 "Receiving packets from bridge interface '%s'",
5731 wpa_s->bridge_ifname);
5732 wpa_s->l2_br = l2_packet_init_bridge(
5733 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5734 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5735 if (!wpa_s->l2_br) {
5736 wpa_msg(wpa_s, MSG_ERROR,
5737 "Failed to open l2_packet connection for the bridge interface '%s'",
5738 wpa_s->bridge_ifname);
5739 goto fail;
5740 }
5741 }
5742
5743#ifdef CONFIG_TDLS
5744 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5745 goto fail;
5746#endif /* CONFIG_TDLS */
5747
5748 return 0;
5749fail:
5750 wpa_s->bridge_ifname[0] = 0;
5751 if (wpa_s->l2_br) {
5752 l2_packet_deinit(wpa_s->l2_br);
5753 wpa_s->l2_br = NULL;
5754 }
5755#ifdef CONFIG_TDLS
5756 if (!wpa_s->p2p_mgmt)
5757 wpa_tdls_init(wpa_s->wpa);
5758#endif /* CONFIG_TDLS */
5759 return -EIO;
5760}
5761
5762
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005763/**
5764 * wpa_supplicant_driver_init - Initialize driver interface parameters
5765 * @wpa_s: Pointer to wpa_supplicant data
5766 * Returns: 0 on success, -1 on failure
5767 *
5768 * This function is called to initialize driver interface parameters.
5769 * wpa_drv_init() must have been called before this function to initialize the
5770 * driver interface.
5771 */
5772int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5773{
5774 static int interface_count = 0;
5775
5776 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5777 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005778
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005779 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5780 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005781 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005782 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5783
Hai Shalomb755a2a2020-04-23 21:49:02 -07005784 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005785 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5786 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005787 wpa_s->l2_br = l2_packet_init_bridge(
5788 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5789 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005790 if (wpa_s->l2_br == NULL) {
5791 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5792 "connection for the bridge interface '%s'",
5793 wpa_s->bridge_ifname);
5794 return -1;
5795 }
5796 }
5797
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005798 if (wpa_s->conf->ap_scan == 2 &&
5799 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5800 wpa_printf(MSG_INFO,
5801 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5802 }
5803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005804 wpa_clear_keys(wpa_s, NULL);
5805
5806 /* Make sure that TKIP countermeasures are not left enabled (could
5807 * happen if wpa_supplicant is killed during countermeasures. */
5808 wpa_drv_set_countermeasures(wpa_s, 0);
5809
5810 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5811 wpa_drv_flush_pmkid(wpa_s);
5812
5813 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005814 wpa_s->prev_scan_wildcard = 0;
5815
Dmitry Shmidt04949592012-07-19 12:16:46 -07005816 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005817 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5818 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5819 interface_count = 0;
5820 }
Keith Mok4389c282022-11-23 21:36:48 +00005821#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005822 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005823 wpa_supplicant_delayed_sched_scan(wpa_s,
5824 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005825 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005826 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005827 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005828#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005829 interface_count++;
5830 } else
5831 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5832
5833 return 0;
5834}
5835
5836
5837static int wpa_supplicant_daemon(const char *pid_file)
5838{
5839 wpa_printf(MSG_DEBUG, "Daemonize..");
5840 return os_daemonize(pid_file);
5841}
5842
5843
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005844static struct wpa_supplicant *
5845wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005846{
5847 struct wpa_supplicant *wpa_s;
5848
5849 wpa_s = os_zalloc(sizeof(*wpa_s));
5850 if (wpa_s == NULL)
5851 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005852 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005853 wpa_s->scan_interval = 5;
5854 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005855 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005856 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005857 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005858 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005860 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005861 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005862#ifdef CONFIG_TESTING_OPTIONS
5863 dl_list_init(&wpa_s->drv_signal_override);
5864#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005865 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005866 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005867
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005868 return wpa_s;
5869}
5870
5871
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005872#ifdef CONFIG_HT_OVERRIDES
5873
5874static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5875 struct ieee80211_ht_capabilities *htcaps,
5876 struct ieee80211_ht_capabilities *htcaps_mask,
5877 const char *ht_mcs)
5878{
5879 /* parse ht_mcs into hex array */
5880 int i;
5881 const char *tmp = ht_mcs;
5882 char *end = NULL;
5883
5884 /* If ht_mcs is null, do not set anything */
5885 if (!ht_mcs)
5886 return 0;
5887
5888 /* This is what we are setting in the kernel */
5889 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5890
5891 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5892
5893 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005894 long v;
5895
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005896 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005897 v = strtol(tmp, &end, 16);
5898
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005899 if (errno == 0) {
5900 wpa_msg(wpa_s, MSG_DEBUG,
5901 "htcap value[%i]: %ld end: %p tmp: %p",
5902 i, v, end, tmp);
5903 if (end == tmp)
5904 break;
5905
5906 htcaps->supported_mcs_set[i] = v;
5907 tmp = end;
5908 } else {
5909 wpa_msg(wpa_s, MSG_ERROR,
5910 "Failed to parse ht-mcs: %s, error: %s\n",
5911 ht_mcs, strerror(errno));
5912 return -1;
5913 }
5914 }
5915
5916 /*
5917 * If we were able to parse any values, then set mask for the MCS set.
5918 */
5919 if (i) {
5920 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5921 IEEE80211_HT_MCS_MASK_LEN - 1);
5922 /* skip the 3 reserved bits */
5923 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5924 0x1f;
5925 }
5926
5927 return 0;
5928}
5929
5930
5931static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5932 struct ieee80211_ht_capabilities *htcaps,
5933 struct ieee80211_ht_capabilities *htcaps_mask,
5934 int disabled)
5935{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005936 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005937
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005938 if (disabled == -1)
5939 return 0;
5940
Hai Shalom74f70d42019-02-11 14:42:39 -08005941 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5942
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005943 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5944 htcaps_mask->ht_capabilities_info |= msk;
5945 if (disabled)
5946 htcaps->ht_capabilities_info &= msk;
5947 else
5948 htcaps->ht_capabilities_info |= msk;
5949
5950 return 0;
5951}
5952
5953
5954static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5955 struct ieee80211_ht_capabilities *htcaps,
5956 struct ieee80211_ht_capabilities *htcaps_mask,
5957 int factor)
5958{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005959 if (factor == -1)
5960 return 0;
5961
Hai Shalom74f70d42019-02-11 14:42:39 -08005962 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5963
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005964 if (factor < 0 || factor > 3) {
5965 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5966 "Must be 0-3 or -1", factor);
5967 return -EINVAL;
5968 }
5969
5970 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5971 htcaps->a_mpdu_params &= ~0x3;
5972 htcaps->a_mpdu_params |= factor & 0x3;
5973
5974 return 0;
5975}
5976
5977
5978static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5979 struct ieee80211_ht_capabilities *htcaps,
5980 struct ieee80211_ht_capabilities *htcaps_mask,
5981 int density)
5982{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005983 if (density == -1)
5984 return 0;
5985
Hai Shalom74f70d42019-02-11 14:42:39 -08005986 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5987
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005988 if (density < 0 || density > 7) {
5989 wpa_msg(wpa_s, MSG_ERROR,
5990 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5991 density);
5992 return -EINVAL;
5993 }
5994
5995 htcaps_mask->a_mpdu_params |= 0x1C;
5996 htcaps->a_mpdu_params &= ~(0x1C);
5997 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5998
5999 return 0;
6000}
6001
6002
6003static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6004 struct ieee80211_ht_capabilities *htcaps,
6005 struct ieee80211_ht_capabilities *htcaps_mask,
6006 int disabled)
6007{
Hai Shalom74f70d42019-02-11 14:42:39 -08006008 if (disabled)
6009 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006010
Paul Stewart092955c2017-02-06 09:13:09 -08006011 set_disable_ht40(htcaps, disabled);
6012 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006013
6014 return 0;
6015}
6016
6017
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006018static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6019 struct ieee80211_ht_capabilities *htcaps,
6020 struct ieee80211_ht_capabilities *htcaps_mask,
6021 int disabled)
6022{
6023 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006024 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6025 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006026
Hai Shalom74f70d42019-02-11 14:42:39 -08006027 if (disabled)
6028 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006029
6030 if (disabled)
6031 htcaps->ht_capabilities_info &= ~msk;
6032 else
6033 htcaps->ht_capabilities_info |= msk;
6034
6035 htcaps_mask->ht_capabilities_info |= msk;
6036
6037 return 0;
6038}
6039
6040
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006041static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6042 struct ieee80211_ht_capabilities *htcaps,
6043 struct ieee80211_ht_capabilities *htcaps_mask,
6044 int disabled)
6045{
6046 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006047 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006048
Hai Shalom74f70d42019-02-11 14:42:39 -08006049 if (disabled)
6050 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006051
6052 if (disabled)
6053 htcaps->ht_capabilities_info &= ~msk;
6054 else
6055 htcaps->ht_capabilities_info |= msk;
6056
6057 htcaps_mask->ht_capabilities_info |= msk;
6058
6059 return 0;
6060}
6061
6062
Hai Shalom74f70d42019-02-11 14:42:39 -08006063static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6064 struct ieee80211_ht_capabilities *htcaps,
6065 struct ieee80211_ht_capabilities *htcaps_mask,
6066 int tx_stbc)
6067{
6068 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6069
6070 if (tx_stbc == -1)
6071 return 0;
6072
6073 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6074
6075 if (tx_stbc < 0 || tx_stbc > 1) {
6076 wpa_msg(wpa_s, MSG_ERROR,
6077 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6078 return -EINVAL;
6079 }
6080
6081 htcaps_mask->ht_capabilities_info |= msk;
6082 htcaps->ht_capabilities_info &= ~msk;
6083 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6084
6085 return 0;
6086}
6087
6088
6089static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6090 struct ieee80211_ht_capabilities *htcaps,
6091 struct ieee80211_ht_capabilities *htcaps_mask,
6092 int rx_stbc)
6093{
6094 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6095
6096 if (rx_stbc == -1)
6097 return 0;
6098
6099 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6100
6101 if (rx_stbc < 0 || rx_stbc > 3) {
6102 wpa_msg(wpa_s, MSG_ERROR,
6103 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6104 return -EINVAL;
6105 }
6106
6107 htcaps_mask->ht_capabilities_info |= msk;
6108 htcaps->ht_capabilities_info &= ~msk;
6109 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6110
6111 return 0;
6112}
6113
6114
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006115void wpa_supplicant_apply_ht_overrides(
6116 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6117 struct wpa_driver_associate_params *params)
6118{
6119 struct ieee80211_ht_capabilities *htcaps;
6120 struct ieee80211_ht_capabilities *htcaps_mask;
6121
6122 if (!ssid)
6123 return;
6124
6125 params->disable_ht = ssid->disable_ht;
6126 if (!params->htcaps || !params->htcaps_mask)
6127 return;
6128
6129 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6130 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6131 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6132 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6133 ssid->disable_max_amsdu);
6134 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6135 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6136 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006137 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006138 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006139 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6140 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006141
6142 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006143 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006144 htcaps->ht_capabilities_info |= bit;
6145 htcaps_mask->ht_capabilities_info |= bit;
6146 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006147}
6148
6149#endif /* CONFIG_HT_OVERRIDES */
6150
6151
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006152#ifdef CONFIG_VHT_OVERRIDES
6153void wpa_supplicant_apply_vht_overrides(
6154 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6155 struct wpa_driver_associate_params *params)
6156{
6157 struct ieee80211_vht_capabilities *vhtcaps;
6158 struct ieee80211_vht_capabilities *vhtcaps_mask;
6159
6160 if (!ssid)
6161 return;
6162
6163 params->disable_vht = ssid->disable_vht;
6164
6165 vhtcaps = (void *) params->vhtcaps;
6166 vhtcaps_mask = (void *) params->vhtcaps_mask;
6167
6168 if (!vhtcaps || !vhtcaps_mask)
6169 return;
6170
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006171 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6172 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006173
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006174#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006175 if (ssid->disable_sgi) {
6176 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6177 VHT_CAP_SHORT_GI_160);
6178 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6179 VHT_CAP_SHORT_GI_160);
6180 wpa_msg(wpa_s, MSG_DEBUG,
6181 "disable-sgi override specified, vht-caps: 0x%x",
6182 vhtcaps->vht_capabilities_info);
6183 }
6184
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006185 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006186 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6187 int max_ampdu;
6188
6189 max_ampdu = (ssid->vht_capa &
6190 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6191 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006192
6193 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6194 wpa_set_ampdu_factor(wpa_s,
6195 (void *) params->htcaps,
6196 (void *) params->htcaps_mask,
6197 max_ampdu);
6198 }
6199#endif /* CONFIG_HT_OVERRIDES */
6200
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006201#define OVERRIDE_MCS(i) \
6202 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6203 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006204 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006205 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006206 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6207 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006208 } \
6209 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6210 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006211 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006212 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006213 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6214 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006215 }
6216
6217 OVERRIDE_MCS(1);
6218 OVERRIDE_MCS(2);
6219 OVERRIDE_MCS(3);
6220 OVERRIDE_MCS(4);
6221 OVERRIDE_MCS(5);
6222 OVERRIDE_MCS(6);
6223 OVERRIDE_MCS(7);
6224 OVERRIDE_MCS(8);
6225}
6226#endif /* CONFIG_VHT_OVERRIDES */
6227
6228
Hai Shalomfdcde762020-04-02 11:19:20 -07006229#ifdef CONFIG_HE_OVERRIDES
6230void wpa_supplicant_apply_he_overrides(
6231 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6232 struct wpa_driver_associate_params *params)
6233{
6234 if (!ssid)
6235 return;
6236
6237 params->disable_he = ssid->disable_he;
6238}
6239#endif /* CONFIG_HE_OVERRIDES */
6240
6241
Sunil Ravi77d572f2023-01-17 23:58:31 +00006242void wpa_supplicant_apply_eht_overrides(
6243 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6244 struct wpa_driver_associate_params *params)
6245{
6246 if (!ssid)
6247 return;
6248
6249 params->disable_eht = ssid->disable_eht;
6250}
6251
6252
Dmitry Shmidt04949592012-07-19 12:16:46 -07006253static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6254{
6255#ifdef PCSC_FUNCS
6256 size_t len;
6257
6258 if (!wpa_s->conf->pcsc_reader)
6259 return 0;
6260
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006261 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006262 if (!wpa_s->scard)
6263 return 1;
6264
6265 if (wpa_s->conf->pcsc_pin &&
6266 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6267 scard_deinit(wpa_s->scard);
6268 wpa_s->scard = NULL;
6269 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6270 return -1;
6271 }
6272
6273 len = sizeof(wpa_s->imsi) - 1;
6274 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6275 scard_deinit(wpa_s->scard);
6276 wpa_s->scard = NULL;
6277 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6278 return -1;
6279 }
6280 wpa_s->imsi[len] = '\0';
6281
6282 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6283
6284 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6285 wpa_s->imsi, wpa_s->mnc_len);
6286
6287 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6288 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6289#endif /* PCSC_FUNCS */
6290
6291 return 0;
6292}
6293
6294
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006295int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6296{
6297 char *val, *pos;
6298
6299 ext_password_deinit(wpa_s->ext_pw);
6300 wpa_s->ext_pw = NULL;
6301 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6302
6303 if (!wpa_s->conf->ext_password_backend)
6304 return 0;
6305
6306 val = os_strdup(wpa_s->conf->ext_password_backend);
6307 if (val == NULL)
6308 return -1;
6309 pos = os_strchr(val, ':');
6310 if (pos)
6311 *pos++ = '\0';
6312
6313 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6314
6315 wpa_s->ext_pw = ext_password_init(val, pos);
6316 os_free(val);
6317 if (wpa_s->ext_pw == NULL) {
6318 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6319 return -1;
6320 }
6321 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6322
6323 return 0;
6324}
6325
6326
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006327#ifdef CONFIG_FST
6328
6329static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6330{
6331 struct wpa_supplicant *wpa_s = ctx;
6332
6333 return (is_zero_ether_addr(wpa_s->bssid) ||
6334 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6335}
6336
6337
6338static void wpas_fst_get_channel_info_cb(void *ctx,
6339 enum hostapd_hw_mode *hw_mode,
6340 u8 *channel)
6341{
6342 struct wpa_supplicant *wpa_s = ctx;
6343
6344 if (wpa_s->current_bss) {
6345 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6346 channel);
6347 } else if (wpa_s->hw.num_modes) {
6348 *hw_mode = wpa_s->hw.modes[0].mode;
6349 } else {
6350 WPA_ASSERT(0);
6351 *hw_mode = 0;
6352 }
6353}
6354
6355
6356static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6357{
6358 struct wpa_supplicant *wpa_s = ctx;
6359
6360 *modes = wpa_s->hw.modes;
6361 return wpa_s->hw.num_modes;
6362}
6363
6364
6365static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6366{
6367 struct wpa_supplicant *wpa_s = ctx;
6368
6369 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6370 wpa_s->fst_ies = fst_ies;
6371}
6372
6373
6374static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6375{
6376 struct wpa_supplicant *wpa_s = ctx;
6377
Paul Stewart092955c2017-02-06 09:13:09 -08006378 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6379 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6380 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6381 return -1;
6382 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006383 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006384 wpa_s->own_addr, wpa_s->bssid,
6385 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006386 0);
6387}
6388
6389
6390static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6391{
6392 struct wpa_supplicant *wpa_s = ctx;
6393
6394 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6395 return wpa_s->received_mb_ies;
6396}
6397
6398
6399static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6400 const u8 *buf, size_t size)
6401{
6402 struct wpa_supplicant *wpa_s = ctx;
6403 struct mb_ies_info info;
6404
6405 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6406
6407 if (!mb_ies_info_by_ies(&info, buf, size)) {
6408 wpabuf_free(wpa_s->received_mb_ies);
6409 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6410 }
6411}
6412
6413
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006414static const u8 * wpas_fst_get_peer_first(void *ctx,
6415 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006416 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006417{
6418 struct wpa_supplicant *wpa_s = ctx;
6419
6420 *get_ctx = NULL;
6421 if (!is_zero_ether_addr(wpa_s->bssid))
6422 return (wpa_s->received_mb_ies || !mb_only) ?
6423 wpa_s->bssid : NULL;
6424 return NULL;
6425}
6426
6427
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006428static const u8 * wpas_fst_get_peer_next(void *ctx,
6429 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006430 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006431{
6432 return NULL;
6433}
6434
6435void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6436 struct fst_wpa_obj *iface_obj)
6437{
Sunil8cd6f4d2022-06-28 18:40:46 +00006438 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006439 iface_obj->ctx = wpa_s;
6440 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6441 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6442 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6443 iface_obj->set_ies = wpas_fst_set_ies_cb;
6444 iface_obj->send_action = wpas_fst_send_action_cb;
6445 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6446 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6447 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6448 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6449}
6450#endif /* CONFIG_FST */
6451
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006452static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006453 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006454{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006455 struct wowlan_triggers *triggers;
6456 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006457
6458 if (!wpa_s->conf->wowlan_triggers)
6459 return 0;
6460
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006461 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6462 if (triggers) {
6463 ret = wpa_drv_wowlan(wpa_s, triggers);
6464 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006465 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006466 return ret;
6467}
6468
6469
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006470enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006471{
6472 if (freq < 3000)
6473 return BAND_2_4_GHZ;
6474 if (freq > 50000)
6475 return BAND_60_GHZ;
6476 return BAND_5_GHZ;
6477}
6478
6479
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006480unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006481{
6482 int i;
6483 unsigned int band = 0;
6484
6485 if (freqs) {
6486 /* freqs are specified for the radio work */
6487 for (i = 0; freqs[i]; i++)
6488 band |= wpas_freq_to_band(freqs[i]);
6489 } else {
6490 /*
6491 * freqs are not specified, implies all
6492 * the supported freqs by HW
6493 */
6494 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6495 if (wpa_s->hw.modes[i].num_channels != 0) {
6496 if (wpa_s->hw.modes[i].mode ==
6497 HOSTAPD_MODE_IEEE80211B ||
6498 wpa_s->hw.modes[i].mode ==
6499 HOSTAPD_MODE_IEEE80211G)
6500 band |= BAND_2_4_GHZ;
6501 else if (wpa_s->hw.modes[i].mode ==
6502 HOSTAPD_MODE_IEEE80211A)
6503 band |= BAND_5_GHZ;
6504 else if (wpa_s->hw.modes[i].mode ==
6505 HOSTAPD_MODE_IEEE80211AD)
6506 band |= BAND_60_GHZ;
6507 else if (wpa_s->hw.modes[i].mode ==
6508 HOSTAPD_MODE_IEEE80211ANY)
6509 band = BAND_2_4_GHZ | BAND_5_GHZ |
6510 BAND_60_GHZ;
6511 }
6512 }
6513 }
6514
6515 return band;
6516}
6517
6518
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006519static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6520 const char *rn)
6521{
6522 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6523 struct wpa_radio *radio;
6524
6525 while (rn && iface) {
6526 radio = iface->radio;
6527 if (radio && os_strcmp(rn, radio->name) == 0) {
6528 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6529 wpa_s->ifname, rn);
6530 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6531 return radio;
6532 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006533
6534 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006535 }
6536
6537 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6538 wpa_s->ifname, rn ? rn : "N/A");
6539 radio = os_zalloc(sizeof(*radio));
6540 if (radio == NULL)
6541 return NULL;
6542
6543 if (rn)
6544 os_strlcpy(radio->name, rn, sizeof(radio->name));
6545 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006546 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006547 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6548
6549 return radio;
6550}
6551
6552
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006553static void radio_work_free(struct wpa_radio_work *work)
6554{
6555 if (work->wpa_s->scan_work == work) {
6556 /* This should not really happen. */
6557 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6558 work->type, work, work->started);
6559 work->wpa_s->scan_work = NULL;
6560 }
6561
6562#ifdef CONFIG_P2P
6563 if (work->wpa_s->p2p_scan_work == work) {
6564 /* This should not really happen. */
6565 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6566 work->type, work, work->started);
6567 work->wpa_s->p2p_scan_work = NULL;
6568 }
6569#endif /* CONFIG_P2P */
6570
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006571 if (work->started) {
6572 work->wpa_s->radio->num_active_works--;
6573 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006574 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006575 work->type, work,
6576 work->wpa_s->radio->num_active_works);
6577 }
6578
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006579 dl_list_del(&work->list);
6580 os_free(work);
6581}
6582
6583
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006584static int radio_work_is_connect(struct wpa_radio_work *work)
6585{
6586 return os_strcmp(work->type, "sme-connect") == 0 ||
6587 os_strcmp(work->type, "connect") == 0;
6588}
6589
6590
6591static int radio_work_is_scan(struct wpa_radio_work *work)
6592{
6593 return os_strcmp(work->type, "scan") == 0 ||
6594 os_strcmp(work->type, "p2p-scan") == 0;
6595}
6596
6597
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006598static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6599{
6600 struct wpa_radio_work *active_work = NULL;
6601 struct wpa_radio_work *tmp;
6602
6603 /* Get the active work to know the type and band. */
6604 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6605 if (tmp->started) {
6606 active_work = tmp;
6607 break;
6608 }
6609 }
6610
6611 if (!active_work) {
6612 /* No active work, start one */
6613 radio->num_active_works = 0;
6614 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6615 list) {
6616 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006617 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006618 (((struct wpa_driver_scan_params *)
6619 tmp->ctx)->only_new_results ||
6620 tmp->wpa_s->clear_driver_scan_cache))
6621 continue;
6622 return tmp;
6623 }
6624 return NULL;
6625 }
6626
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006627 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006628 /*
6629 * If the active work is either connect or sme-connect,
6630 * do not parallelize them with other radio works.
6631 */
6632 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6633 "Do not parallelize radio work with %s",
6634 active_work->type);
6635 return NULL;
6636 }
6637
6638 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6639 if (tmp->started)
6640 continue;
6641
6642 /*
6643 * If connect or sme-connect are enqueued, parallelize only
6644 * those operations ahead of them in the queue.
6645 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006646 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006647 break;
6648
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006649 /* Serialize parallel scan and p2p_scan operations on the same
6650 * interface since the driver_nl80211 mechanism for tracking
6651 * scan cookies does not yet have support for this. */
6652 if (active_work->wpa_s == tmp->wpa_s &&
6653 radio_work_is_scan(active_work) &&
6654 radio_work_is_scan(tmp)) {
6655 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6656 "Do not start work '%s' when another work '%s' is already scheduled",
6657 tmp->type, active_work->type);
6658 continue;
6659 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006660 /*
6661 * Check that the radio works are distinct and
6662 * on different bands.
6663 */
6664 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6665 (active_work->bands != tmp->bands)) {
6666 /*
6667 * If a scan has to be scheduled through nl80211 scan
6668 * interface and if an external scan is already running,
6669 * do not schedule the scan since it is likely to get
6670 * rejected by kernel.
6671 */
6672 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006673 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006674 (((struct wpa_driver_scan_params *)
6675 tmp->ctx)->only_new_results ||
6676 tmp->wpa_s->clear_driver_scan_cache))
6677 continue;
6678
6679 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6680 "active_work:%s new_work:%s",
6681 active_work->type, tmp->type);
6682 return tmp;
6683 }
6684 }
6685
6686 /* Did not find a radio work to schedule in parallel. */
6687 return NULL;
6688}
6689
6690
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006691static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6692{
6693 struct wpa_radio *radio = eloop_ctx;
6694 struct wpa_radio_work *work;
6695 struct os_reltime now, diff;
6696 struct wpa_supplicant *wpa_s;
6697
6698 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006699 if (work == NULL) {
6700 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006701 return;
6702 }
6703
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006704 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6705 radio_list);
6706
6707 if (!(wpa_s &&
6708 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6709 if (work->started)
6710 return; /* already started and still in progress */
6711
Hai Shalom60840252021-02-19 19:02:11 -08006712 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006713 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6714 return;
6715 }
6716 } else {
6717 work = NULL;
6718 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6719 /* get the work to schedule next */
6720 work = radio_work_get_next_work(radio);
6721 }
6722 if (!work)
6723 return;
6724 }
6725
6726 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006727 os_get_reltime(&now);
6728 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006729 wpa_dbg(wpa_s, MSG_DEBUG,
6730 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006731 work->type, work, diff.sec, diff.usec);
6732 work->started = 1;
6733 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006734 radio->num_active_works++;
6735
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006736 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006737
6738 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6739 radio->num_active_works < MAX_ACTIVE_WORKS)
6740 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006741}
6742
6743
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006744/*
6745 * This function removes both started and pending radio works running on
6746 * the provided interface's radio.
6747 * Prior to the removal of the radio work, its callback (cb) is called with
6748 * deinit set to be 1. Each work's callback is responsible for clearing its
6749 * internal data and restoring to a correct state.
6750 * @wpa_s: wpa_supplicant data
6751 * @type: type of works to be removed
6752 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6753 * this interface's works.
6754 */
6755void radio_remove_works(struct wpa_supplicant *wpa_s,
6756 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006757{
6758 struct wpa_radio_work *work, *tmp;
6759 struct wpa_radio *radio = wpa_s->radio;
6760
6761 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6762 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006763 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006764 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006765
6766 /* skip other ifaces' works */
6767 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006768 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006769
6770 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6771 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006772 work->cb(work, 1);
6773 radio_work_free(work);
6774 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006775
6776 /* in case we removed the started work */
6777 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006778}
6779
6780
Roshan Pius3a1667e2018-07-03 15:17:14 -07006781void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6782{
6783 struct wpa_radio_work *work;
6784 struct wpa_radio *radio = wpa_s->radio;
6785
6786 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6787 if (work->ctx != ctx)
6788 continue;
6789 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6790 work->type, work, work->started ? " (started)" : "");
6791 radio_work_free(work);
6792 break;
6793 }
6794}
6795
6796
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006797static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6798{
6799 struct wpa_radio *radio = wpa_s->radio;
6800
6801 if (!radio)
6802 return;
6803
6804 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6805 wpa_s->ifname, radio->name);
6806 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006807 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006808 /* If the interface that triggered the external scan was removed, the
6809 * external scan is no longer running. */
6810 if (wpa_s == radio->external_scan_req_interface)
6811 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006812 wpa_s->radio = NULL;
6813 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006814 return; /* Interfaces remain for this radio */
6815
6816 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006817 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006818 os_free(radio);
6819}
6820
6821
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006822void radio_work_check_next(struct wpa_supplicant *wpa_s)
6823{
6824 struct wpa_radio *radio = wpa_s->radio;
6825
6826 if (dl_list_empty(&radio->work))
6827 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006828 if (wpa_s->ext_work_in_progress) {
6829 wpa_printf(MSG_DEBUG,
6830 "External radio work in progress - delay start of pending item");
6831 return;
6832 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006833 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6834 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6835}
6836
6837
6838/**
6839 * radio_add_work - Add a radio work item
6840 * @wpa_s: Pointer to wpa_supplicant data
6841 * @freq: Frequency of the offchannel operation in MHz or 0
6842 * @type: Unique identifier for each type of work
6843 * @next: Force as the next work to be executed
6844 * @cb: Callback function for indicating when radio is available
6845 * @ctx: Context pointer for the work (work->ctx in cb())
6846 * Returns: 0 on success, -1 on failure
6847 *
6848 * This function is used to request time for an operation that requires
6849 * exclusive radio control. Once the radio is available, the registered callback
6850 * function will be called. radio_work_done() must be called once the exclusive
6851 * radio operation has been completed, so that the radio is freed for other
6852 * operations. The special case of deinit=1 is used to free the context data
6853 * during interface removal. That does not allow the callback function to start
6854 * the radio operation, i.e., it must free any resources allocated for the radio
6855 * work and return.
6856 *
6857 * The @freq parameter can be used to indicate a single channel on which the
6858 * offchannel operation will occur. This may allow multiple radio work
6859 * operations to be performed in parallel if they apply for the same channel.
6860 * Setting this to 0 indicates that the work item may use multiple channels or
6861 * requires exclusive control of the radio.
6862 */
6863int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6864 const char *type, int next,
6865 void (*cb)(struct wpa_radio_work *work, int deinit),
6866 void *ctx)
6867{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006868 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006869 struct wpa_radio_work *work;
6870 int was_empty;
6871
6872 work = os_zalloc(sizeof(*work));
6873 if (work == NULL)
6874 return -1;
6875 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6876 os_get_reltime(&work->time);
6877 work->freq = freq;
6878 work->type = type;
6879 work->wpa_s = wpa_s;
6880 work->cb = cb;
6881 work->ctx = ctx;
6882
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006883 if (freq)
6884 work->bands = wpas_freq_to_band(freq);
6885 else if (os_strcmp(type, "scan") == 0 ||
6886 os_strcmp(type, "p2p-scan") == 0)
6887 work->bands = wpas_get_bands(wpa_s,
6888 ((struct wpa_driver_scan_params *)
6889 ctx)->freqs);
6890 else
6891 work->bands = wpas_get_bands(wpa_s, NULL);
6892
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006893 was_empty = dl_list_empty(&wpa_s->radio->work);
6894 if (next)
6895 dl_list_add(&wpa_s->radio->work, &work->list);
6896 else
6897 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6898 if (was_empty) {
6899 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6900 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006901 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6902 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6903 wpa_dbg(wpa_s, MSG_DEBUG,
6904 "Try to schedule a radio work (num_active_works=%u)",
6905 radio->num_active_works);
6906 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006907 }
6908
6909 return 0;
6910}
6911
6912
6913/**
6914 * radio_work_done - Indicate that a radio work item has been completed
6915 * @work: Completed work
6916 *
6917 * This function is called once the callback function registered with
6918 * radio_add_work() has completed its work.
6919 */
6920void radio_work_done(struct wpa_radio_work *work)
6921{
6922 struct wpa_supplicant *wpa_s = work->wpa_s;
6923 struct os_reltime now, diff;
6924 unsigned int started = work->started;
6925
6926 os_get_reltime(&now);
6927 os_reltime_sub(&now, &work->time, &diff);
6928 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6929 work->type, work, started ? "done" : "canceled",
6930 diff.sec, diff.usec);
6931 radio_work_free(work);
6932 if (started)
6933 radio_work_check_next(wpa_s);
6934}
6935
6936
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006937struct wpa_radio_work *
6938radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006939{
6940 struct wpa_radio_work *work;
6941 struct wpa_radio *radio = wpa_s->radio;
6942
6943 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6944 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006945 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006946 }
6947
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006948 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006949}
6950
6951
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006952static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006953 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006954{
6955 const char *ifname, *driver, *rn;
6956
6957 driver = iface->driver;
6958next_driver:
6959 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6960 return -1;
6961
6962 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6963 if (wpa_s->drv_priv == NULL) {
6964 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006965 int level = MSG_ERROR;
6966
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006967 pos = driver ? os_strchr(driver, ',') : NULL;
6968 if (pos) {
6969 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6970 "driver interface - try next driver wrapper");
6971 driver = pos + 1;
6972 goto next_driver;
6973 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006974
6975#ifdef CONFIG_MATCH_IFACE
6976 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6977 level = MSG_DEBUG;
6978#endif /* CONFIG_MATCH_IFACE */
6979 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006980 return -1;
6981 }
6982 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6983 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6984 "driver_param '%s'", wpa_s->conf->driver_param);
6985 return -1;
6986 }
6987
6988 ifname = wpa_drv_get_ifname(wpa_s);
6989 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6990 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6991 "interface name with '%s'", ifname);
6992 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6993 }
6994
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006995 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006996 if (rn && rn[0] == '\0')
6997 rn = NULL;
6998
6999 wpa_s->radio = radio_add_interface(wpa_s, rn);
7000 if (wpa_s->radio == NULL)
7001 return -1;
7002
7003 return 0;
7004}
7005
7006
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007007#ifdef CONFIG_GAS_SERVER
7008
7009static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7010 unsigned int freq, const u8 *dst,
7011 const u8 *src, const u8 *bssid,
7012 const u8 *data, size_t data_len,
7013 enum offchannel_send_action_result result)
7014{
7015 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7016 " result=%s",
7017 freq, MAC2STR(dst),
7018 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7019 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7020 "FAILED"));
7021 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7022 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7023}
7024
7025
7026static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7027 struct wpabuf *buf, unsigned int wait_time)
7028{
7029 struct wpa_supplicant *wpa_s = ctx;
7030 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7031
7032 if (wait_time > wpa_s->max_remain_on_chan)
7033 wait_time = wpa_s->max_remain_on_chan;
7034
7035 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7036 wpabuf_head(buf), wpabuf_len(buf),
7037 wait_time, wpas_gas_server_tx_status, 0);
7038}
7039
7040#endif /* CONFIG_GAS_SERVER */
7041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007042static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007043 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007044{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007045 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007046 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007047 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007048
7049 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7050 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7051 iface->confname ? iface->confname : "N/A",
7052 iface->driver ? iface->driver : "default",
7053 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7054 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7055
7056 if (iface->confname) {
7057#ifdef CONFIG_BACKEND_FILE
7058 wpa_s->confname = os_rel2abs_path(iface->confname);
7059 if (wpa_s->confname == NULL) {
7060 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7061 "for configuration file '%s'.",
7062 iface->confname);
7063 return -1;
7064 }
7065 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7066 iface->confname, wpa_s->confname);
7067#else /* CONFIG_BACKEND_FILE */
7068 wpa_s->confname = os_strdup(iface->confname);
7069#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007070 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007071 if (wpa_s->conf == NULL) {
7072 wpa_printf(MSG_ERROR, "Failed to read or parse "
7073 "configuration '%s'.", wpa_s->confname);
7074 return -1;
7075 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007076 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007077 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007078 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007079 wpa_printf(MSG_ERROR,
7080 "Failed to read or parse configuration '%s'.",
7081 wpa_s->confanother);
7082 return -1;
7083 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007084
7085 /*
7086 * Override ctrl_interface and driver_param if set on command
7087 * line.
7088 */
7089 if (iface->ctrl_interface) {
7090 os_free(wpa_s->conf->ctrl_interface);
7091 wpa_s->conf->ctrl_interface =
7092 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007093 if (!wpa_s->conf->ctrl_interface) {
7094 wpa_printf(MSG_ERROR,
7095 "Failed to duplicate control interface '%s'.",
7096 iface->ctrl_interface);
7097 return -1;
7098 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007099 }
7100
7101 if (iface->driver_param) {
7102 os_free(wpa_s->conf->driver_param);
7103 wpa_s->conf->driver_param =
7104 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007105 if (!wpa_s->conf->driver_param) {
7106 wpa_printf(MSG_ERROR,
7107 "Failed to duplicate driver param '%s'.",
7108 iface->driver_param);
7109 return -1;
7110 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007111 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007112
7113 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7114 os_free(wpa_s->conf->ctrl_interface);
7115 wpa_s->conf->ctrl_interface = NULL;
7116 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007117 } else
7118 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7119 iface->driver_param);
7120
7121 if (wpa_s->conf == NULL) {
7122 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7123 return -1;
7124 }
7125
7126 if (iface->ifname == NULL) {
7127 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7128 return -1;
7129 }
7130 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7131 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7132 iface->ifname);
7133 return -1;
7134 }
7135 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007136#ifdef CONFIG_MATCH_IFACE
7137 wpa_s->matched = iface->matched;
7138#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007139
7140 if (iface->bridge_ifname) {
7141 if (os_strlen(iface->bridge_ifname) >=
7142 sizeof(wpa_s->bridge_ifname)) {
7143 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7144 "name '%s'.", iface->bridge_ifname);
7145 return -1;
7146 }
7147 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7148 sizeof(wpa_s->bridge_ifname));
7149 }
7150
7151 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007152 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7153 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007154
7155 /* Initialize driver interface and register driver event handler before
7156 * L2 receive handler so that association events are processed before
7157 * EAPOL-Key packets if both become available for the same select()
7158 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007159 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007160 return -1;
7161
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007162 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7163 return -1;
7164
7165 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7166 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7167 NULL);
7168 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7169
7170 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7171 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7172 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7173 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7174 "dot11RSNAConfigPMKLifetime");
7175 return -1;
7176 }
7177
7178 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7179 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7180 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7181 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7182 "dot11RSNAConfigPMKReauthThreshold");
7183 return -1;
7184 }
7185
7186 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7187 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7188 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7189 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7190 "dot11RSNAConfigSATimeout");
7191 return -1;
7192 }
7193
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007194 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7195 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007196 &wpa_s->hw.flags,
7197 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007198 if (wpa_s->hw.modes) {
7199 u16 i;
7200
7201 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7202 if (wpa_s->hw.modes[i].vht_capab) {
7203 wpa_s->hw_capab = CAPAB_VHT;
7204 break;
7205 }
7206
7207 if (wpa_s->hw.modes[i].ht_capab &
7208 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7209 wpa_s->hw_capab = CAPAB_HT40;
7210 else if (wpa_s->hw.modes[i].ht_capab &&
7211 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7212 wpa_s->hw_capab = CAPAB_HT;
7213 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007214 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007215 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007216
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007217 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7218 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007219 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007220 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007221 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007222 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007223 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007224 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007225 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007226 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007227 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007228 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7229 wpa_s->max_sched_scan_plan_interval =
7230 capa.max_sched_scan_plan_interval;
7231 wpa_s->max_sched_scan_plan_iterations =
7232 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007233 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7234 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007235 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7236 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007237 wpa_s->extended_capa = capa.extended_capa;
7238 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7239 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007240 wpa_s->num_multichan_concurrent =
7241 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007242 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007243 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007244
7245 if (capa.mac_addr_rand_scan_supported)
7246 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7247 if (wpa_s->sched_scan_supported &&
7248 capa.mac_addr_rand_sched_scan_supported)
7249 wpa_s->mac_addr_rand_supported |=
7250 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007251
7252 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7253 if (wpa_s->extended_capa &&
7254 wpa_s->extended_capa_len >= 3 &&
7255 wpa_s->extended_capa[2] & 0x40)
7256 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007257 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007258#ifdef CONFIG_PASN
7259 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7260#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007261 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7262 !!(wpa_s->drv_flags &
7263 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007264 if (wpa_s->max_remain_on_chan == 0)
7265 wpa_s->max_remain_on_chan = 1000;
7266
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007267 /*
7268 * Only take p2p_mgmt parameters when P2P Device is supported.
7269 * Doing it here as it determines whether l2_packet_init() will be done
7270 * during wpa_supplicant_driver_init().
7271 */
7272 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7273 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007274
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007275 if (wpa_s->num_multichan_concurrent == 0)
7276 wpa_s->num_multichan_concurrent = 1;
7277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007278 if (wpa_supplicant_driver_init(wpa_s) < 0)
7279 return -1;
7280
7281#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007282 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007283 return -1;
7284#endif /* CONFIG_TDLS */
7285
7286 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7287 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7288 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7289 return -1;
7290 }
7291
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007292#ifdef CONFIG_FST
7293 if (wpa_s->conf->fst_group_id) {
7294 struct fst_iface_cfg cfg;
7295 struct fst_wpa_obj iface_obj;
7296
7297 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7298 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7299 sizeof(cfg.group_id));
7300 cfg.priority = wpa_s->conf->fst_priority;
7301 cfg.llt = wpa_s->conf->fst_llt;
7302
7303 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7304 &iface_obj, &cfg);
7305 if (!wpa_s->fst) {
7306 wpa_msg(wpa_s, MSG_ERROR,
7307 "FST: Cannot attach iface %s to group %s",
7308 wpa_s->ifname, cfg.group_id);
7309 return -1;
7310 }
7311 }
7312#endif /* CONFIG_FST */
7313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007314 if (wpas_wps_init(wpa_s))
7315 return -1;
7316
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007317#ifdef CONFIG_GAS_SERVER
7318 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7319 if (!wpa_s->gas_server) {
7320 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7321 return -1;
7322 }
7323#endif /* CONFIG_GAS_SERVER */
7324
7325#ifdef CONFIG_DPP
7326 if (wpas_dpp_init(wpa_s) < 0)
7327 return -1;
7328#endif /* CONFIG_DPP */
7329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007330 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7331 return -1;
7332 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7333
7334 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7335 if (wpa_s->ctrl_iface == NULL) {
7336 wpa_printf(MSG_ERROR,
7337 "Failed to initialize control interface '%s'.\n"
7338 "You may have another wpa_supplicant process "
7339 "already running or the file was\n"
7340 "left by an unclean termination of wpa_supplicant "
7341 "in which case you will need\n"
7342 "to manually remove this file before starting "
7343 "wpa_supplicant again.\n",
7344 wpa_s->conf->ctrl_interface);
7345 return -1;
7346 }
7347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007348 wpa_s->gas = gas_query_init(wpa_s);
7349 if (wpa_s->gas == NULL) {
7350 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7351 return -1;
7352 }
7353
Roshan Pius3a1667e2018-07-03 15:17:14 -07007354 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7355 wpa_s->p2p_mgmt) &&
7356 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007357 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7358 return -1;
7359 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007360
7361 if (wpa_bss_init(wpa_s) < 0)
7362 return -1;
7363
Paul Stewart092955c2017-02-06 09:13:09 -08007364#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7365#ifdef CONFIG_MESH
7366 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7367#endif /* CONFIG_MESH */
7368#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7369
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007370 /*
7371 * Set Wake-on-WLAN triggers, if configured.
7372 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7373 * have effect anyway when the interface is down).
7374 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007375 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007376 return -1;
7377
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007378#ifdef CONFIG_EAP_PROXY
7379{
7380 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007381 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7382 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007383 if (wpa_s->mnc_len > 0) {
7384 wpa_s->imsi[len] = '\0';
7385 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7386 wpa_s->imsi, wpa_s->mnc_len);
7387 } else {
7388 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7389 }
7390}
7391#endif /* CONFIG_EAP_PROXY */
7392
Dmitry Shmidt04949592012-07-19 12:16:46 -07007393 if (pcsc_reader_init(wpa_s) < 0)
7394 return -1;
7395
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007396 if (wpas_init_ext_pw(wpa_s) < 0)
7397 return -1;
7398
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007399 wpas_rrm_reset(wpa_s);
7400
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007401 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7402
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007403#ifdef CONFIG_HS20
7404 hs20_init(wpa_s);
7405#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007406#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007407 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007408 if ((wpa_s->conf->oce & OCE_STA) &&
7409 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7410 wpa_s->enable_oce = OCE_STA;
7411 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7412 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7413 /* TODO: Need to add STA-CFON support */
7414 wpa_printf(MSG_ERROR,
7415 "OCE STA-CFON feature is not yet supported");
7416 }
7417 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007418 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7419#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007420
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007421 wpa_supplicant_set_default_scan_ies(wpa_s);
7422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007423 return 0;
7424}
7425
7426
7427static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007428 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007429{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007430 struct wpa_global *global = wpa_s->global;
7431 struct wpa_supplicant *iface, *prev;
7432
Jimmy Chen0e73c002021-08-18 13:21:30 +08007433 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007434 wpas_p2p_group_remove(wpa_s, "*");
7435
7436 iface = global->ifaces;
7437 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007438 if (iface->p2pdev == wpa_s)
7439 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007440 if (iface == wpa_s || iface->parent != wpa_s) {
7441 iface = iface->next;
7442 continue;
7443 }
7444 wpa_printf(MSG_DEBUG,
7445 "Remove remaining child interface %s from parent %s",
7446 iface->ifname, wpa_s->ifname);
7447 prev = iface;
7448 iface = iface->next;
7449 wpa_supplicant_remove_iface(global, prev, terminate);
7450 }
7451
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007452 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007453 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007454 /*
7455 * Don't deauthenticate if WoWLAN is enable and not explicitly
7456 * been configured to disconnect.
7457 */
7458 if (!wpa_drv_get_wowlan(wpa_s) ||
7459 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007460 wpa_supplicant_deauthenticate(
7461 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007462
Hai Shalomfdcde762020-04-02 11:19:20 -07007463 wpa_drv_set_countermeasures(wpa_s, 0);
7464 wpa_clear_keys(wpa_s, NULL);
7465 } else {
7466 wpa_msg(wpa_s, MSG_INFO,
7467 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7468 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007469 }
7470
7471 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007472 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007473
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007474 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007475 radio_remove_interface(wpa_s);
7476
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007477#ifdef CONFIG_FST
7478 if (wpa_s->fst) {
7479 fst_detach(wpa_s->fst);
7480 wpa_s->fst = NULL;
7481 }
7482 if (wpa_s->received_mb_ies) {
7483 wpabuf_free(wpa_s->received_mb_ies);
7484 wpa_s->received_mb_ies = NULL;
7485 }
7486#endif /* CONFIG_FST */
7487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007488 if (wpa_s->drv_priv)
7489 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007490
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007491 if (notify)
7492 wpas_notify_iface_removed(wpa_s);
7493
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007494 if (terminate)
7495 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007496
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007497 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7498 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007499
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007500#ifdef CONFIG_MESH
7501 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007502 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007503 wpa_s->ifmsh = NULL;
7504 }
7505#endif /* CONFIG_MESH */
7506
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007507 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007508 wpa_config_free(wpa_s->conf);
7509 wpa_s->conf = NULL;
7510 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007511
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007512 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007513 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007514
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007515 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007516}
7517
7518
Dmitry Shmidte4663042016-04-04 10:07:49 -07007519#ifdef CONFIG_MATCH_IFACE
7520
7521/**
7522 * wpa_supplicant_match_iface - Match an interface description to a name
7523 * @global: Pointer to global data from wpa_supplicant_init()
7524 * @ifname: Name of the interface to match
7525 * Returns: Pointer to the created interface description or %NULL on failure
7526 */
7527struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7528 const char *ifname)
7529{
7530 int i;
7531 struct wpa_interface *iface, *miface;
7532
7533 for (i = 0; i < global->params.match_iface_count; i++) {
7534 miface = &global->params.match_ifaces[i];
7535 if (!miface->ifname ||
7536 fnmatch(miface->ifname, ifname, 0) == 0) {
7537 iface = os_zalloc(sizeof(*iface));
7538 if (!iface)
7539 return NULL;
7540 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007541 if (!miface->ifname)
7542 iface->matched = WPA_IFACE_MATCHED_NULL;
7543 else
7544 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007545 iface->ifname = ifname;
7546 return iface;
7547 }
7548 }
7549
7550 return NULL;
7551}
7552
7553
7554/**
7555 * wpa_supplicant_match_existing - Match existing interfaces
7556 * @global: Pointer to global data from wpa_supplicant_init()
7557 * Returns: 0 on success, -1 on failure
7558 */
7559static int wpa_supplicant_match_existing(struct wpa_global *global)
7560{
7561 struct if_nameindex *ifi, *ifp;
7562 struct wpa_supplicant *wpa_s;
7563 struct wpa_interface *iface;
7564
7565 ifp = if_nameindex();
7566 if (!ifp) {
7567 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7568 return -1;
7569 }
7570
7571 for (ifi = ifp; ifi->if_name; ifi++) {
7572 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7573 if (wpa_s)
7574 continue;
7575 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7576 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007577 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007578 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007579 }
7580 }
7581
7582 if_freenameindex(ifp);
7583 return 0;
7584}
7585
7586#endif /* CONFIG_MATCH_IFACE */
7587
7588
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007589/**
7590 * wpa_supplicant_add_iface - Add a new network interface
7591 * @global: Pointer to global data from wpa_supplicant_init()
7592 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007593 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007594 * Returns: Pointer to the created interface or %NULL on failure
7595 *
7596 * This function is used to add new network interfaces for %wpa_supplicant.
7597 * This can be called before wpa_supplicant_run() to add interfaces before the
7598 * main event loop has been started. In addition, new interfaces can be added
7599 * dynamically while %wpa_supplicant is already running. This could happen,
7600 * e.g., when a hotplug network adapter is inserted.
7601 */
7602struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007603 struct wpa_interface *iface,
7604 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007605{
7606 struct wpa_supplicant *wpa_s;
7607 struct wpa_interface t_iface;
7608 struct wpa_ssid *ssid;
7609
7610 if (global == NULL || iface == NULL)
7611 return NULL;
7612
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007613 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007614 if (wpa_s == NULL)
7615 return NULL;
7616
7617 wpa_s->global = global;
7618
7619 t_iface = *iface;
7620 if (global->params.override_driver) {
7621 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7622 "('%s' -> '%s')",
7623 iface->driver, global->params.override_driver);
7624 t_iface.driver = global->params.override_driver;
7625 }
7626 if (global->params.override_ctrl_interface) {
7627 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7628 "ctrl_interface ('%s' -> '%s')",
7629 iface->ctrl_interface,
7630 global->params.override_ctrl_interface);
7631 t_iface.ctrl_interface =
7632 global->params.override_ctrl_interface;
7633 }
7634 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7635 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7636 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007637 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007638 return NULL;
7639 }
7640
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007641 /* Notify the control interfaces about new iface */
7642 if (wpas_notify_iface_added(wpa_s)) {
7643 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7644 return NULL;
7645 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007646
Jimmy Chene2206be2022-07-10 10:25:21 +08007647 /* Notify the control interfaces about new networks */
7648 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7649 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007650 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007651 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7652 && os_strncmp((const char *) ssid->ssid,
7653 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7654 wpas_notify_persistent_group_added(wpa_s, ssid);
7655 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007656 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007657
7658 wpa_s->next = global->ifaces;
7659 global->ifaces = wpa_s;
7660
7661 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007662 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007663
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007664#ifdef CONFIG_P2P
7665 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007666 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007667 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007668 wpas_p2p_add_p2pdev_interface(
7669 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007670 wpa_printf(MSG_INFO,
7671 "P2P: Failed to enable P2P Device interface");
7672 /* Try to continue without. P2P will be disabled. */
7673 }
7674#endif /* CONFIG_P2P */
7675
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007676 return wpa_s;
7677}
7678
7679
7680/**
7681 * wpa_supplicant_remove_iface - Remove a network interface
7682 * @global: Pointer to global data from wpa_supplicant_init()
7683 * @wpa_s: Pointer to the network interface to be removed
7684 * Returns: 0 if interface was removed, -1 if interface was not found
7685 *
7686 * This function can be used to dynamically remove network interfaces from
7687 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7688 * addition, this function is used to remove all remaining interfaces when
7689 * %wpa_supplicant is terminated.
7690 */
7691int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007692 struct wpa_supplicant *wpa_s,
7693 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007694{
7695 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007696#ifdef CONFIG_MESH
7697 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7698 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007699 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007700#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007701
7702 /* Remove interface from the global list of interfaces */
7703 prev = global->ifaces;
7704 if (prev == wpa_s) {
7705 global->ifaces = wpa_s->next;
7706 } else {
7707 while (prev && prev->next != wpa_s)
7708 prev = prev->next;
7709 if (prev == NULL)
7710 return -1;
7711 prev->next = wpa_s->next;
7712 }
7713
7714 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7715
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007716#ifdef CONFIG_MESH
7717 if (mesh_if_created) {
7718 ifname = os_strdup(wpa_s->ifname);
7719 if (ifname == NULL) {
7720 wpa_dbg(wpa_s, MSG_ERROR,
7721 "mesh: Failed to malloc ifname");
7722 return -1;
7723 }
7724 }
7725#endif /* CONFIG_MESH */
7726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007727 if (global->p2p_group_formation == wpa_s)
7728 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007729 if (global->p2p_invite_group == wpa_s)
7730 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007731 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007732
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007733#ifdef CONFIG_MESH
7734 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007735 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007736 os_free(ifname);
7737 }
7738#endif /* CONFIG_MESH */
7739
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007740 return 0;
7741}
7742
7743
7744/**
7745 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7746 * @wpa_s: Pointer to the network interface
7747 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7748 */
7749const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7750{
7751 const char *eapol_method;
7752
7753 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7754 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7755 return "NO-EAP";
7756 }
7757
7758 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7759 if (eapol_method == NULL)
7760 return "UNKNOWN-EAP";
7761
7762 return eapol_method;
7763}
7764
7765
7766/**
7767 * wpa_supplicant_get_iface - Get a new network interface
7768 * @global: Pointer to global data from wpa_supplicant_init()
7769 * @ifname: Interface name
7770 * Returns: Pointer to the interface or %NULL if not found
7771 */
7772struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7773 const char *ifname)
7774{
7775 struct wpa_supplicant *wpa_s;
7776
7777 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7778 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7779 return wpa_s;
7780 }
7781 return NULL;
7782}
7783
7784
7785#ifndef CONFIG_NO_WPA_MSG
7786static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7787{
7788 struct wpa_supplicant *wpa_s = ctx;
7789 if (wpa_s == NULL)
7790 return NULL;
7791 return wpa_s->ifname;
7792}
7793#endif /* CONFIG_NO_WPA_MSG */
7794
7795
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007796#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7797#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7798#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7799
7800/* Periodic cleanup tasks */
7801static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7802{
7803 struct wpa_global *global = eloop_ctx;
7804 struct wpa_supplicant *wpa_s;
7805
7806 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7807 wpas_periodic, global, NULL);
7808
7809#ifdef CONFIG_P2P
7810 if (global->p2p)
7811 p2p_expire_peers(global->p2p);
7812#endif /* CONFIG_P2P */
7813
7814 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7815 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7816#ifdef CONFIG_AP
7817 ap_periodic(wpa_s);
7818#endif /* CONFIG_AP */
7819 }
7820}
7821
7822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007823/**
7824 * wpa_supplicant_init - Initialize %wpa_supplicant
7825 * @params: Parameters for %wpa_supplicant
7826 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7827 *
7828 * This function is used to initialize %wpa_supplicant. After successful
7829 * initialization, the returned data pointer can be used to add and remove
7830 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7831 */
7832struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7833{
7834 struct wpa_global *global;
7835 int ret, i;
7836
7837 if (params == NULL)
7838 return NULL;
7839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007840#ifdef CONFIG_DRIVER_NDIS
7841 {
7842 void driver_ndis_init_ops(void);
7843 driver_ndis_init_ops();
7844 }
7845#endif /* CONFIG_DRIVER_NDIS */
7846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007847#ifndef CONFIG_NO_WPA_MSG
7848 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7849#endif /* CONFIG_NO_WPA_MSG */
7850
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007851 if (params->wpa_debug_file_path)
7852 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007853 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007854 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007855 if (params->wpa_debug_syslog)
7856 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007857 if (params->wpa_debug_tracing) {
7858 ret = wpa_debug_open_linux_tracing();
7859 if (ret) {
7860 wpa_printf(MSG_ERROR,
7861 "Failed to enable trace logging");
7862 return NULL;
7863 }
7864 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007865
7866 ret = eap_register_methods();
7867 if (ret) {
7868 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7869 if (ret == -2)
7870 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7871 "the same EAP type.");
7872 return NULL;
7873 }
7874
7875 global = os_zalloc(sizeof(*global));
7876 if (global == NULL)
7877 return NULL;
7878 dl_list_init(&global->p2p_srv_bonjour);
7879 dl_list_init(&global->p2p_srv_upnp);
7880 global->params.daemonize = params->daemonize;
7881 global->params.wait_for_monitor = params->wait_for_monitor;
7882 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007883
7884 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007885 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007886 if (!global->params.pid_file) {
7887 wpa_supplicant_deinit(global);
7888 return NULL;
7889 }
7890 }
7891
7892 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007893 global->params.ctrl_interface =
7894 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007895 if (!global->params.ctrl_interface) {
7896 wpa_supplicant_deinit(global);
7897 return NULL;
7898 }
7899 }
7900
7901 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007902 global->params.ctrl_interface_group =
7903 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007904 if (!global->params.ctrl_interface_group) {
7905 wpa_supplicant_deinit(global);
7906 return NULL;
7907 }
7908 }
7909
7910 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007911 global->params.override_driver =
7912 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007913 if (!global->params.override_driver) {
7914 wpa_supplicant_deinit(global);
7915 return NULL;
7916 }
7917 }
7918
7919 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007920 global->params.override_ctrl_interface =
7921 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007922 if (!global->params.override_ctrl_interface) {
7923 wpa_supplicant_deinit(global);
7924 return NULL;
7925 }
7926 }
7927
Dmitry Shmidte4663042016-04-04 10:07:49 -07007928#ifdef CONFIG_MATCH_IFACE
7929 global->params.match_iface_count = params->match_iface_count;
7930 if (params->match_iface_count) {
7931 global->params.match_ifaces =
7932 os_calloc(params->match_iface_count,
7933 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007934 if (!global->params.match_ifaces) {
7935 wpa_printf(MSG_ERROR,
7936 "Failed to allocate match interfaces");
7937 wpa_supplicant_deinit(global);
7938 return NULL;
7939 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007940 os_memcpy(global->params.match_ifaces,
7941 params->match_ifaces,
7942 params->match_iface_count *
7943 sizeof(struct wpa_interface));
7944 }
7945#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007946#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007947 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007948 global->params.conf_p2p_dev =
7949 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007950 if (!global->params.conf_p2p_dev) {
7951 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7952 wpa_supplicant_deinit(global);
7953 return NULL;
7954 }
7955 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007956#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007957 wpa_debug_level = global->params.wpa_debug_level =
7958 params->wpa_debug_level;
7959 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7960 params->wpa_debug_show_keys;
7961 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7962 params->wpa_debug_timestamp;
7963
Hai Shalomfdcde762020-04-02 11:19:20 -07007964 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007965
7966 if (eloop_init()) {
7967 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7968 wpa_supplicant_deinit(global);
7969 return NULL;
7970 }
7971
Jouni Malinen75ecf522011-06-27 15:19:46 -07007972 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007973
7974 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7975 if (global->ctrl_iface == NULL) {
7976 wpa_supplicant_deinit(global);
7977 return NULL;
7978 }
7979
7980 if (wpas_notify_supplicant_initialized(global)) {
7981 wpa_supplicant_deinit(global);
7982 return NULL;
7983 }
7984
7985 for (i = 0; wpa_drivers[i]; i++)
7986 global->drv_count++;
7987 if (global->drv_count == 0) {
7988 wpa_printf(MSG_ERROR, "No drivers enabled");
7989 wpa_supplicant_deinit(global);
7990 return NULL;
7991 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007992 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007993 if (global->drv_priv == NULL) {
7994 wpa_supplicant_deinit(global);
7995 return NULL;
7996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007997
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007998#ifdef CONFIG_WIFI_DISPLAY
7999 if (wifi_display_init(global) < 0) {
8000 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8001 wpa_supplicant_deinit(global);
8002 return NULL;
8003 }
8004#endif /* CONFIG_WIFI_DISPLAY */
8005
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008006 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8007 wpas_periodic, global, NULL);
8008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008009 return global;
8010}
8011
8012
8013/**
8014 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8015 * @global: Pointer to global data from wpa_supplicant_init()
8016 * Returns: 0 after successful event loop run, -1 on failure
8017 *
8018 * This function starts the main event loop and continues running as long as
8019 * there are any remaining events. In most cases, this function is running as
8020 * long as the %wpa_supplicant process in still in use.
8021 */
8022int wpa_supplicant_run(struct wpa_global *global)
8023{
8024 struct wpa_supplicant *wpa_s;
8025
8026 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008027 (wpa_supplicant_daemon(global->params.pid_file) ||
8028 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008029 return -1;
8030
Dmitry Shmidte4663042016-04-04 10:07:49 -07008031#ifdef CONFIG_MATCH_IFACE
8032 if (wpa_supplicant_match_existing(global))
8033 return -1;
8034#endif
8035
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008036 if (global->params.wait_for_monitor) {
8037 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008038 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008039 wpa_supplicant_ctrl_iface_wait(
8040 wpa_s->ctrl_iface);
8041 }
8042
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008043#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008044 // If daemonize is enabled, initialize AIDL here.
8045 if (global->params.daemonize) {
8046 global->aidl = wpas_aidl_init(global);
8047 if (!global->aidl)
8048 return -1;
8049 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008050#endif /* CONFIG_AIDL */
8051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008052 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8053 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8054
8055 eloop_run();
8056
8057 return 0;
8058}
8059
8060
8061/**
8062 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8063 * @global: Pointer to global data from wpa_supplicant_init()
8064 *
8065 * This function is called to deinitialize %wpa_supplicant and to free all
8066 * allocated resources. Remaining network interfaces will also be removed.
8067 */
8068void wpa_supplicant_deinit(struct wpa_global *global)
8069{
8070 int i;
8071
8072 if (global == NULL)
8073 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008074
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008075 eloop_cancel_timeout(wpas_periodic, global, NULL);
8076
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008077#ifdef CONFIG_WIFI_DISPLAY
8078 wifi_display_deinit(global);
8079#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008080
8081 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008082 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008083
8084 if (global->ctrl_iface)
8085 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8086
8087 wpas_notify_supplicant_deinitialized(global);
8088
8089 eap_peer_unregister_methods();
8090#ifdef CONFIG_AP
8091 eap_server_unregister_methods();
8092#endif /* CONFIG_AP */
8093
8094 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8095 if (!global->drv_priv[i])
8096 continue;
8097 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8098 }
8099 os_free(global->drv_priv);
8100
8101 random_deinit();
8102
8103 eloop_destroy();
8104
8105 if (global->params.pid_file) {
8106 os_daemonize_terminate(global->params.pid_file);
8107 os_free(global->params.pid_file);
8108 }
8109 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008110 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008111 os_free(global->params.override_driver);
8112 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008113#ifdef CONFIG_MATCH_IFACE
8114 os_free(global->params.match_ifaces);
8115#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008116#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008117 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008118#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008119
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008120 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008121 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008122 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008123
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008124 os_free(global);
8125 wpa_debug_close_syslog();
8126 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008127 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008128}
8129
8130
8131void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8132{
8133 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8134 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8135 char country[3];
8136 country[0] = wpa_s->conf->country[0];
8137 country[1] = wpa_s->conf->country[1];
8138 country[2] = '\0';
8139 if (wpa_drv_set_country(wpa_s, country) < 0) {
8140 wpa_printf(MSG_ERROR, "Failed to set country code "
8141 "'%s'", country);
8142 }
8143 }
8144
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008145 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8146 wpas_init_ext_pw(wpa_s);
8147
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008148 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8149 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8150
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008151 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8152 struct wpa_driver_capa capa;
8153 int res = wpa_drv_get_capa(wpa_s, &capa);
8154
8155 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8156 wpa_printf(MSG_ERROR,
8157 "Failed to update wowlan_triggers to '%s'",
8158 wpa_s->conf->wowlan_triggers);
8159 }
8160
Hai Shalom81f62d82019-07-22 12:10:00 -07008161 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8162 wpa_supplicant_set_default_scan_ies(wpa_s);
8163
Hai Shalom899fcc72020-10-19 14:38:18 -07008164#ifdef CONFIG_BGSCAN
8165 /*
8166 * We default to global bgscan parameters only when per-network bgscan
8167 * parameters aren't set. Only bother resetting bgscan parameters if
8168 * this is the case.
8169 */
8170 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8171 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8172 wpa_s->wpa_state == WPA_COMPLETED)
8173 wpa_supplicant_reset_bgscan(wpa_s);
8174#endif /* CONFIG_BGSCAN */
8175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008176#ifdef CONFIG_WPS
8177 wpas_wps_update_config(wpa_s);
8178#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008179 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008180 wpa_s->conf->changed_parameters = 0;
8181}
8182
8183
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008184void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008185{
8186 int i;
8187
8188 for (i = 0; i < *num_freqs; i++) {
8189 if (freqs[i] == freq)
8190 return;
8191 }
8192
8193 freqs[*num_freqs] = freq;
8194 (*num_freqs)++;
8195}
8196
8197
8198static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8199{
8200 struct wpa_bss *bss, *cbss;
8201 const int max_freqs = 10;
8202 int *freqs;
8203 int num_freqs = 0;
8204
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008205 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008206 if (freqs == NULL)
8207 return NULL;
8208
8209 cbss = wpa_s->current_bss;
8210
8211 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8212 if (bss == cbss)
8213 continue;
8214 if (bss->ssid_len == cbss->ssid_len &&
8215 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008216 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008217 add_freq(freqs, &num_freqs, bss->freq);
8218 if (num_freqs == max_freqs)
8219 break;
8220 }
8221 }
8222
8223 if (num_freqs == 0) {
8224 os_free(freqs);
8225 freqs = NULL;
8226 }
8227
8228 return freqs;
8229}
8230
8231
8232void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8233{
8234 int timeout;
8235 int count;
8236 int *freqs = NULL;
8237
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008238 wpas_connect_work_done(wpa_s);
8239
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008240 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008241 * Remove possible authentication timeout since the connection failed.
8242 */
8243 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8244
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008245 /*
Hai Shalom60840252021-02-19 19:02:11 -08008246 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008247 * generated based on local request to disconnect.
8248 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008249 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008250 wpa_s->own_disconnect_req = 0;
8251 wpa_dbg(wpa_s, MSG_DEBUG,
8252 "Ignore connection failure due to local request to disconnect");
8253 return;
8254 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008255 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008256 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8257 "indication since interface has been put into "
8258 "disconnected state");
8259 return;
8260 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008261 if (wpa_s->auto_reconnect_disabled) {
8262 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8263 "indication since auto connect is disabled");
8264 return;
8265 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008266
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008267 /*
Hai Shalom60840252021-02-19 19:02:11 -08008268 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008269 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008270 */
Hai Shalom60840252021-02-19 19:02:11 -08008271 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008272 if (count == 1 && wpa_s->current_bss) {
8273 /*
Hai Shalom60840252021-02-19 19:02:11 -08008274 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008275 * another BSS available for the same ESS, we should try that
8276 * next. Otherwise, we may as well try this one once more
8277 * before allowing other, likely worse, ESSes to be considered.
8278 */
8279 freqs = get_bss_freqs_in_ess(wpa_s);
8280 if (freqs) {
8281 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8282 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008283 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008284 /*
8285 * On the next scan, go through only the known channels
8286 * used in this ESS based on previous scans to speed up
8287 * common load balancing use case.
8288 */
8289 os_free(wpa_s->next_scan_freqs);
8290 wpa_s->next_scan_freqs = freqs;
8291 }
8292 }
8293
Hai Shalom899fcc72020-10-19 14:38:18 -07008294 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008295
Hai Shalom899fcc72020-10-19 14:38:18 -07008296 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008297 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8298 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008299 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008300 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008301 /*
8302 * Multiple consecutive connection failures mean that other APs are
8303 * either not available or have already been tried, so we can start
8304 * increasing the delay here to avoid constant scanning.
8305 */
8306 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008307 case 1:
8308 timeout = 100;
8309 break;
8310 case 2:
8311 timeout = 500;
8312 break;
8313 case 3:
8314 timeout = 1000;
8315 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008316 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008317 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008318 break;
8319 default:
8320 timeout = 10000;
8321 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008322 }
8323
Hai Shalom899fcc72020-10-19 14:38:18 -07008324 wpa_dbg(wpa_s, MSG_DEBUG,
8325 "Consecutive connection failures: %d --> request scan in %d ms",
8326 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008328 /*
8329 * TODO: if more than one possible AP is available in scan results,
8330 * could try the other ones before requesting a new scan.
8331 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008332
8333 /* speed up the connection attempt with normal scan */
8334 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008335 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8336 1000 * (timeout % 1000));
8337}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008338
8339
Hai Shalomce48b4a2018-09-05 11:41:35 -07008340#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008341
8342void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8343{
8344 struct wpa_ssid *ssid = wpa_s->current_ssid;
8345 const u8 *realm, *username, *rrk;
8346 size_t realm_len, username_len, rrk_len;
8347 u16 next_seq_num;
8348
8349 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8350 * Check for ERP keys existing to limit when this can be done since
8351 * the rejection response is not protected and such triggers should
8352 * really not allow internal state to be modified unless required to
8353 * avoid significant issues in functionality. In addition, drop
8354 * externally configure PMKSA entries even without ERP keys since it
8355 * is possible for an external component to add PMKSA entries for FILS
8356 * authentication without restoring previously generated ERP keys.
8357 *
8358 * In this case, this is needed to allow recovery from cases where the
8359 * AP or authentication server has dropped PMKSAs and ERP keys. */
8360 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8361 return;
8362
8363 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8364 &username, &username_len,
8365 &realm, &realm_len, &next_seq_num,
8366 &rrk, &rrk_len) != 0 ||
8367 !realm) {
8368 wpa_dbg(wpa_s, MSG_DEBUG,
8369 "FILS: Drop external PMKSA cache entry");
8370 wpa_sm_aborted_external_cached(wpa_s->wpa);
8371 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8372 return;
8373 }
8374
8375 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8376 wpa_sm_aborted_cached(wpa_s->wpa);
8377 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8378}
8379
8380
Hai Shalomce48b4a2018-09-05 11:41:35 -07008381void fils_connection_failure(struct wpa_supplicant *wpa_s)
8382{
8383 struct wpa_ssid *ssid = wpa_s->current_ssid;
8384 const u8 *realm, *username, *rrk;
8385 size_t realm_len, username_len, rrk_len;
8386 u16 next_seq_num;
8387
8388 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8389 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8390 &username, &username_len,
8391 &realm, &realm_len, &next_seq_num,
8392 &rrk, &rrk_len) != 0 ||
8393 !realm)
8394 return;
8395
8396 wpa_hexdump_ascii(MSG_DEBUG,
8397 "FILS: Store last connection failure realm",
8398 realm, realm_len);
8399 os_free(wpa_s->last_con_fail_realm);
8400 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8401 if (wpa_s->last_con_fail_realm) {
8402 wpa_s->last_con_fail_realm_len = realm_len;
8403 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8404 }
8405}
8406#endif /* CONFIG_FILS */
8407
8408
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008409int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8410{
8411 return wpa_s->conf->ap_scan == 2 ||
8412 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8413}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008414
Dmitry Shmidt04949592012-07-19 12:16:46 -07008415
Gabriel Biren57ededa2021-09-03 16:08:50 +00008416#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008417int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8418 struct wpa_ssid *ssid,
8419 const char *field,
8420 const char *value)
8421{
8422#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008423 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008424
8425 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8426 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8427 (const u8 *) value, os_strlen(value));
8428
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008429 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008430 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008431#else /* IEEE8021X_EAPOL */
8432 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8433 return -1;
8434#endif /* IEEE8021X_EAPOL */
8435}
8436
8437int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8438 struct wpa_ssid *ssid,
8439 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008440 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008441{
8442#ifdef IEEE8021X_EAPOL
8443 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008444 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008445
8446 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008447 case WPA_CTRL_REQ_EAP_IDENTITY:
8448 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008449 os_free(eap->imsi_identity);
8450 if (value == NULL)
8451 return -1;
8452 identity = os_strchr(value, ':');
8453 if (identity == NULL) {
8454 /* plain identity */
8455 eap->identity = (u8 *)os_strdup(value);
8456 eap->identity_len = os_strlen(value);
8457 } else {
8458 /* have both plain identity and encrypted identity */
8459 imsi_identity = value;
8460 *identity++ = '\0';
8461 /* plain identity */
8462 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8463 eap->imsi_identity_len = strlen(imsi_identity);
8464 /* encrypted identity */
8465 eap->identity = (u8 *)dup_binstr(identity,
8466 value_len - strlen(imsi_identity) - 1);
8467 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8468 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008469 eap->pending_req_identity = 0;
8470 if (ssid == wpa_s->current_ssid)
8471 wpa_s->reassociate = 1;
8472 break;
8473 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008474 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008475 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008476 if (!eap->password)
8477 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008478 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008479 eap->pending_req_password = 0;
8480 if (ssid == wpa_s->current_ssid)
8481 wpa_s->reassociate = 1;
8482 break;
8483 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008484 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008485 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008486 if (!eap->new_password)
8487 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008488 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008489 eap->pending_req_new_password = 0;
8490 if (ssid == wpa_s->current_ssid)
8491 wpa_s->reassociate = 1;
8492 break;
8493 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008494 str_clear_free(eap->cert.pin);
8495 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008496 if (!eap->cert.pin)
8497 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008498 eap->pending_req_pin = 0;
8499 if (ssid == wpa_s->current_ssid)
8500 wpa_s->reassociate = 1;
8501 break;
8502 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008503 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008504 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008505 if (!eap->otp)
8506 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008507 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008508 os_free(eap->pending_req_otp);
8509 eap->pending_req_otp = NULL;
8510 eap->pending_req_otp_len = 0;
8511 break;
8512 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008513 str_clear_free(eap->cert.private_key_passwd);
8514 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008515 if (!eap->cert.private_key_passwd)
8516 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008517 eap->pending_req_passphrase = 0;
8518 if (ssid == wpa_s->current_ssid)
8519 wpa_s->reassociate = 1;
8520 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008521 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008522 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008523 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008524 if (!eap->external_sim_resp)
8525 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008526 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008527 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008528 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8529 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8530 return -1;
8531 ssid->mem_only_psk = 1;
8532 if (ssid->passphrase)
8533 wpa_config_update_psk(ssid);
8534 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8535 wpa_supplicant_req_scan(wpa_s, 0, 0);
8536 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008537 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8538 if (eap->pending_ext_cert_check != PENDING_CHECK)
8539 return -1;
8540 if (os_strcmp(value, "good") == 0)
8541 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8542 else if (os_strcmp(value, "bad") == 0)
8543 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8544 else
8545 return -1;
8546 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008547 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008548 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008549 return -1;
8550 }
8551
8552 return 0;
8553#else /* IEEE8021X_EAPOL */
8554 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8555 return -1;
8556#endif /* IEEE8021X_EAPOL */
8557}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008558#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008559
8560
8561int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8562{
Hai Shalomfdcde762020-04-02 11:19:20 -07008563#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008564 int i;
8565 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008566#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008567
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008568 if (wpa_s->p2p_mgmt)
8569 return 1; /* no normal network profiles on p2p_mgmt interface */
8570
Dmitry Shmidt04949592012-07-19 12:16:46 -07008571 if (ssid == NULL)
8572 return 1;
8573
8574 if (ssid->disabled)
8575 return 1;
8576
Hai Shalomfdcde762020-04-02 11:19:20 -07008577#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008578 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008579 drv_enc = wpa_s->drv_enc;
8580 else
8581 drv_enc = (unsigned int) -1;
8582
8583 for (i = 0; i < NUM_WEP_KEYS; i++) {
8584 size_t len = ssid->wep_key_len[i];
8585 if (len == 0)
8586 continue;
8587 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8588 continue;
8589 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8590 continue;
8591 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8592 continue;
8593 return 1; /* invalid WEP key */
8594 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008595#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008596
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008597 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008598 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008599 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008600 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008601 return 1;
8602
Sunil Ravi89eba102022-09-13 21:04:37 -07008603#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008604#ifdef CRYPTO_RSA_OAEP_SHA256
8605 if (ssid->eap.imsi_privacy_cert) {
8606 struct crypto_rsa_key *key;
8607 bool failed = false;
8608
8609 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8610 if (!key)
8611 failed = true;
8612 crypto_rsa_key_free(key);
8613 if (failed) {
8614 wpa_printf(MSG_DEBUG,
8615 "Invalid imsi_privacy_cert (%s) - disable network",
8616 ssid->eap.imsi_privacy_cert);
8617 return 1;
8618 }
8619 }
8620#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008621#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008622
Dmitry Shmidt04949592012-07-19 12:16:46 -07008623 return 0;
8624}
8625
8626
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008627int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8628{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008629 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8630 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8631 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8632 /*
8633 * Driver does not support BIP -- ignore pmf=1 default
8634 * since the connection with PMF would fail and the
8635 * configuration does not require PMF to be enabled.
8636 */
8637 return NO_MGMT_FRAME_PROTECTION;
8638 }
8639
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008640 if (ssid &&
8641 (ssid->key_mgmt &
8642 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8643 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8644 /*
8645 * Do not use the default PMF value for non-RSN networks
8646 * since PMF is available only with RSN and pmf=2
8647 * configuration would otherwise prevent connections to
8648 * all open networks.
8649 */
8650 return NO_MGMT_FRAME_PROTECTION;
8651 }
8652
Sunil Ravi77d572f2023-01-17 23:58:31 +00008653#ifdef CONFIG_OCV
8654 /* Enable PMF if OCV is being enabled */
8655 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8656 ssid && ssid->ocv)
8657 return MGMT_FRAME_PROTECTION_OPTIONAL;
8658#endif /* CONFIG_OCV */
8659
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008660 return wpa_s->conf->pmf;
8661 }
8662
8663 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008664}
8665
8666
Sunil Ravi77d572f2023-01-17 23:58:31 +00008667#ifdef CONFIG_SAE
8668bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8669 struct wpa_ssid *ssid,
8670 const struct wpa_ie_data *ie)
8671{
8672 return wpa_s->conf->sae_check_mfp &&
8673 (!(ie->capabilities &
8674 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8675 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8676}
8677#endif /* CONFIG_SAE */
8678
8679
Hai Shalomc1a21442022-02-04 13:43:00 -08008680int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8681{
8682 if (wpa_s->current_ssid == NULL ||
8683 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8684 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8685 return 0;
8686 return wpa_sm_pmf_enabled(wpa_s->wpa);
8687}
8688
8689
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008690int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008691{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008692 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008693 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008694 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008695 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008696 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008697}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008698
8699
Sunil Ravi77d572f2023-01-17 23:58:31 +00008700void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8701 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008702{
8703 struct wpa_ssid *ssid = wpa_s->current_ssid;
8704 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008705 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008706
8707 if (ssid == NULL) {
8708 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8709 "SSID block");
8710 return;
8711 }
8712
8713 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8714 return;
8715
8716 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008717
8718#ifdef CONFIG_P2P
8719 if (ssid->p2p_group &&
8720 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8721 /*
8722 * Skip the wait time since there is a short timeout on the
8723 * connection to a P2P group.
8724 */
8725 return;
8726 }
8727#endif /* CONFIG_P2P */
8728
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008729 if (ssid->auth_failures > 50)
8730 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008731 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008732 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008733 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008734 dur = 90;
8735 else if (ssid->auth_failures > 3)
8736 dur = 60;
8737 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008738 dur = 30;
8739 else if (ssid->auth_failures > 1)
8740 dur = 20;
8741 else
8742 dur = 10;
8743
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008744 if (ssid->auth_failures > 1 &&
8745 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8746 dur += os_random() % (ssid->auth_failures * 10);
8747
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008748 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008749 if (now.sec + dur <= ssid->disabled_until.sec)
8750 return;
8751
8752 ssid->disabled_until.sec = now.sec + dur;
8753
8754 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008755 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008756 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008757 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008758
8759 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8760 int msg_len = snprintf(NULL, 0, format_str,
8761 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8762 ssid->auth_failures, dur, reason) + 1;
8763 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308764 if (!msg)
8765 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008766 snprintf(msg, msg_len, format_str,
8767 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8768 ssid->auth_failures, dur, reason);
8769 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8770 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008771
8772 if (bssid)
8773 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008774}
8775
8776
8777void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8778 struct wpa_ssid *ssid, int clear_failures)
8779{
8780 if (ssid == NULL)
8781 return;
8782
8783 if (ssid->disabled_until.sec) {
8784 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8785 "id=%d ssid=\"%s\"",
8786 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8787 }
8788 ssid->disabled_until.sec = 0;
8789 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008790 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008791 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008792 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8793 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8794 " ignored to allow a lower priority BSS, if any, to be tried next",
8795 MAC2STR(ssid->disabled_due_to));
8796 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8797 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8798 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008799}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008800
8801
8802int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8803{
8804 size_t i;
8805
8806 if (wpa_s->disallow_aps_bssid == NULL)
8807 return 0;
8808
8809 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8810 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8811 bssid, ETH_ALEN) == 0)
8812 return 1;
8813 }
8814
8815 return 0;
8816}
8817
8818
8819int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8820 size_t ssid_len)
8821{
8822 size_t i;
8823
8824 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8825 return 0;
8826
8827 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8828 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8829 if (ssid_len == s->ssid_len &&
8830 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8831 return 1;
8832 }
8833
8834 return 0;
8835}
8836
8837
8838/**
8839 * wpas_request_connection - Request a new connection
8840 * @wpa_s: Pointer to the network interface
8841 *
8842 * This function is used to request a new connection to be found. It will mark
8843 * the interface to allow reassociation and request a new scan to find a
8844 * suitable network to connect to.
8845 */
8846void wpas_request_connection(struct wpa_supplicant *wpa_s)
8847{
8848 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008849 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008850 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008851 wpa_s->disconnected = 0;
8852 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008853 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008854
8855 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8856 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008857 else
8858 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008859}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008860
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008861
Roshan Pius02242d72016-08-09 15:31:48 -07008862/**
8863 * wpas_request_disconnection - Request disconnection
8864 * @wpa_s: Pointer to the network interface
8865 *
8866 * This function is used to request disconnection from the currently connected
8867 * network. This will stop any ongoing scans and initiate deauthentication.
8868 */
8869void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8870{
8871#ifdef CONFIG_SME
8872 wpa_s->sme.prev_bssid_set = 0;
8873#endif /* CONFIG_SME */
8874 wpa_s->reassociate = 0;
8875 wpa_s->disconnected = 1;
8876 wpa_supplicant_cancel_sched_scan(wpa_s);
8877 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008878 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008879 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8880 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008881 radio_remove_works(wpa_s, "connect", 0);
8882 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008883 wpa_s->roam_in_progress = false;
8884#ifdef CONFIG_WNM
8885 wpa_s->bss_trans_mgmt_in_progress = false;
8886#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008887}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008888
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008889
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008890void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8891 struct wpa_used_freq_data *freqs_data,
8892 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008893{
8894 unsigned int i;
8895
8896 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8897 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008898 for (i = 0; i < len; i++) {
8899 struct wpa_used_freq_data *cur = &freqs_data[i];
8900 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8901 i, cur->freq, cur->flags);
8902 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008903}
8904
8905
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008906/*
8907 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008908 * are using the same radio as the current interface, and in addition, get
8909 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008910 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008911int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8912 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008913 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008914{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008915 struct wpa_supplicant *ifs;
8916 u8 bssid[ETH_ALEN];
8917 int freq;
8918 unsigned int idx = 0, i;
8919
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008920 wpa_dbg(wpa_s, MSG_DEBUG,
8921 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008922 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008923
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008924 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8925 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008926 if (idx == len)
8927 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008928
Sunil Ravi77d572f2023-01-17 23:58:31 +00008929 if (exclude_current && ifs == wpa_s)
8930 continue;
8931
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008932 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8933 continue;
8934
8935 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008936 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8937 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008938 freq = ifs->current_ssid->frequency;
8939 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8940 freq = ifs->assoc_freq;
8941 else
8942 continue;
8943
8944 /* Hold only distinct freqs */
8945 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008946 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008947 break;
8948
8949 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008950 freqs_data[idx++].freq = freq;
8951
8952 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008953 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008954 WPA_FREQ_USED_BY_P2P_CLIENT :
8955 WPA_FREQ_USED_BY_INFRA_STATION;
8956 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008957 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008958
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008959 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008960 return idx;
8961}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008962
8963
8964/*
8965 * Find the operating frequencies of any of the virtual interfaces that
8966 * are using the same radio as the current interface.
8967 */
8968int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008969 int *freq_array, unsigned int len,
8970 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008971{
8972 struct wpa_used_freq_data *freqs_data;
8973 int num, i;
8974
8975 os_memset(freq_array, 0, sizeof(int) * len);
8976
8977 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8978 if (!freqs_data)
8979 return -1;
8980
Sunil Ravi77d572f2023-01-17 23:58:31 +00008981 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8982 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008983 for (i = 0; i < num; i++)
8984 freq_array[i] = freqs_data[i].freq;
8985
8986 os_free(freqs_data);
8987
8988 return num;
8989}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008990
8991
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008992struct wpa_supplicant *
8993wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8994{
8995 switch (frame) {
8996#ifdef CONFIG_P2P
8997 case VENDOR_ELEM_PROBE_REQ_P2P:
8998 case VENDOR_ELEM_PROBE_RESP_P2P:
8999 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9000 case VENDOR_ELEM_BEACON_P2P_GO:
9001 case VENDOR_ELEM_P2P_PD_REQ:
9002 case VENDOR_ELEM_P2P_PD_RESP:
9003 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9004 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9005 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9006 case VENDOR_ELEM_P2P_INV_REQ:
9007 case VENDOR_ELEM_P2P_INV_RESP:
9008 case VENDOR_ELEM_P2P_ASSOC_REQ:
9009 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009010 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009011#endif /* CONFIG_P2P */
9012 default:
9013 return wpa_s;
9014 }
9015}
9016
9017
9018void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9019{
9020 unsigned int i;
9021 char buf[30];
9022
9023 wpa_printf(MSG_DEBUG, "Update vendor elements");
9024
9025 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9026 if (wpa_s->vendor_elem[i]) {
9027 int res;
9028
9029 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9030 if (!os_snprintf_error(sizeof(buf), res)) {
9031 wpa_hexdump_buf(MSG_DEBUG, buf,
9032 wpa_s->vendor_elem[i]);
9033 }
9034 }
9035 }
9036
9037#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009038 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009039 wpa_s->global->p2p &&
9040 !wpa_s->global->p2p_disabled)
9041 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9042#endif /* CONFIG_P2P */
9043}
9044
9045
9046int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9047 const u8 *elem, size_t len)
9048{
9049 u8 *ie, *end;
9050
9051 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9052 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9053
9054 for (; ie + 1 < end; ie += 2 + ie[1]) {
9055 if (ie + len > end)
9056 break;
9057 if (os_memcmp(ie, elem, len) != 0)
9058 continue;
9059
9060 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9061 wpabuf_free(wpa_s->vendor_elem[frame]);
9062 wpa_s->vendor_elem[frame] = NULL;
9063 } else {
9064 os_memmove(ie, ie + len, end - (ie + len));
9065 wpa_s->vendor_elem[frame]->used -= len;
9066 }
9067 wpas_vendor_elem_update(wpa_s);
9068 return 0;
9069 }
9070
9071 return -1;
9072}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009073
9074
9075struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009076 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009077 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009078{
9079 u16 i;
9080
Hai Shalomc1a21442022-02-04 13:43:00 -08009081 if (!modes)
9082 return NULL;
9083
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009084 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009085 if (modes[i].mode != mode ||
9086 !modes[i].num_channels || !modes[i].channels)
9087 continue;
9088 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
9089 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009090 return &modes[i];
9091 }
9092
9093 return NULL;
9094}
9095
9096
Hai Shalomc1a21442022-02-04 13:43:00 -08009097struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9098 u16 num_modes, int freq)
9099{
9100 int i, j;
9101
9102 for (i = 0; i < num_modes; i++) {
9103 for (j = 0; j < modes[i].num_channels; j++) {
9104 if (freq == modes[i].channels[j].freq)
9105 return &modes[i];
9106 }
9107 }
9108
9109 return NULL;
9110}
9111
9112
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009113static struct
9114wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9115 const u8 *bssid)
9116{
9117 struct wpa_bss_tmp_disallowed *bss;
9118
9119 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9120 struct wpa_bss_tmp_disallowed, list) {
9121 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
9122 return bss;
9123 }
9124
9125 return NULL;
9126}
9127
9128
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009129static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9130{
9131 struct wpa_bss_tmp_disallowed *tmp;
9132 unsigned int num_bssid = 0;
9133 u8 *bssids;
9134 int ret;
9135
9136 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9137 if (!bssids)
9138 return -1;
9139 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9140 struct wpa_bss_tmp_disallowed, list) {
9141 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9142 ETH_ALEN);
9143 num_bssid++;
9144 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009145 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009146 os_free(bssids);
9147 return ret;
9148}
9149
9150
9151static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9152{
9153 struct wpa_supplicant *wpa_s = eloop_ctx;
9154 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9155
9156 /* Make sure the bss is not already freed */
9157 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9158 struct wpa_bss_tmp_disallowed, list) {
9159 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009160 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009161 wpa_set_driver_tmp_disallow_list(wpa_s);
9162 break;
9163 }
9164 }
9165}
9166
9167
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009168void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009169 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009170{
9171 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009172
9173 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9174 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009175 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009176 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009177 }
9178
9179 bss = os_malloc(sizeof(*bss));
9180 if (!bss) {
9181 wpa_printf(MSG_DEBUG,
9182 "Failed to allocate memory for temp disallow BSS");
9183 return;
9184 }
9185
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009186 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9187 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009188 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009189
9190finish:
9191 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009192 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9193 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009194}
9195
9196
Hai Shalom74f70d42019-02-11 14:42:39 -08009197int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9198 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009199{
Hai Shalom74f70d42019-02-11 14:42:39 -08009200 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009201
9202 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9203 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009204 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9205 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009206 break;
9207 }
9208 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009209 if (!disallowed)
9210 return 0;
9211
9212 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009213 bss->level > disallowed->rssi_threshold) {
9214 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9215 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009216 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009217 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009218
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009219 return 1;
9220}
Hai Shalom81f62d82019-07-22 12:10:00 -07009221
9222
9223int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9224 unsigned int type, const u8 *addr,
9225 const u8 *mask)
9226{
9227 if ((addr && !mask) || (!addr && mask)) {
9228 wpa_printf(MSG_INFO,
9229 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9230 return -1;
9231 }
9232
9233 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9234 wpa_printf(MSG_INFO,
9235 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9236 return -1;
9237 }
9238
9239 if (type & MAC_ADDR_RAND_SCAN) {
9240 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9241 addr, mask))
9242 return -1;
9243 }
9244
9245 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9246 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9247 addr, mask))
9248 return -1;
9249
9250 if (wpa_s->sched_scanning && !wpa_s->pno)
9251 wpas_scan_restart_sched_scan(wpa_s);
9252 }
9253
9254 if (type & MAC_ADDR_RAND_PNO) {
9255 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9256 addr, mask))
9257 return -1;
9258
9259 if (wpa_s->pno) {
9260 wpas_stop_pno(wpa_s);
9261 wpas_start_pno(wpa_s);
9262 }
9263 }
9264
9265 return 0;
9266}
9267
9268
9269int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9270 unsigned int type)
9271{
9272 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9273 if (wpa_s->pno) {
9274 if (type & MAC_ADDR_RAND_PNO) {
9275 wpas_stop_pno(wpa_s);
9276 wpas_start_pno(wpa_s);
9277 }
9278 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9279 wpas_scan_restart_sched_scan(wpa_s);
9280 }
9281
9282 return 0;
9283}
Hai Shalomfdcde762020-04-02 11:19:20 -07009284
9285
9286int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9287 struct wpa_signal_info *si)
9288{
9289 int res;
9290
9291 if (!wpa_s->driver->signal_poll)
9292 return -1;
9293
9294 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9295
9296#ifdef CONFIG_TESTING_OPTIONS
9297 if (res == 0) {
9298 struct driver_signal_override *dso;
9299
9300 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9301 struct driver_signal_override, list) {
9302 if (os_memcmp(wpa_s->bssid, dso->bssid,
9303 ETH_ALEN) != 0)
9304 continue;
9305 wpa_printf(MSG_DEBUG,
9306 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
Sunil Ravi77d572f2023-01-17 23:58:31 +00009307 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009308 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009309 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009310 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009311 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009312 dso->si_avg_beacon_signal,
9313 si->current_noise,
9314 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009315 si->data.signal = dso->si_current_signal;
9316 si->data.avg_signal = dso->si_avg_signal;
9317 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009318 si->current_noise = dso->si_current_noise;
9319 break;
9320 }
9321 }
9322#endif /* CONFIG_TESTING_OPTIONS */
9323
9324 return res;
9325}
9326
9327
9328struct wpa_scan_results *
9329wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9330{
9331 struct wpa_scan_results *scan_res;
9332#ifdef CONFIG_TESTING_OPTIONS
9333 size_t idx;
9334#endif /* CONFIG_TESTING_OPTIONS */
9335
9336 if (!wpa_s->driver->get_scan_results2)
9337 return NULL;
9338
9339 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9340
9341#ifdef CONFIG_TESTING_OPTIONS
9342 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9343 struct driver_signal_override *dso;
9344 struct wpa_scan_res *res = scan_res->res[idx];
9345
9346 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9347 struct driver_signal_override, list) {
9348 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9349 continue;
9350 wpa_printf(MSG_DEBUG,
9351 "Override driver scan signal level %d->%d for "
9352 MACSTR,
9353 res->level, dso->scan_level,
9354 MAC2STR(res->bssid));
9355 res->flags |= WPA_SCAN_QUAL_INVALID;
9356 if (dso->scan_level < 0)
9357 res->flags |= WPA_SCAN_LEVEL_DBM;
9358 else
9359 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9360 res->level = dso->scan_level;
9361 break;
9362 }
9363 }
9364#endif /* CONFIG_TESTING_OPTIONS */
9365
9366 return scan_res;
9367}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009368
9369
9370static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9371{
9372 int i;
9373
9374 if (!wpa_s->valid_links)
9375 return false;
9376
9377 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9378 if (!(wpa_s->valid_links & BIT(i)))
9379 continue;
9380
9381 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9382 return true;
9383 }
9384
9385 return false;
9386}
9387
9388
9389int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9390 unsigned int wait, const u8 *dst, const u8 *src,
9391 const u8 *bssid, const u8 *data, size_t data_len,
9392 int no_cck)
9393{
9394 if (!wpa_s->driver->send_action)
9395 return -1;
9396
9397 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9398 if (wpas_ap_link_address(wpa_s, dst))
9399 dst = wpa_s->ap_mld_addr;
9400
9401 if (wpas_ap_link_address(wpa_s, bssid))
9402 bssid = wpa_s->ap_mld_addr;
9403 }
9404
9405 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9406 bssid, data, data_len, no_cck);
9407}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009408
9409
9410bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9411{
9412 struct hostapd_channel_data *chnl;
9413 int i, j;
9414
9415 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9416 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9417 chnl = wpa_s->hw.modes[i].channels;
9418 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9419 if (only_enabled &&
9420 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9421 continue;
9422 if (is_6ghz_freq(chnl[j].freq))
9423 return true;
9424 }
9425 }
9426 }
9427
9428 return false;
9429}