blob: cb6ca380716b6693b42f95d0ea666fee28f0c030 [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
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002089#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2090 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302091 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002092 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2093 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002094 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2095 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302096 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2097 wpa_dbg(wpa_s, MSG_INFO,
2098 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2099 }
Sunil Ravif42be322022-11-04 03:31:21 +00002100#else
2101 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2102 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2103 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002104#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2105 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 return 0;
2108}
2109
2110
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002111static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2112 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002113{
Hai Shalomc1a21442022-02-04 13:43:00 -08002114 bool scs = true, mscs = true;
2115
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002116 *pos = 0x00;
2117
2118 switch (idx) {
2119 case 0: /* Bits 0-7 */
2120 break;
2121 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002122 if (wpa_s->conf->coloc_intf_reporting) {
2123 /* Bit 13 - Collocated Interference Reporting */
2124 *pos |= 0x20;
2125 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002126 break;
2127 case 2: /* Bits 16-23 */
2128#ifdef CONFIG_WNM
2129 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002130 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002131 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002132#endif /* CONFIG_WNM */
2133 break;
2134 case 3: /* Bits 24-31 */
2135#ifdef CONFIG_WNM
2136 *pos |= 0x02; /* Bit 25 - SSID List */
2137#endif /* CONFIG_WNM */
2138#ifdef CONFIG_INTERWORKING
2139 if (wpa_s->conf->interworking)
2140 *pos |= 0x80; /* Bit 31 - Interworking */
2141#endif /* CONFIG_INTERWORKING */
2142 break;
2143 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002144#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002145 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002146 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002147#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002148 break;
2149 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002150#ifdef CONFIG_HS20
2151 if (wpa_s->conf->hs20)
2152 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2153#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002154#ifdef CONFIG_MBO
2155 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2156#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002157 break;
2158 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002159#ifdef CONFIG_TESTING_OPTIONS
2160 if (wpa_s->disable_scs_support)
2161 scs = false;
2162#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002163 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2164 /* Drop own SCS capability indication since the AP does
2165 * not support it. This is needed to avoid
2166 * interoperability issues with APs that get confused
2167 * with Extended Capabilities element. */
2168 scs = false;
2169 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002170 if (scs)
2171 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002172 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002173 case 7: /* Bits 56-63 */
2174 break;
2175 case 8: /* Bits 64-71 */
2176 if (wpa_s->conf->ftm_responder)
2177 *pos |= 0x40; /* Bit 70 - FTM responder */
2178 if (wpa_s->conf->ftm_initiator)
2179 *pos |= 0x80; /* Bit 71 - FTM initiator */
2180 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002181 case 9: /* Bits 72-79 */
2182#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002183 if (!wpa_s->disable_fils)
2184 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002185#endif /* CONFIG_FILS */
2186 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002187 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002188#ifdef CONFIG_TESTING_OPTIONS
2189 if (wpa_s->disable_mscs_support)
2190 mscs = false;
2191#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002192 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2193 /* Drop own MSCS capability indication since the AP does
2194 * not support it. This is needed to avoid
2195 * interoperability issues with APs that get confused
2196 * with Extended Capabilities element. */
2197 mscs = false;
2198 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002199 if (mscs)
2200 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002201 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002202 }
2203}
2204
2205
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002206int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2207 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002208{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002209 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002210 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002211
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002212 if (len < wpa_s->extended_capa_len)
2213 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002214 if (buflen < (size_t) len + 2) {
2215 wpa_printf(MSG_INFO,
2216 "Not enough room for building extended capabilities element");
2217 return -1;
2218 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002219
2220 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002221 *pos++ = len;
2222 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002223 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002224
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002225 if (i < wpa_s->extended_capa_len) {
2226 *pos &= ~wpa_s->extended_capa_mask[i];
2227 *pos |= wpa_s->extended_capa[i];
2228 }
2229 }
2230
2231 while (len > 0 && buf[1 + len] == 0) {
2232 len--;
2233 buf[1] = len;
2234 }
2235 if (len == 0)
2236 return 0;
2237
2238 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002239}
2240
2241
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002242static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2243 struct wpa_bss *test_bss)
2244{
2245 struct wpa_bss *bss;
2246
2247 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2248 if (bss == test_bss)
2249 return 1;
2250 }
2251
2252 return 0;
2253}
2254
2255
2256static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2257 struct wpa_ssid *test_ssid)
2258{
2259 struct wpa_ssid *ssid;
2260
2261 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2262 if (ssid == test_ssid)
2263 return 1;
2264 }
2265
2266 return 0;
2267}
2268
2269
2270int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2271 struct wpa_ssid *test_ssid)
2272{
2273 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2274 return 0;
2275
2276 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2277}
2278
2279
2280void wpas_connect_work_free(struct wpa_connect_work *cwork)
2281{
2282 if (cwork == NULL)
2283 return;
2284 os_free(cwork);
2285}
2286
2287
2288void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2289{
2290 struct wpa_connect_work *cwork;
2291 struct wpa_radio_work *work = wpa_s->connect_work;
2292
2293 if (!work)
2294 return;
2295
2296 wpa_s->connect_work = NULL;
2297 cwork = work->ctx;
2298 work->ctx = NULL;
2299 wpas_connect_work_free(cwork);
2300 radio_work_done(work);
2301}
2302
2303
Sunil Ravi77d572f2023-01-17 23:58:31 +00002304int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2305 enum wpas_mac_addr_style style,
2306 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002307{
2308 struct os_reltime now;
2309 u8 addr[ETH_ALEN];
2310
2311 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002312 /* Random addresses are valid within a given ESS so check
2313 * expiration/value only when continuing to use the same ESS. */
2314 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2315 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2316 /* Pregenerated addresses do not expire but their value
2317 * might have changed, so let's check that. */
2318 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2319 ETH_ALEN) == 0)
2320 return 0;
2321 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2322 wpa_s->last_mac_addr_change.usec != 0) &&
2323 !os_reltime_expired(
2324 &now,
2325 &wpa_s->last_mac_addr_change,
2326 wpa_s->conf->rand_addr_lifetime)) {
2327 wpa_msg(wpa_s, MSG_DEBUG,
2328 "Previously selected random MAC address has not yet expired");
2329 return 0;
2330 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002331 }
2332
2333 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002334 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002335 if (random_mac_addr(addr) < 0)
2336 return -1;
2337 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002338 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002339 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2340 if (random_mac_addr_keep_oui(addr) < 0)
2341 return -1;
2342 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002343 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2344 if (!ssid) {
2345 wpa_msg(wpa_s, MSG_INFO,
2346 "Invalid 'ssid' for address policy 3");
2347 return -1;
2348 }
2349 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2350 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002351 default:
2352 return -1;
2353 }
2354
2355 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2356 wpa_msg(wpa_s, MSG_INFO,
2357 "Failed to set random MAC address");
2358 return -1;
2359 }
2360
2361 os_get_reltime(&wpa_s->last_mac_addr_change);
2362 wpa_s->mac_addr_changed = 1;
2363 wpa_s->last_mac_addr_style = style;
2364
2365 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2366 wpa_msg(wpa_s, MSG_INFO,
2367 "Could not update MAC address information");
2368 return -1;
2369 }
2370
2371 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2372 MAC2STR(addr));
2373
Sunil Ravi77d572f2023-01-17 23:58:31 +00002374 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002375}
2376
2377
2378int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2379{
2380 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2381 !wpa_s->conf->preassoc_mac_addr)
2382 return 0;
2383
Sunil Ravi77d572f2023-01-17 23:58:31 +00002384 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2385 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002386}
2387
2388
Sunil Ravi036cec52023-03-29 11:35:17 -07002389void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2390 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002391{
2392#ifdef CONFIG_SAE
2393 int *groups = conf->sae_groups;
2394 int default_groups[] = { 19, 20, 21, 0 };
2395 const char *password;
2396
2397 if (!groups || groups[0] <= 0)
2398 groups = default_groups;
2399
2400 password = ssid->sae_password;
2401 if (!password)
2402 password = ssid->passphrase;
2403
Hai Shalom899fcc72020-10-19 14:38:18 -07002404 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002405 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002406 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002407 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002408 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002409 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002410 /* PT derivation not needed */
2411 sae_deinit_pt(ssid->pt);
2412 ssid->pt = NULL;
2413 return;
2414 }
2415
2416 if (ssid->pt)
2417 return; /* PT already derived */
2418 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2419 (const u8 *) password, os_strlen(password),
2420 ssid->sae_password_id);
2421#endif /* CONFIG_SAE */
2422}
2423
2424
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002425static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2426{
2427#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2428 os_free(wpa_s->sme.sae_rejected_groups);
2429 wpa_s->sme.sae_rejected_groups = NULL;
2430#ifdef CONFIG_TESTING_OPTIONS
2431 if (wpa_s->extra_sae_rejected_groups) {
2432 int i, *groups = wpa_s->extra_sae_rejected_groups;
2433
2434 for (i = 0; groups[i]; i++) {
2435 wpa_printf(MSG_DEBUG,
2436 "TESTING: Indicate rejection of an extra SAE group %d",
2437 groups[i]);
2438 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2439 groups[i]);
2440 }
2441 }
2442#endif /* CONFIG_TESTING_OPTIONS */
2443#endif /* CONFIG_SAE && CONFIG_SME */
2444}
2445
2446
Hai Shalom60840252021-02-19 19:02:11 -08002447int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2448{
2449 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2450 wpa_msg(wpa_s, MSG_INFO,
2451 "Could not restore permanent MAC address");
2452 return -1;
2453 }
2454 wpa_s->mac_addr_changed = 0;
2455 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2456 wpa_msg(wpa_s, MSG_INFO,
2457 "Could not update MAC address information");
2458 return -1;
2459 }
2460 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2461 return 0;
2462}
2463
2464
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002465static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467/**
2468 * wpa_supplicant_associate - Request association
2469 * @wpa_s: Pointer to wpa_supplicant data
2470 * @bss: Scan results for the selected BSS, or %NULL if not available
2471 * @ssid: Configuration data for the selected network
2472 *
2473 * This function is used to request %wpa_supplicant to associate with a BSS.
2474 */
2475void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2476 struct wpa_bss *bss, struct wpa_ssid *ssid)
2477{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002478 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002479 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002480
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002481 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002482 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002483
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002484 /*
2485 * If we are starting a new connection, any previously pending EAPOL
2486 * RX cannot be valid anymore.
2487 */
2488 wpabuf_free(wpa_s->pending_eapol_rx);
2489 wpa_s->pending_eapol_rx = NULL;
2490
Sunil Ravi77d572f2023-01-17 23:58:31 +00002491 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002492 rand_style = wpa_s->conf->mac_addr;
2493 else
2494 rand_style = ssid->mac_addr;
2495
Sunil Ravia04bd252022-05-02 22:54:18 -07002496 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002497 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002498 wmm_ac_clear_saved_tspecs(wpa_s);
2499 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002500 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002501#ifdef CONFIG_TESTING_OPTIONS
2502 wpa_s->testing_resend_assoc = 0;
2503#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002504
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002505 if (wpa_s->last_ssid == ssid) {
2506 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002507 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002508 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2509 wmm_ac_save_tspecs(wpa_s);
2510 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002511 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2512 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002513 }
Hai Shalomc3565922019-10-28 11:58:20 -07002514 } else {
2515#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002516 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002517#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002518 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002519#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002520 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002521#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002522
Sunil Ravi77d572f2023-01-17 23:58:31 +00002523 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2524 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2525
2526 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002527 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002528 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2529 status > 0) /* MAC changed */
2530 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2531 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2532 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002533 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002534 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002535 }
2536 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537
2538#ifdef CONFIG_IBSS_RSN
2539 ibss_rsn_deinit(wpa_s->ibss_rsn);
2540 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002541#else /* CONFIG_IBSS_RSN */
2542 if (ssid->mode == WPAS_MODE_IBSS &&
2543 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2544 wpa_msg(wpa_s, MSG_INFO,
2545 "IBSS RSN not supported in the build");
2546 return;
2547 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548#endif /* CONFIG_IBSS_RSN */
2549
2550 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2551 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2552#ifdef CONFIG_AP
2553 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2554 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2555 "mode");
2556 return;
2557 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002558 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2559 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002560 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2561 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002562 return;
2563 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 wpa_s->current_bss = bss;
2565#else /* CONFIG_AP */
2566 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2567 "the build");
2568#endif /* CONFIG_AP */
2569 return;
2570 }
2571
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002572 if (ssid->mode == WPAS_MODE_MESH) {
2573#ifdef CONFIG_MESH
2574 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2575 wpa_msg(wpa_s, MSG_INFO,
2576 "Driver does not support mesh mode");
2577 return;
2578 }
2579 if (bss)
2580 ssid->frequency = bss->freq;
2581 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002582 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002583 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2584 return;
2585 }
2586 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002587#else /* CONFIG_MESH */
2588 wpa_msg(wpa_s, MSG_ERROR,
2589 "mesh mode support not included in the build");
2590#endif /* CONFIG_MESH */
2591 return;
2592 }
2593
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002594 /*
2595 * Set WPA state machine configuration to match the selected network now
2596 * so that the information is available before wpas_start_assoc_cb()
2597 * gets called. This is needed at least for RSN pre-authentication where
2598 * candidate APs are added to a list based on scan result processing
2599 * before completion of the first association.
2600 */
2601 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2602
2603#ifdef CONFIG_DPP
2604 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2605 return;
2606#endif /* CONFIG_DPP */
2607
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608#ifdef CONFIG_TDLS
2609 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002610 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611#endif /* CONFIG_TDLS */
2612
Hai Shalomc3565922019-10-28 11:58:20 -07002613#ifdef CONFIG_MBO
2614 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2615#endif /* CONFIG_MBO */
2616
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002618 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 sme_authenticate(wpa_s, bss, ssid);
2620 return;
2621 }
2622
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002623 if (wpa_s->connect_work) {
2624 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2625 return;
2626 }
2627
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002628 if (radio_work_pending(wpa_s, "connect")) {
2629 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2630 return;
2631 }
2632
Dmitry Shmidt29333592017-01-09 12:27:11 -08002633#ifdef CONFIG_SME
2634 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2635 /* Clear possibly set auth_alg, if any, from last attempt. */
2636 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2637 }
2638#endif /* CONFIG_SME */
2639
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002640 wpas_abort_ongoing_scan(wpa_s);
2641
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002642 cwork = os_zalloc(sizeof(*cwork));
2643 if (cwork == NULL)
2644 return;
2645
2646 cwork->bss = bss;
2647 cwork->ssid = ssid;
2648
2649 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2650 wpas_start_assoc_cb, cwork) < 0) {
2651 os_free(cwork);
2652 }
2653}
2654
2655
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002656static int bss_is_ibss(struct wpa_bss *bss)
2657{
2658 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2659 IEEE80211_CAP_IBSS;
2660}
2661
2662
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002663static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2664 const struct wpa_ssid *ssid)
2665{
2666 enum hostapd_hw_mode hw_mode;
2667 struct hostapd_hw_modes *mode = NULL;
2668 u8 channel;
2669 int i;
2670
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002671 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2672 if (hw_mode == NUM_HOSTAPD_MODES)
2673 return 0;
2674 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2675 if (wpa_s->hw.modes[i].mode == hw_mode) {
2676 mode = &wpa_s->hw.modes[i];
2677 break;
2678 }
2679 }
2680
2681 if (!mode)
2682 return 0;
2683
2684 return mode->vht_capab != 0;
2685}
2686
2687
Hai Shalomc1a21442022-02-04 13:43:00 -08002688static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2689{
2690 int i;
2691
2692 for (i = channel; i < channel + 16; i += 4) {
2693 struct hostapd_channel_data *chan;
2694
2695 chan = hw_get_channel_chan(mode, i, NULL);
2696 if (!chan ||
2697 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2698 return false;
2699 }
2700
2701 return true;
2702}
2703
2704
Sunil Ravi036cec52023-03-29 11:35:17 -07002705static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2706 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002707{
Sunil Ravi036cec52023-03-29 11:35:17 -07002708 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002709
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002710 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2711 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2712
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002713 if (!bss_is_ibss(bss))
2714 continue;
2715
2716 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002717 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2718 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002719 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002720 return NULL;
2721}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002722
Sunil Ravi036cec52023-03-29 11:35:17 -07002723
2724static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2725 const struct wpa_ssid *ssid,
2726 struct hostapd_hw_modes *mode)
2727{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002728 /* For IBSS check HT_IBSS flag */
2729 if (ssid->mode == WPAS_MODE_IBSS &&
2730 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002731 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002732
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002733 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2734 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2735 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2736 wpa_printf(MSG_DEBUG,
2737 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002738 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002739 }
2740
Sunil Ravi036cec52023-03-29 11:35:17 -07002741 if (!ht_supported(mode))
2742 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002743
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002744#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002745 if (ssid->disable_ht)
2746 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002747#endif /* CONFIG_HT_OVERRIDES */
2748
Sunil Ravi036cec52023-03-29 11:35:17 -07002749 return true;
2750}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002751
Sunil Ravi036cec52023-03-29 11:35:17 -07002752
2753static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2754 const struct wpa_ssid *ssid,
2755 struct hostapd_hw_modes *mode)
2756{
2757 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2758 return false;
2759
2760 if (!drv_supports_vht(wpa_s, ssid))
2761 return false;
2762
2763 /* For IBSS check VHT_IBSS flag */
2764 if (ssid->mode == WPAS_MODE_IBSS &&
2765 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2766 return false;
2767
2768 if (!vht_supported(mode))
2769 return false;
2770
2771#ifdef CONFIG_VHT_OVERRIDES
2772 if (ssid->disable_vht)
2773 return false;
2774#endif /* CONFIG_VHT_OVERRIDES */
2775
2776 return true;
2777}
2778
2779
2780static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2781 const struct wpa_ssid *ssid,
2782 const struct hostapd_hw_modes *mode,
2783 int ieee80211_mode)
2784{
Hai Shalomfdcde762020-04-02 11:19:20 -07002785#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002786 if (ssid->disable_he)
2787 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002788#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002789
Sunil Ravi036cec52023-03-29 11:35:17 -07002790 switch (mode->mode) {
2791 case HOSTAPD_MODE_IEEE80211G:
2792 case HOSTAPD_MODE_IEEE80211B:
2793 case HOSTAPD_MODE_IEEE80211A:
2794 return mode->he_capab[ieee80211_mode].he_supported;
2795 default:
2796 return false;
2797 }
2798}
2799
2800
2801static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2802 const struct wpa_ssid *ssid,
2803 const struct hostapd_hw_modes *mode,
2804 int ieee80211_mode)
2805{
2806 if (ssid->disable_eht)
2807 return false;
2808
2809 switch(mode->mode) {
2810 case HOSTAPD_MODE_IEEE80211G:
2811 case HOSTAPD_MODE_IEEE80211B:
2812 case HOSTAPD_MODE_IEEE80211A:
2813 return mode->eht_capab[ieee80211_mode].eht_supported;
2814 default:
2815 return false;
2816 }
2817}
2818
2819
2820static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2821 const struct wpa_ssid *ssid,
2822 struct hostapd_hw_modes *mode,
2823 struct hostapd_freq_params *freq,
2824 int obss_scan) {
2825 int chan_idx;
2826 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2827 int i, res;
2828 unsigned int j;
2829 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002830 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2831 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002832 };
2833 int ht40 = -1;
2834
2835 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002836 return;
2837
2838 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2839 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002840 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002841 break;
2842 pri_chan = NULL;
2843 }
2844 if (!pri_chan)
2845 return;
2846
2847 /* Check primary channel flags */
2848 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2849 return;
2850
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002851#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002852 if (ssid->disable_ht40)
2853 return;
2854#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002855
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002856 /* Check/setup HT40+/HT40- */
2857 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002858 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002859 ht40 = 1;
2860 break;
2861 }
2862 }
2863
2864 /* Find secondary channel */
2865 for (i = 0; i < mode->num_channels; i++) {
2866 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002867 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002868 break;
2869 sec_chan = NULL;
2870 }
2871 if (!sec_chan)
2872 return;
2873
2874 /* Check secondary channel flags */
2875 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2876 return;
2877
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002878 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002879 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2880 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002881 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002882 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2883 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002884 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002885 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002886
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002887 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002888 struct wpa_scan_results *scan_res;
2889
2890 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2891 if (scan_res == NULL) {
2892 /* Back to HT20 */
2893 freq->sec_channel_offset = 0;
2894 return;
2895 }
2896
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002897 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002898 switch (res) {
2899 case 0:
2900 /* Back to HT20 */
2901 freq->sec_channel_offset = 0;
2902 break;
2903 case 1:
2904 /* Configuration allowed */
2905 break;
2906 case 2:
2907 /* Switch pri/sec channels */
2908 freq->freq = hw_get_freq(mode, sec_chan->chan);
2909 freq->sec_channel_offset = -freq->sec_channel_offset;
2910 freq->channel = sec_chan->chan;
2911 break;
2912 default:
2913 freq->sec_channel_offset = 0;
2914 break;
2915 }
2916
2917 wpa_scan_results_free(scan_res);
2918 }
2919
2920 wpa_printf(MSG_DEBUG,
2921 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2922 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002923}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002924
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002925
Sunil Ravi036cec52023-03-29 11:35:17 -07002926static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2927 const struct wpa_ssid *ssid,
2928 struct hostapd_hw_modes *mode,
2929 struct hostapd_freq_params *freq,
2930 int ieee80211_mode, bool is_6ghz) {
2931 static const int bw80[] = {
2932 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2933 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2934 6515, 6595, 6675, 6755, 6835, 6915, 6995
2935 };
2936 static const int bw160[] = {
2937 5955, 6115, 6275, 6435, 6595, 6755, 6915
2938 };
2939 struct hostapd_freq_params vht_freq;
2940 int i;
2941 unsigned int j, k;
2942 int chwidth, seg0, seg1;
2943 u32 vht_caps = 0;
2944 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002945
Sunil Ravi036cec52023-03-29 11:35:17 -07002946 if (!freq->vht_enabled && !freq->he_enabled)
2947 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002948
Hai Shalomc1a21442022-02-04 13:43:00 -08002949 vht_freq = *freq;
2950
Sunil Ravi036cec52023-03-29 11:35:17 -07002951 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2952 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2953 seg1 = 0;
2954 if (freq->sec_channel_offset == 0) {
2955 seg0 = 0;
2956 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2957 if (freq->ht_enabled && !is_6ghz)
2958 goto skip_80mhz;
2959 }
2960 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2961 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002962
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002963 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002964 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2965 if (freq->freq >= bw80[j] &&
2966 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002967 break;
2968 }
2969
Hai Shalomc1a21442022-02-04 13:43:00 -08002970 if (j == ARRAY_SIZE(bw80) ||
2971 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002972 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002973
Sunil Ravi036cec52023-03-29 11:35:17 -07002974 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002975 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002976 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002977
Sunil8cd6f4d2022-06-28 18:40:46 +00002978 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002979 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002980 seg1 = 0;
2981
Sunil Ravi036cec52023-03-29 11:35:17 -07002982 /* In 160 MHz, the initial four 20 MHz channels were validated
2983 * above. If 160 MHz is supported, check the remaining four 20 MHz
2984 * channels for the total of 160 MHz bandwidth for 6 GHz.
2985 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002986 if ((mode->he_capab[ieee80211_mode].phy_cap[
2987 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002988 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2989 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002990 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2991 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002992 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002993 seg0 = channel + 14;
2994 break;
2995 }
2996 }
2997 }
2998
Sunil8cd6f4d2022-06-28 18:40:46 +00002999 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003000 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003001 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003002 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003003 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003004 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003005
3006 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3007 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003008 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003009
3010 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003011 struct hostapd_channel_data *chan;
3012
3013 chan = hw_get_channel_chan(mode, i, NULL);
3014 if (!chan)
3015 continue;
3016
3017 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3018 HOSTAPD_CHAN_NO_IR |
3019 HOSTAPD_CHAN_RADAR))
3020 continue;
3021
3022 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003023 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003024 if (!is_6ghz)
3025 vht_caps |=
3026 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3027 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003028 }
3029
Sunil8cd6f4d2022-06-28 18:40:46 +00003030 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003031 break;
3032 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003033 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003034 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003035 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003036 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3037 seg0 = 50;
3038 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003039 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003040 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3041 seg0 = 114;
3042 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003043 }
3044
Sunil Ravi036cec52023-03-29 11:35:17 -07003045skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003046 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003047 freq->channel, ssid->enable_edmg,
3048 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003049 freq->vht_enabled, freq->he_enabled,
3050 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003051 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003052 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003053 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003054 &mode->eht_capab[ieee80211_mode]) != 0)
3055 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003056
3057 *freq = vht_freq;
3058
3059 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3060 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003061 return true;
3062}
3063
3064
3065void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3066 const struct wpa_ssid *ssid,
3067 struct hostapd_freq_params *freq)
3068{
3069 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3070 enum hostapd_hw_mode hw_mode;
3071 struct hostapd_hw_modes *mode = NULL;
3072 int i, obss_scan = 1;
3073 u8 channel;
3074 bool is_6ghz;
3075
3076 freq->freq = ssid->frequency;
3077
3078 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3079 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3080
3081 if (bss) {
3082 wpa_printf(MSG_DEBUG,
3083 "IBSS already found in scan results, adjust control freq: %d",
3084 bss->freq);
3085 freq->freq = bss->freq;
3086 obss_scan = 0;
3087 }
3088 }
3089
3090 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3091 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3092 if (wpa_s->hw.modes[i].mode == hw_mode &&
3093 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3094 NULL) != NULL) {
3095 mode = &wpa_s->hw.modes[i];
3096 break;
3097 }
3098 }
3099
3100 if (!mode)
3101 return;
3102
3103 is_6ghz = is_6ghz_freq(freq->freq);
3104
3105 freq->ht_enabled = 0;
3106 freq->vht_enabled = 0;
3107 freq->he_enabled = 0;
3108 freq->eht_enabled = 0;
3109
3110 if (!is_6ghz)
3111 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3112 if (freq->ht_enabled)
3113 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3114 if (freq->vht_enabled || is_6ghz)
3115 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3116 ieee80211_mode);
3117 freq->channel = channel;
3118 /* Setup higher BW only for 5 GHz */
3119 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3120 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3121 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3122 ieee80211_mode, is_6ghz))
3123 freq->he_enabled = freq->vht_enabled = false;
3124 }
3125
3126 if (freq->he_enabled)
3127 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3128 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003129}
3130
3131
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003132#ifdef CONFIG_FILS
3133static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3134 size_t ie_buf_len)
3135{
3136 struct fils_hlp_req *req;
3137 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3138 const u8 *pos;
3139 u8 *buf = ie_buf;
3140
3141 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3142 list) {
3143 rem_len = ie_buf_len - ie_len;
3144 pos = wpabuf_head(req->pkt);
3145 hdr_len = 1 + 2 * ETH_ALEN + 6;
3146 hlp_len = wpabuf_len(req->pkt);
3147
3148 if (rem_len < 2 + hdr_len + hlp_len) {
3149 wpa_printf(MSG_ERROR,
3150 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3151 (unsigned long) rem_len,
3152 (unsigned long) (2 + hdr_len + hlp_len));
3153 break;
3154 }
3155
3156 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3157 /* Element ID */
3158 *buf++ = WLAN_EID_EXTENSION;
3159 /* Length */
3160 *buf++ = len;
3161 /* Element ID Extension */
3162 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3163 /* Destination MAC address */
3164 os_memcpy(buf, req->dst, ETH_ALEN);
3165 buf += ETH_ALEN;
3166 /* Source MAC address */
3167 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3168 buf += ETH_ALEN;
3169 /* LLC/SNAP Header */
3170 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3171 buf += 6;
3172 /* HLP Packet */
3173 os_memcpy(buf, pos, len - hdr_len);
3174 buf += len - hdr_len;
3175 pos += len - hdr_len;
3176
3177 hlp_len -= len - hdr_len;
3178 ie_len += 2 + len;
3179 rem_len -= 2 + len;
3180
3181 while (hlp_len) {
3182 len = (hlp_len > 255) ? 255 : hlp_len;
3183 if (rem_len < 2 + len)
3184 break;
3185 *buf++ = WLAN_EID_FRAGMENT;
3186 *buf++ = len;
3187 os_memcpy(buf, pos, len);
3188 buf += len;
3189 pos += len;
3190
3191 hlp_len -= len;
3192 ie_len += 2 + len;
3193 rem_len -= 2 + len;
3194 }
3195 }
3196
3197 return ie_len;
3198}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003199
3200
3201int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3202{
3203 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3204 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3205 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3206 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3207}
3208
3209
3210int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3211{
3212#ifdef CONFIG_FILS_SK_PFS
3213 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3214 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3215#else /* CONFIG_FILS_SK_PFS */
3216 return 0;
3217#endif /* CONFIG_FILS_SK_PFS */
3218}
3219
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003220#endif /* CONFIG_FILS */
3221
3222
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003223bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3224{
3225 const u8 *wfa_capa;
3226
3227 if (!bss)
3228 return false;
3229
3230 /* Get WFA capability from Beacon or Probe Response frame elements */
3231 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3232 if (!wfa_capa)
3233 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3234 bss, WFA_CAPA_IE_VENDOR_TYPE);
3235
3236 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3237 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3238 /* AP does not enable QM non EHT traffic description policy */
3239 return false;
3240 }
3241
3242 return true;
3243}
3244
3245
Hai Shalomc1a21442022-02-04 13:43:00 -08003246static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3247 struct wpa_bss *bss,
3248 u8 *wpa_ie, size_t wpa_ie_len,
3249 size_t max_wpa_ie_len)
3250{
3251 struct wpabuf *wfa_ie = NULL;
3252 u8 wfa_capa[1];
3253 size_t wfa_ie_len, buf_len;
3254
3255 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3256 if (wpa_s->enable_dscp_policy_capa)
3257 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3258
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003259 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3260 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3261
Hai Shalomc1a21442022-02-04 13:43:00 -08003262 if (!wfa_capa[0])
3263 return wpa_ie_len;
3264
3265 /* Wi-Fi Alliance element */
3266 buf_len = 1 + /* Element ID */
3267 1 + /* Length */
3268 3 + /* OUI */
3269 1 + /* OUI Type */
3270 1 + /* Capabilities Length */
3271 sizeof(wfa_capa); /* Capabilities */
3272 wfa_ie = wpabuf_alloc(buf_len);
3273 if (!wfa_ie)
3274 return wpa_ie_len;
3275
3276 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3277 wpabuf_put_u8(wfa_ie, buf_len - 2);
3278 wpabuf_put_be24(wfa_ie, OUI_WFA);
3279 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3280 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3281 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3282
3283 wfa_ie_len = wpabuf_len(wfa_ie);
3284 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3285 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3286 wfa_ie);
3287 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3288 wfa_ie_len);
3289 wpa_ie_len += wfa_ie_len;
3290 }
3291
3292 wpabuf_free(wfa_ie);
3293 return wpa_ie_len;
3294}
3295
3296
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003297static u8 * wpas_populate_assoc_ies(
3298 struct wpa_supplicant *wpa_s,
3299 struct wpa_bss *bss, struct wpa_ssid *ssid,
3300 struct wpa_driver_associate_params *params,
3301 enum wpa_drv_update_connect_params_mask *mask)
3302{
3303 u8 *wpa_ie;
3304 size_t max_wpa_ie_len = 500;
3305 size_t wpa_ie_len;
3306 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003307#ifdef CONFIG_MBO
3308 const u8 *mbo_ie;
3309#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303310#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3311 int pmksa_cached = 0;
3312#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313#ifdef CONFIG_FILS
3314 const u8 *realm, *username, *rrk;
3315 size_t realm_len, username_len, rrk_len;
3316 u16 next_seq_num;
3317 struct fils_hlp_req *req;
3318
3319 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3320 list) {
3321 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3322 2 + 2 * wpabuf_len(req->pkt) / 255;
3323 }
3324#endif /* CONFIG_FILS */
3325
3326 wpa_ie = os_malloc(max_wpa_ie_len);
3327 if (!wpa_ie) {
3328 wpa_printf(MSG_ERROR,
3329 "Failed to allocate connect IE buffer for %lu bytes",
3330 (unsigned long) max_wpa_ie_len);
3331 return NULL;
3332 }
3333
3334 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3335 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3336 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3337 int try_opportunistic;
3338 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003339 const u8 *addr = bss->bssid;
3340
Sunil Ravi036cec52023-03-29 11:35:17 -07003341 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3342 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3343 !is_zero_ether_addr(bss->mld_addr))
3344 addr = bss->mld_addr;
3345
3346 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3347 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003348 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003349
3350 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3351 wpa_s->conf->okc :
3352 ssid->proactive_key_caching) &&
3353 (ssid->proto & WPA_PROTO_RSN);
3354#ifdef CONFIG_FILS
3355 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3356 cache_id = wpa_bss_get_fils_cache_id(bss);
3357#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003358 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003359 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003360 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003361 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303362#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3363 pmksa_cached = 1;
3364#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003365 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003366 wpa_ie_len = max_wpa_ie_len;
3367 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003368 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003369 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3370 "key management and encryption suites");
3371 os_free(wpa_ie);
3372 return NULL;
3373 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003374#ifdef CONFIG_HS20
3375 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3376 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3377 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3378 wpa_ie_len = max_wpa_ie_len;
3379 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003380 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003381 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3382 "key management and encryption suites");
3383 os_free(wpa_ie);
3384 return NULL;
3385 }
3386#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003387 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3388 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3389 /*
3390 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3391 * use non-WPA since the scan results did not indicate that the
3392 * AP is using WPA or WPA2.
3393 */
3394 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3395 wpa_ie_len = 0;
3396 wpa_s->wpa_proto = 0;
3397 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3398 wpa_ie_len = max_wpa_ie_len;
3399 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003400 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003401 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3402 "key management and encryption suites (no "
3403 "scan results)");
3404 os_free(wpa_ie);
3405 return NULL;
3406 }
3407#ifdef CONFIG_WPS
3408 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3409 struct wpabuf *wps_ie;
3410 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3411 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3412 wpa_ie_len = wpabuf_len(wps_ie);
3413 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3414 } else
3415 wpa_ie_len = 0;
3416 wpabuf_free(wps_ie);
3417 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3418 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3419 params->wps = WPS_MODE_PRIVACY;
3420 else
3421 params->wps = WPS_MODE_OPEN;
3422 wpa_s->wpa_proto = 0;
3423#endif /* CONFIG_WPS */
3424 } else {
3425 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3426 wpa_ie_len = 0;
3427 wpa_s->wpa_proto = 0;
3428 }
3429
3430#ifdef IEEE8021X_EAPOL
3431 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3432 if (ssid->leap) {
3433 if (ssid->non_leap == 0)
3434 algs = WPA_AUTH_ALG_LEAP;
3435 else
3436 algs |= WPA_AUTH_ALG_LEAP;
3437 }
3438 }
3439
3440#ifdef CONFIG_FILS
3441 /* Clear FILS association */
3442 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3443
3444 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3445 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3446 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3447 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003448 &next_seq_num, &rrk, &rrk_len) == 0 &&
3449 (!wpa_s->last_con_fail_realm ||
3450 wpa_s->last_con_fail_realm_len != realm_len ||
3451 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003452 algs = WPA_AUTH_ALG_FILS;
3453 params->fils_erp_username = username;
3454 params->fils_erp_username_len = username_len;
3455 params->fils_erp_realm = realm;
3456 params->fils_erp_realm_len = realm_len;
3457 params->fils_erp_next_seq_num = next_seq_num;
3458 params->fils_erp_rrk = rrk;
3459 params->fils_erp_rrk_len = rrk_len;
3460
3461 if (mask)
3462 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303463 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3464 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3465 pmksa_cached) {
3466 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003467 }
3468#endif /* CONFIG_FILS */
3469#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003470#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003471 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003472 algs = WPA_AUTH_ALG_SAE;
3473#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003474
3475 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3476 if (ssid->auth_alg) {
3477 algs = ssid->auth_alg;
3478 wpa_dbg(wpa_s, MSG_DEBUG,
3479 "Overriding auth_alg selection: 0x%x", algs);
3480 }
3481
Hai Shalom5f92bc92019-04-18 11:54:11 -07003482#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303483 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003484 wpa_dbg(wpa_s, MSG_DEBUG,
3485 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3486 algs = WPA_AUTH_ALG_OPEN;
3487 }
3488#endif /* CONFIG_SAE */
3489
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003490#ifdef CONFIG_P2P
3491 if (wpa_s->global->p2p) {
3492 u8 *pos;
3493 size_t len;
3494 int res;
3495 pos = wpa_ie + wpa_ie_len;
3496 len = max_wpa_ie_len - wpa_ie_len;
3497 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3498 ssid->p2p_group);
3499 if (res >= 0)
3500 wpa_ie_len += res;
3501 }
3502
3503 wpa_s->cross_connect_disallowed = 0;
3504 if (bss) {
3505 struct wpabuf *p2p;
3506 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3507 if (p2p) {
3508 wpa_s->cross_connect_disallowed =
3509 p2p_get_cross_connect_disallowed(p2p);
3510 wpabuf_free(p2p);
3511 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3512 "connection",
3513 wpa_s->cross_connect_disallowed ?
3514 "disallows" : "allows");
3515 }
3516 }
3517
3518 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3519#endif /* CONFIG_P2P */
3520
3521 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003522 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003523 wpa_ie + wpa_ie_len,
3524 max_wpa_ie_len -
3525 wpa_ie_len);
3526 }
3527
3528 /*
3529 * Workaround: Add Extended Capabilities element only if the AP
3530 * included this element in Beacon/Probe Response frames. Some older
3531 * APs seem to have interoperability issues if this element is
3532 * included, so while the standard may require us to include the
3533 * element in all cases, it is justifiable to skip it to avoid
3534 * interoperability issues.
3535 */
3536 if (ssid->p2p_group)
3537 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3538 else
3539 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3540
3541 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3542 u8 ext_capab[18];
3543 int ext_capab_len;
3544 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003545 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003546 if (ext_capab_len > 0 &&
3547 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3548 u8 *pos = wpa_ie;
3549 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3550 pos += 2 + pos[1];
3551 os_memmove(pos + ext_capab_len, pos,
3552 wpa_ie_len - (pos - wpa_ie));
3553 wpa_ie_len += ext_capab_len;
3554 os_memcpy(pos, ext_capab, ext_capab_len);
3555 }
3556 }
3557
3558#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003559 if (is_hs20_network(wpa_s, ssid, bss)
3560#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3561 && is_hs20_config(wpa_s)
3562#endif /* ANDROID */
3563 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003564 struct wpabuf *hs20;
3565
Roshan Pius3a1667e2018-07-03 15:17:14 -07003566 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003567 if (hs20) {
3568 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3569 size_t len;
3570
Hai Shalom74f70d42019-02-11 14:42:39 -08003571 wpas_hs20_add_indication(hs20, pps_mo_id,
3572 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003573 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003574 len = max_wpa_ie_len - wpa_ie_len;
3575 if (wpabuf_len(hs20) <= len) {
3576 os_memcpy(wpa_ie + wpa_ie_len,
3577 wpabuf_head(hs20), wpabuf_len(hs20));
3578 wpa_ie_len += wpabuf_len(hs20);
3579 }
3580 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003581 }
3582 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003583 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003584#endif /* CONFIG_HS20 */
3585
3586 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3587 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3588 size_t len;
3589
3590 len = max_wpa_ie_len - wpa_ie_len;
3591 if (wpabuf_len(buf) <= len) {
3592 os_memcpy(wpa_ie + wpa_ie_len,
3593 wpabuf_head(buf), wpabuf_len(buf));
3594 wpa_ie_len += wpabuf_len(buf);
3595 }
3596 }
3597
3598#ifdef CONFIG_FST
3599 if (wpa_s->fst_ies) {
3600 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3601
3602 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3603 os_memcpy(wpa_ie + wpa_ie_len,
3604 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3605 wpa_ie_len += fst_ies_len;
3606 }
3607 }
3608#endif /* CONFIG_FST */
3609
3610#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003611 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003612 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003613 int len;
3614
3615 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003616 max_wpa_ie_len - wpa_ie_len,
3617 !!mbo_attr_from_mbo_ie(mbo_ie,
3618 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003619 if (len >= 0)
3620 wpa_ie_len += len;
3621 }
3622#endif /* CONFIG_MBO */
3623
3624#ifdef CONFIG_FILS
3625 if (algs == WPA_AUTH_ALG_FILS) {
3626 size_t len;
3627
3628 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3629 max_wpa_ie_len - wpa_ie_len);
3630 wpa_ie_len += len;
3631 }
3632#endif /* CONFIG_FILS */
3633
3634#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003635#ifdef CONFIG_TESTING_OPTIONS
3636 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3637 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3638 } else
3639#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003640 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003641 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3642 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003643 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003644 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003645
Roshan Pius3a1667e2018-07-03 15:17:14 -07003646 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003647 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003648 } else if (wpa_s->assoc_status_code ==
3649 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003650 if (wpa_s->last_owe_group == 19)
3651 group = 20;
3652 else if (wpa_s->last_owe_group == 20)
3653 group = 21;
3654 else
3655 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003656 } else {
3657 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003658 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003659
Roshan Pius3a1667e2018-07-03 15:17:14 -07003660 wpa_s->last_owe_group = group;
3661 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003662 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3663 if (owe_ie &&
3664 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3665 os_memcpy(wpa_ie + wpa_ie_len,
3666 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3667 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003668 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003669 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003670 }
3671#endif /* CONFIG_OWE */
3672
Hai Shalom021b0b52019-04-10 11:17:58 -07003673#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003674 if (DPP_VERSION > 1 &&
3675 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003676 ssid->dpp_netaccesskey &&
3677 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003678 struct rsn_pmksa_cache_entry *pmksa;
3679
3680 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3681 if (!pmksa || !pmksa->dpp_pfs)
3682 goto pfs_fail;
3683
Hai Shalom021b0b52019-04-10 11:17:58 -07003684 dpp_pfs_free(wpa_s->dpp_pfs);
3685 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3686 ssid->dpp_netaccesskey_len);
3687 if (!wpa_s->dpp_pfs) {
3688 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3689 /* Try to continue without PFS */
3690 goto pfs_fail;
3691 }
3692 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3693 max_wpa_ie_len - wpa_ie_len) {
3694 os_memcpy(wpa_ie + wpa_ie_len,
3695 wpabuf_head(wpa_s->dpp_pfs->ie),
3696 wpabuf_len(wpa_s->dpp_pfs->ie));
3697 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3698 }
3699 }
3700pfs_fail:
3701#endif /* CONFIG_DPP2 */
3702
Roshan Pius3a1667e2018-07-03 15:17:14 -07003703#ifdef CONFIG_IEEE80211R
3704 /*
3705 * Add MDIE under these conditions: the network profile allows FT,
3706 * the AP supports FT, and the mobility domain ID matches.
3707 */
3708 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3709 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3710
3711 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3712 size_t len = 0;
3713 const u8 *md = mdie + 2;
3714 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3715
3716 if (os_memcmp(md, wpa_md,
3717 MOBILITY_DOMAIN_ID_LEN) == 0) {
3718 /* Add mobility domain IE */
3719 len = wpa_ft_add_mdie(
3720 wpa_s->wpa, wpa_ie + wpa_ie_len,
3721 max_wpa_ie_len - wpa_ie_len, mdie);
3722 wpa_ie_len += len;
3723 }
3724#ifdef CONFIG_SME
3725 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003726 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003727 wpa_dbg(wpa_s, MSG_DEBUG,
3728 "SME: Trying to use FT over-the-air");
3729 algs |= WPA_AUTH_ALG_FT;
3730 }
3731#endif /* CONFIG_SME */
3732 }
3733 }
3734#endif /* CONFIG_IEEE80211R */
3735
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003736#ifdef CONFIG_TESTING_OPTIONS
3737 if (wpa_s->rsnxe_override_assoc &&
3738 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3739 max_wpa_ie_len - wpa_ie_len) {
3740 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3741 os_memcpy(wpa_ie + wpa_ie_len,
3742 wpabuf_head(wpa_s->rsnxe_override_assoc),
3743 wpabuf_len(wpa_s->rsnxe_override_assoc));
3744 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3745 } else
3746#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003747 if (wpa_s->rsnxe_len > 0 &&
3748 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3749 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3750 wpa_ie_len += wpa_s->rsnxe_len;
3751 }
3752
Hai Shalomc1a21442022-02-04 13:43:00 -08003753#ifdef CONFIG_TESTING_OPTIONS
3754 if (wpa_s->disable_mscs_support)
3755 goto mscs_end;
3756#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003757 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3758 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003759 struct wpabuf *mscs_ie;
3760 size_t mscs_ie_len, buf_len;
3761
Hai Shalom899fcc72020-10-19 14:38:18 -07003762 buf_len = 3 + /* MSCS descriptor IE header */
3763 1 + /* Request type */
3764 2 + /* User priority control */
3765 4 + /* Stream timeout */
3766 3 + /* TCLAS Mask IE header */
3767 wpa_s->robust_av.frame_classifier_len;
3768 mscs_ie = wpabuf_alloc(buf_len);
3769 if (!mscs_ie) {
3770 wpa_printf(MSG_INFO,
3771 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003772 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003773 }
3774
3775 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3776 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3777 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3778 mscs_ie_len = wpabuf_len(mscs_ie);
3779 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3780 mscs_ie_len);
3781 wpa_ie_len += mscs_ie_len;
3782 }
3783
3784 wpabuf_free(mscs_ie);
3785 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003786mscs_end:
3787
3788 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3789 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003790
Hai Shalom74f70d42019-02-11 14:42:39 -08003791 if (ssid->multi_ap_backhaul_sta) {
3792 size_t multi_ap_ie_len;
3793
3794 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3795 max_wpa_ie_len - wpa_ie_len,
3796 MULTI_AP_BACKHAUL_STA);
3797 if (multi_ap_ie_len == 0) {
3798 wpa_printf(MSG_ERROR,
3799 "Multi-AP: Failed to build Multi-AP IE");
3800 os_free(wpa_ie);
3801 return NULL;
3802 }
3803 wpa_ie_len += multi_ap_ie_len;
3804 }
3805
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003806 params->wpa_ie = wpa_ie;
3807 params->wpa_ie_len = wpa_ie_len;
3808 params->auth_alg = algs;
3809 if (mask)
3810 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3811
3812 return wpa_ie;
3813}
3814
3815
Hai Shalomc3565922019-10-28 11:58:20 -07003816#ifdef CONFIG_OWE
3817static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3818{
3819 struct wpa_driver_associate_params params;
3820 u8 *wpa_ie;
3821
3822 os_memset(&params, 0, sizeof(params));
3823 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3824 wpa_s->current_ssid, &params, NULL);
3825 if (!wpa_ie)
3826 return;
3827
3828 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3829 os_free(wpa_ie);
3830}
3831#endif /* CONFIG_OWE */
3832
3833
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003834#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3835static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3836{
3837 struct wpa_driver_associate_params params;
3838 enum wpa_drv_update_connect_params_mask mask = 0;
3839 u8 *wpa_ie;
3840
3841 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3842 return; /* nothing to do */
3843
3844 os_memset(&params, 0, sizeof(params));
3845 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3846 wpa_s->current_ssid, &params, &mask);
3847 if (!wpa_ie)
3848 return;
3849
Hai Shalomc1a21442022-02-04 13:43:00 -08003850 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3851 wpa_s->auth_alg = params.auth_alg;
3852 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003853 }
3854
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003855 os_free(wpa_ie);
3856}
3857#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3858
3859
Hai Shalomc3565922019-10-28 11:58:20 -07003860static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3861{
3862 if (!edmg_ie || edmg_ie[1] < 6)
3863 return 0;
3864 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3865}
3866
3867
3868static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3869{
3870 if (!edmg_ie || edmg_ie[1] < 6)
3871 return 0;
3872 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3873}
3874
3875
3876/* Returns the intersection of two EDMG configurations.
3877 * Note: The current implementation is limited to CB2 only (CB1 included),
3878 * i.e., the implementation supports up to 2 contiguous channels.
3879 * For supporting non-contiguous (aggregated) channels and for supporting
3880 * CB3 and above, this function will need to be extended.
3881 */
3882static struct ieee80211_edmg_config
3883get_edmg_intersection(struct ieee80211_edmg_config a,
3884 struct ieee80211_edmg_config b,
3885 u8 primary_channel)
3886{
3887 struct ieee80211_edmg_config result;
3888 int i, contiguous = 0;
3889 int max_contiguous = 0;
3890
3891 result.channels = b.channels & a.channels;
3892 if (!result.channels) {
3893 wpa_printf(MSG_DEBUG,
3894 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3895 a.channels, b.channels);
3896 goto fail;
3897 }
3898
3899 if (!(result.channels & BIT(primary_channel - 1))) {
3900 wpa_printf(MSG_DEBUG,
3901 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3902 primary_channel, result.channels);
3903 goto fail;
3904 }
3905
3906 /* Find max contiguous channels */
3907 for (i = 0; i < 6; i++) {
3908 if (result.channels & BIT(i))
3909 contiguous++;
3910 else
3911 contiguous = 0;
3912
3913 if (contiguous > max_contiguous)
3914 max_contiguous = contiguous;
3915 }
3916
3917 /* Assuming AP and STA supports ONLY contiguous channels,
3918 * bw configuration can have value between 4-7.
3919 */
3920 if ((b.bw_config < a.bw_config))
3921 result.bw_config = b.bw_config;
3922 else
3923 result.bw_config = a.bw_config;
3924
3925 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3926 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3927 wpa_printf(MSG_DEBUG,
3928 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3929 max_contiguous);
3930 goto fail;
3931 }
3932
3933 return result;
3934
3935fail:
3936 result.channels = 0;
3937 result.bw_config = 0;
3938 return result;
3939}
3940
3941
3942static struct ieee80211_edmg_config
3943get_supported_edmg(struct wpa_supplicant *wpa_s,
3944 struct hostapd_freq_params *freq,
3945 struct ieee80211_edmg_config request_edmg)
3946{
3947 enum hostapd_hw_mode hw_mode;
3948 struct hostapd_hw_modes *mode = NULL;
3949 u8 primary_channel;
3950
3951 if (!wpa_s->hw.modes)
3952 goto fail;
3953
3954 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3955 if (hw_mode == NUM_HOSTAPD_MODES)
3956 goto fail;
3957
Hai Shalom60840252021-02-19 19:02:11 -08003958 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003959 if (!mode)
3960 goto fail;
3961
3962 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3963
3964fail:
3965 request_edmg.channels = 0;
3966 request_edmg.bw_config = 0;
3967 return request_edmg;
3968}
3969
3970
Hai Shalom021b0b52019-04-10 11:17:58 -07003971#ifdef CONFIG_MBO
3972void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3973{
3974 struct wpa_driver_associate_params params;
3975 u8 *wpa_ie;
3976
3977 /*
3978 * Update MBO connect params only in case of change of MBO attributes
3979 * when connected, if the AP support MBO.
3980 */
3981
3982 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3983 !wpa_s->current_bss ||
3984 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3985 return;
3986
3987 os_memset(&params, 0, sizeof(params));
3988 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3989 wpa_s->current_ssid, &params, NULL);
3990 if (!wpa_ie)
3991 return;
3992
3993 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3994 os_free(wpa_ie);
3995}
3996#endif /* CONFIG_MBO */
3997
3998
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003999static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4000{
4001 struct wpa_connect_work *cwork = work->ctx;
4002 struct wpa_bss *bss = cwork->bss;
4003 struct wpa_ssid *ssid = cwork->ssid;
4004 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004005 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004006 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004007 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004008 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004009 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004010 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004011#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004012 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004013#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004014 int assoc_failed = 0;
4015 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004016 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004017#ifdef CONFIG_HT_OVERRIDES
4018 struct ieee80211_ht_capabilities htcaps;
4019 struct ieee80211_ht_capabilities htcaps_mask;
4020#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004021#ifdef CONFIG_VHT_OVERRIDES
4022 struct ieee80211_vht_capabilities vhtcaps;
4023 struct ieee80211_vht_capabilities vhtcaps_mask;
4024#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004025
Hai Shalomc1a21442022-02-04 13:43:00 -08004026 wpa_s->roam_in_progress = false;
4027#ifdef CONFIG_WNM
4028 wpa_s->bss_trans_mgmt_in_progress = false;
4029#endif /* CONFIG_WNM */
4030
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004031 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004032 if (work->started) {
4033 wpa_s->connect_work = NULL;
4034
4035 /* cancel possible auth. timeout */
4036 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4037 NULL);
4038 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004039 wpas_connect_work_free(cwork);
4040 return;
4041 }
4042
4043 wpa_s->connect_work = work;
4044
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004045 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4046 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004047 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4048 wpas_connect_work_done(wpa_s);
4049 return;
4050 }
4051
Sunil Ravi640215c2023-06-28 23:08:09 +00004052 /*
4053 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4054 * (for MLO connection) as the previous BSSID for reassociation requests
4055 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4056 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4057 * will be zero.
4058 */
4059 os_memcpy(prev_bssid,
4060 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4061 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004062 os_memset(&params, 0, sizeof(params));
4063 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004064 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004065
4066 /* Starting new association, so clear the possibly used WPA IE from the
4067 * previous association. */
4068 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4069 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4070 wpa_s->rsnxe_len = 0;
4071 wpa_s->mscs_setup_done = false;
4072
4073 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4074 if (!wpa_ie) {
4075 wpas_connect_work_done(wpa_s);
4076 return;
4077 }
4078
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004079 if (bss &&
4080 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004081#ifdef CONFIG_IEEE80211R
4082 const u8 *ie, *md = NULL;
4083#endif /* CONFIG_IEEE80211R */
4084 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4085 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4086 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4087 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4088 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4089 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4090 if (bssid_changed)
4091 wpas_notify_bssid_changed(wpa_s);
4092#ifdef CONFIG_IEEE80211R
4093 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4094 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4095 md = ie + 2;
4096 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4097 if (md) {
4098 /* Prepare for the next transition */
4099 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4100 }
4101#endif /* CONFIG_IEEE80211R */
4102#ifdef CONFIG_WPS
4103 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4104 wpa_s->conf->ap_scan == 2 &&
4105 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4106 /* Use ap_scan==1 style network selection to find the network
4107 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004108 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004109 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 wpa_s->reassociate = 1;
4111 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004112 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113 return;
4114#endif /* CONFIG_WPS */
4115 } else {
4116 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4117 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004118 if (bss)
4119 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4120 else
4121 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004123 if (!wpa_s->pno)
4124 wpa_supplicant_cancel_sched_scan(wpa_s);
4125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 wpa_supplicant_cancel_scan(wpa_s);
4127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4129 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004130 cipher_pairwise = wpa_s->pairwise_cipher;
4131 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004132 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4134 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4135 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4136 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004137#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 if (wpa_set_wep_keys(wpa_s, ssid)) {
4139 use_crypt = 1;
4140 wep_keys_set = 1;
4141 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004142#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143 }
4144 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4145 use_crypt = 0;
4146
4147#ifdef IEEE8021X_EAPOL
4148 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4149 if ((ssid->eapol_flags &
4150 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4151 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4152 !wep_keys_set) {
4153 use_crypt = 0;
4154 } else {
4155 /* Assume that dynamic WEP-104 keys will be used and
4156 * set cipher suites in order for drivers to expect
4157 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004158 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004159 }
4160 }
4161#endif /* IEEE8021X_EAPOL */
4162
4163 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4164 /* Set the key before (and later after) association */
4165 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4166 }
4167
Sunil8cd6f4d2022-06-28 18:40:46 +00004168 /* Set current_ssid before changing state to ASSOCIATING, so that the
4169 * selected SSID is available to wpas_notify_state_changed(). */
4170 old_ssid = wpa_s->current_ssid;
4171 wpa_s->current_ssid = ssid;
4172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4174 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 params.ssid = bss->ssid;
4176 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004177 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4178 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004179 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4180 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004181 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004182 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004183 ssid->bssid_set,
4184 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004185 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004186 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004187 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004188 params.bssid_hint = bss->bssid;
4189 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004190 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004192 if (ssid->bssid_hint_set)
4193 params.bssid_hint = ssid->bssid_hint;
4194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195 params.ssid = ssid->ssid;
4196 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004197 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004199
4200 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4201 wpa_s->conf->ap_scan == 2) {
4202 params.bssid = ssid->bssid;
4203 params.fixed_bssid = 1;
4204 }
4205
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004206 /* Initial frequency for IBSS/mesh */
4207 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004208 ssid->frequency > 0 && params.freq.freq == 0)
4209 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004210
4211 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004212 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004213 if (ssid->beacon_int)
4214 params.beacon_int = ssid->beacon_int;
4215 else
4216 params.beacon_int = wpa_s->conf->beacon_int;
4217 }
4218
Hai Shalomc3565922019-10-28 11:58:20 -07004219 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004220 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4221 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004222 else
4223 edmg_ie_oper = NULL;
4224
4225 if (edmg_ie_oper) {
4226 params.freq.edmg.channels =
4227 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4228 params.freq.edmg.bw_config =
4229 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4230 wpa_printf(MSG_DEBUG,
4231 "AP supports EDMG channels 0x%x, bw_config %d",
4232 params.freq.edmg.channels,
4233 params.freq.edmg.bw_config);
4234
4235 /* User may ask for specific EDMG channel for EDMG connection
4236 * (must be supported by AP)
4237 */
4238 if (ssid->edmg_channel) {
4239 struct ieee80211_edmg_config configured_edmg;
4240 enum hostapd_hw_mode hw_mode;
4241 u8 primary_channel;
4242
4243 hw_mode = ieee80211_freq_to_chan(bss->freq,
4244 &primary_channel);
4245 if (hw_mode == NUM_HOSTAPD_MODES)
4246 goto edmg_fail;
4247
4248 hostapd_encode_edmg_chan(ssid->enable_edmg,
4249 ssid->edmg_channel,
4250 primary_channel,
4251 &configured_edmg);
4252
4253 if (ieee802_edmg_is_allowed(params.freq.edmg,
4254 configured_edmg)) {
4255 params.freq.edmg = configured_edmg;
4256 wpa_printf(MSG_DEBUG,
4257 "Use EDMG channel %d for connection",
4258 ssid->edmg_channel);
4259 } else {
4260 edmg_fail:
4261 params.freq.edmg.channels = 0;
4262 params.freq.edmg.bw_config = 0;
4263 wpa_printf(MSG_WARNING,
4264 "EDMG channel %d not supported by AP, fallback to DMG",
4265 ssid->edmg_channel);
4266 }
4267 }
4268
4269 if (params.freq.edmg.channels) {
4270 wpa_printf(MSG_DEBUG,
4271 "EDMG before: channels 0x%x, bw_config %d",
4272 params.freq.edmg.channels,
4273 params.freq.edmg.bw_config);
4274 params.freq.edmg = get_supported_edmg(wpa_s,
4275 &params.freq,
4276 params.freq.edmg);
4277 wpa_printf(MSG_DEBUG,
4278 "EDMG after: channels 0x%x, bw_config %d",
4279 params.freq.edmg.channels,
4280 params.freq.edmg.bw_config);
4281 }
4282 }
4283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284 params.pairwise_suite = cipher_pairwise;
4285 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004286 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004287 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004288 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004289 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004290 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004292 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004293#ifdef CONFIG_WEP
4294 {
4295 int i;
4296
4297 for (i = 0; i < NUM_WEP_KEYS; i++) {
4298 if (ssid->wep_key_len[i])
4299 params.wep_key[i] = ssid->wep_key[i];
4300 params.wep_key_len[i] = ssid->wep_key_len[i];
4301 }
4302 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004304#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004305
Hai Shalom74f70d42019-02-11 14:42:39 -08004306 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004307#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4308 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))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004311#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4312 defined(CONFIG_DRIVER_NL80211_SYNA)
4313 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4314 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4315 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4316 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304317#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004318 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4319 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4320 (params.allowed_key_mgmts &
4321 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004322#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4323 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004324 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004325 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4326 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004327 }
4328
Hai Shalom74f70d42019-02-11 14:42:39 -08004329 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4330 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4331 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4332 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004333 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4334 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004335 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004336
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004337 if (wpa_s->conf->key_mgmt_offload) {
4338 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4339 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004340 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004341 params.key_mgmt_suite ==
4342 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4343 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004344 params.req_key_mgmt_offload =
4345 ssid->proactive_key_caching < 0 ?
4346 wpa_s->conf->okc : ssid->proactive_key_caching;
4347 else
4348 params.req_key_mgmt_offload = 1;
4349
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004350#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4351 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004352 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004353 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4354 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004355#else
4356 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4357 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004358#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4359 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004360 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4361 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004362 }
4363
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004364 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4365 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4366 params.auth_alg = WPA_AUTH_ALG_SAE;
4367 if (ssid->sae_password) {
4368 params.sae_password = ssid->sae_password;
4369 params.sae_password_id = ssid->sae_password_id;
4370 } else if (ssid->passphrase) {
4371 params.passphrase = ssid->passphrase;
4372 }
4373 }
4374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375 params.drop_unencrypted = use_crypt;
4376
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004377 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004378 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004379 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4380 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004381 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4382 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004383 ie.capabilities &
4384 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4385 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4386 "MFP: require MFP");
4387 params.mgmt_frame_protection =
4388 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004389#ifdef CONFIG_OWE
4390 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4391 !ssid->owe_only) {
4392 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4393#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 }
4395 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004396
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004397 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004398
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004399 if (wpa_s->p2pdev->set_sta_uapsd)
4400 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401 else
4402 params.uapsd = -1;
4403
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004404#ifdef CONFIG_HT_OVERRIDES
4405 os_memset(&htcaps, 0, sizeof(htcaps));
4406 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4407 params.htcaps = (u8 *) &htcaps;
4408 params.htcaps_mask = (u8 *) &htcaps_mask;
4409 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4410#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004411#ifdef CONFIG_VHT_OVERRIDES
4412 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4413 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4414 params.vhtcaps = &vhtcaps;
4415 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004416 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004417#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004418#ifdef CONFIG_HE_OVERRIDES
4419 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4420#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004421 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004422
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004423#ifdef CONFIG_P2P
4424 /*
4425 * If multi-channel concurrency is not supported, check for any
4426 * frequency conflict. In case of any frequency conflict, remove the
4427 * least prioritized connection.
4428 */
4429 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004430 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004431 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004432 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004433 wpa_printf(MSG_DEBUG,
4434 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004435 freq, params.freq.freq);
4436 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004437 wpa_s, params.freq.freq, ssid) < 0) {
4438 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004439 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004440 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004441 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004442 }
4443 }
4444#endif /* CONFIG_P2P */
4445
Dmitry Shmidte4663042016-04-04 10:07:49 -07004446 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004447 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004448 params.prev_bssid = prev_bssid;
4449
Hai Shalom60840252021-02-19 19:02:11 -08004450#ifdef CONFIG_SAE
4451 params.sae_pwe = wpa_s->conf->sae_pwe;
4452#endif /* CONFIG_SAE */
4453
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004454 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004455 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004456 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457 if (ret < 0) {
4458 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4459 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004460 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 /*
4462 * The driver is known to mean what is saying, so we
4463 * can stop right here; the association will not
4464 * succeed.
4465 */
4466 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004467 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004468 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004469 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4471 return;
4472 }
4473 /* try to continue anyway; new association will be tried again
4474 * after timeout */
4475 assoc_failed = 1;
4476 }
4477
4478 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4479 /* Set the key after the association just in case association
4480 * cleared the previously configured key. */
4481 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4482 /* No need to timeout authentication since there is no key
4483 * management. */
4484 wpa_supplicant_cancel_auth_timeout(wpa_s);
4485 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4486#ifdef CONFIG_IBSS_RSN
4487 } else if (ssid->mode == WPAS_MODE_IBSS &&
4488 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4489 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4490 /*
4491 * RSN IBSS authentication is per-STA and we can disable the
4492 * per-BSSID authentication.
4493 */
4494 wpa_supplicant_cancel_auth_timeout(wpa_s);
4495#endif /* CONFIG_IBSS_RSN */
4496 } else {
4497 /* Timeout for IEEE 802.11 authentication and association */
4498 int timeout = 60;
4499
4500 if (assoc_failed) {
4501 /* give IBSS a bit more time */
4502 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4503 } else if (wpa_s->conf->ap_scan == 1) {
4504 /* give IBSS a bit more time */
4505 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4506 }
4507 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4508 }
4509
Hai Shalomfdcde762020-04-02 11:19:20 -07004510#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004511 if (wep_keys_set &&
4512 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004513 /* Set static WEP keys again */
4514 wpa_set_wep_keys(wpa_s, ssid);
4515 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004516#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004517
Sunil8cd6f4d2022-06-28 18:40:46 +00004518 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519 /*
4520 * Do not allow EAP session resumption between different
4521 * network configurations.
4522 */
4523 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4524 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004525
4526 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004527 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004528#ifdef CONFIG_HS20
4529 hs20_configure_frame_filters(wpa_s);
4530#endif /* CONFIG_HS20 */
4531 }
4532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004533 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4534 wpa_supplicant_initiate_eapol(wpa_s);
4535 if (old_ssid != wpa_s->current_ssid)
4536 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004537 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4538 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539}
4540
4541
4542static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4543 const u8 *addr)
4544{
4545 struct wpa_ssid *old_ssid;
4546
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004547 wpa_s->ml_connect_probe_ssid = NULL;
4548 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004549 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004550 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004552 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004553 wpa_sm_set_config(wpa_s->wpa, NULL);
4554 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4555 if (old_ssid != wpa_s->current_ssid)
4556 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004557
4558 wpas_scs_deinit(wpa_s);
4559 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4561}
4562
4563
4564/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004565 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4566 * @wpa_s: Pointer to wpa_supplicant data
4567 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4568 *
4569 * This function is used to request %wpa_supplicant to deauthenticate from the
4570 * current AP.
4571 */
4572void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004573 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004574{
4575 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004576 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004577 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004578
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004579 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004580 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004581 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004582 reason_code, reason2str(reason_code),
4583 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004584
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004585 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4586 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4587 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004588 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004589 else if (!is_zero_ether_addr(wpa_s->bssid))
4590 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004591 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4592 /*
4593 * When using driver-based BSS selection, we may not know the
4594 * BSSID with which we are currently trying to associate. We
4595 * need to notify the driver of this disconnection even in such
4596 * a case, so use the all zeros address here.
4597 */
4598 addr = wpa_s->bssid;
4599 zero_addr = 1;
4600 }
4601
Hai Shalom74f70d42019-02-11 14:42:39 -08004602 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4603 wpa_s->enabled_4addr_mode = 0;
4604
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004605#ifdef CONFIG_TDLS
4606 wpa_tdls_teardown_peers(wpa_s->wpa);
4607#endif /* CONFIG_TDLS */
4608
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004609#ifdef CONFIG_MESH
4610 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004611 struct mesh_conf *mconf;
4612
4613 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004614 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4615 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004616 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4617 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004618 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004619 }
4620#endif /* CONFIG_MESH */
4621
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004622 if (addr) {
4623 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004624 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004625 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004626 event.deauth_info.locally_generated = 1;
4627 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004628 if (zero_addr)
4629 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630 }
4631
4632 wpa_supplicant_clear_connection(wpa_s, addr);
4633}
4634
Hai Shalomfdcde762020-04-02 11:19:20 -07004635
4636void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4637{
4638 wpa_s->own_reconnect_req = 1;
4639 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4640
4641}
4642
4643
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004644static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4645 struct wpa_ssid *ssid)
4646{
4647 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4648 return;
4649
4650 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004651 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004652 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4653 wpas_notify_network_enabled_changed(wpa_s, ssid);
4654
4655 /*
4656 * Try to reassociate since there is no current configuration and a new
4657 * network was made available.
4658 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004659 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004660 wpa_s->reassociate = 1;
4661}
4662
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004663
Roshan Pius950bec92016-07-19 09:49:24 -07004664/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004665 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004666 * @wpa_s: wpa_supplicant structure for a network interface
4667 * Returns: The new network configuration or %NULL if operation failed
4668 *
4669 * This function performs the following operations:
4670 * 1. Adds a new network.
4671 * 2. Send network addition notification.
4672 * 3. Marks the network disabled.
4673 * 4. Set network default parameters.
4674 */
4675struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4676{
4677 struct wpa_ssid *ssid;
4678
4679 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004680 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004681 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004682 wpas_notify_network_added(wpa_s, ssid);
4683 ssid->disabled = 1;
4684 wpa_config_set_network_defaults(ssid);
4685
4686 return ssid;
4687}
4688
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004689
Roshan Pius950bec92016-07-19 09:49:24 -07004690/**
4691 * wpa_supplicant_remove_network - Remove a configured network based on id
4692 * @wpa_s: wpa_supplicant structure for a network interface
4693 * @id: Unique network id to search for
4694 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4695 * could not be removed
4696 *
4697 * This function performs the following operations:
4698 * 1. Removes the network.
4699 * 2. Send network removal notification.
4700 * 3. Update internal state machines.
4701 * 4. Stop any running sched scans.
4702 */
4703int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4704{
Sunil Ravia04bd252022-05-02 22:54:18 -07004705 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004706 int was_disabled;
4707
4708 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004709 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004710 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004711 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004712
Sunil Ravia04bd252022-05-02 22:54:18 -07004713 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004714#ifdef CONFIG_SME
4715 wpa_s->sme.prev_bssid_set = 0;
4716#endif /* CONFIG_SME */
4717 /*
4718 * Invalidate the EAP session cache if the current or
4719 * previously used network is removed.
4720 */
4721 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4722 }
4723
Sunil Ravia04bd252022-05-02 22:54:18 -07004724 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004725 wpa_sm_set_config(wpa_s->wpa, NULL);
4726 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4727
4728 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4729 wpa_s->own_disconnect_req = 1;
4730 wpa_supplicant_deauthenticate(wpa_s,
4731 WLAN_REASON_DEAUTH_LEAVING);
4732 }
4733
4734 was_disabled = ssid->disabled;
4735
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004736 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004737 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004738
4739 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004740 wpa_printf(MSG_DEBUG,
4741 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004742 wpa_supplicant_cancel_sched_scan(wpa_s);
4743 wpa_supplicant_req_scan(wpa_s, 0, 0);
4744 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004745
Roshan Pius950bec92016-07-19 09:49:24 -07004746 return 0;
4747}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004750/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004751 * wpa_supplicant_remove_all_networks - Remove all configured networks
4752 * @wpa_s: wpa_supplicant structure for a network interface
4753 * Returns: 0 on success (errors are currently ignored)
4754 *
4755 * This function performs the following operations:
4756 * 1. Remove all networks.
4757 * 2. Send network removal notifications.
4758 * 3. Update internal state machines.
4759 * 4. Stop any running sched scans.
4760 */
4761int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4762{
4763 struct wpa_ssid *ssid;
4764
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304765 if (wpa_s->drv_flags2 &
4766 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4767 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4768 wpa_drv_flush_pmkid(wpa_s);
4769
Hai Shalom899fcc72020-10-19 14:38:18 -07004770 if (wpa_s->sched_scanning)
4771 wpa_supplicant_cancel_sched_scan(wpa_s);
4772
4773 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4774 if (wpa_s->current_ssid) {
4775#ifdef CONFIG_SME
4776 wpa_s->sme.prev_bssid_set = 0;
4777#endif /* CONFIG_SME */
4778 wpa_sm_set_config(wpa_s->wpa, NULL);
4779 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4780 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4781 wpa_s->own_disconnect_req = 1;
4782 wpa_supplicant_deauthenticate(
4783 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4784 }
4785 ssid = wpa_s->conf->ssid;
4786 while (ssid) {
4787 struct wpa_ssid *remove_ssid = ssid;
4788 int id;
4789
4790 id = ssid->id;
4791 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004792 wpas_notify_network_removed(wpa_s, remove_ssid);
4793 wpa_config_remove_network(wpa_s->conf, id);
4794 }
4795 return 0;
4796}
4797
4798
4799/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004800 * wpa_supplicant_enable_network - Mark a configured network as enabled
4801 * @wpa_s: wpa_supplicant structure for a network interface
4802 * @ssid: wpa_ssid structure for a configured network or %NULL
4803 *
4804 * Enables the specified network or all networks if no network specified.
4805 */
4806void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4807 struct wpa_ssid *ssid)
4808{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004810 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4811 wpa_supplicant_enable_one_network(wpa_s, ssid);
4812 } else
4813 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004814
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004815 if (wpa_s->reassociate && !wpa_s->disconnected &&
4816 (!wpa_s->current_ssid ||
4817 wpa_s->wpa_state == WPA_DISCONNECTED ||
4818 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004819 if (wpa_s->sched_scanning) {
4820 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4821 "new network to scan filters");
4822 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004823 }
4824
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004825 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4826 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004827 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004828 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004829 }
4830}
4831
4832
4833/**
4834 * wpa_supplicant_disable_network - Mark a configured network as disabled
4835 * @wpa_s: wpa_supplicant structure for a network interface
4836 * @ssid: wpa_ssid structure for a configured network or %NULL
4837 *
4838 * Disables the specified network or all networks if no network specified.
4839 */
4840void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4841 struct wpa_ssid *ssid)
4842{
4843 struct wpa_ssid *other_ssid;
4844 int was_disabled;
4845
4846 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004847 if (wpa_s->sched_scanning)
4848 wpa_supplicant_cancel_sched_scan(wpa_s);
4849
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004850 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4851 other_ssid = other_ssid->next) {
4852 was_disabled = other_ssid->disabled;
4853 if (was_disabled == 2)
4854 continue; /* do not change persistent P2P group
4855 * data */
4856
4857 other_ssid->disabled = 1;
4858
4859 if (was_disabled != other_ssid->disabled)
4860 wpas_notify_network_enabled_changed(
4861 wpa_s, other_ssid);
4862 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004863 if (wpa_s->current_ssid) {
4864 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4865 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004866 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004867 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004868 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004870 if (ssid == wpa_s->current_ssid) {
4871 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4872 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004873 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004875 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004876
4877 was_disabled = ssid->disabled;
4878
4879 ssid->disabled = 1;
4880
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004881 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004882 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004883 if (wpa_s->sched_scanning) {
4884 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4885 "to remove network from filters");
4886 wpa_supplicant_cancel_sched_scan(wpa_s);
4887 wpa_supplicant_req_scan(wpa_s, 0, 0);
4888 }
4889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004890 }
4891}
4892
4893
4894/**
4895 * wpa_supplicant_select_network - Attempt association with a network
4896 * @wpa_s: wpa_supplicant structure for a network interface
4897 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4898 */
4899void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4900 struct wpa_ssid *ssid)
4901{
4902
4903 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004904 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004906 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004907 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4908 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004909 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004911 disconnected = 1;
4912 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004913
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004914 if (ssid)
4915 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4916
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917 /*
4918 * Mark all other networks disabled or mark all networks enabled if no
4919 * network specified.
4920 */
4921 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4922 other_ssid = other_ssid->next) {
4923 int was_disabled = other_ssid->disabled;
4924 if (was_disabled == 2)
4925 continue; /* do not change persistent P2P group data */
4926
4927 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004928 if (was_disabled && !other_ssid->disabled)
4929 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004930
4931 if (was_disabled != other_ssid->disabled)
4932 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4933 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004934
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004935 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4936 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004937 /* We are already associated with the selected network */
4938 wpa_printf(MSG_DEBUG, "Already associated with the "
4939 "selected network - do nothing");
4940 return;
4941 }
4942
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004943 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004944 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004945 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004946 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004947 (ssid->mode == WPAS_MODE_MESH ||
4948 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004949
4950 /*
4951 * Don't optimize next scan freqs since a new ESS has been
4952 * selected.
4953 */
4954 os_free(wpa_s->next_scan_freqs);
4955 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004956 } else {
4957 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004958 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004959
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960 wpa_s->disconnected = 0;
4961 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004962 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004963 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004964 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004965 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004966 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004967 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004968
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004969 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004970 wpa_supplicant_fast_associate(wpa_s) != 1) {
4971 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004972 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004973 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004974 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004975
4976 if (ssid)
4977 wpas_notify_network_selected(wpa_s, ssid);
4978}
4979
4980
4981/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004982 * wpas_remove_cred - Remove the specified credential and all the network
4983 * entries created based on the removed credential
4984 * @wpa_s: wpa_supplicant structure for a network interface
4985 * @cred: The credential to remove
4986 * Returns: 0 on success, -1 on failure
4987 */
4988int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4989{
4990 struct wpa_ssid *ssid, *next;
4991 int id;
4992
4993 if (!cred) {
4994 wpa_printf(MSG_DEBUG, "Could not find cred");
4995 return -1;
4996 }
4997
4998 id = cred->id;
4999 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5000 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5001 return -1;
5002 }
5003
5004 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5005
5006 /* Remove any network entry created based on the removed credential */
5007 ssid = wpa_s->conf->ssid;
5008 while (ssid) {
5009 next = ssid->next;
5010
5011 if (ssid->parent_cred == cred) {
5012 wpa_printf(MSG_DEBUG,
5013 "Remove network id %d since it used the removed credential",
5014 ssid->id);
5015 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5016 -1) {
5017 wpa_printf(MSG_DEBUG,
5018 "Could not find network id=%d",
5019 ssid->id);
5020 }
5021 }
5022
5023 ssid = next;
5024 }
5025
5026 return 0;
5027}
5028
5029
5030/**
5031 * wpas_remove_cred - Remove all the Interworking credentials
5032 * @wpa_s: wpa_supplicant structure for a network interface
5033 * Returns: 0 on success, -1 on failure
5034 */
5035int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5036{
5037 int res, ret = 0;
5038 struct wpa_cred *cred, *prev;
5039
5040 cred = wpa_s->conf->cred;
5041 while (cred) {
5042 prev = cred;
5043 cred = cred->next;
5044 res = wpas_remove_cred(wpa_s, prev);
5045 if (res < 0) {
5046 wpa_printf(MSG_DEBUG,
5047 "Removal of all credentials failed - failed to remove credential id=%d",
5048 prev->id);
5049 ret = -1;
5050 }
5051 }
5052
5053 return ret;
5054}
5055
5056
5057/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005058 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5059 * @wpa_s: wpa_supplicant structure for a network interface
5060 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5061 * @pkcs11_module_path: PKCS #11 module path or NULL
5062 * Returns: 0 on success; -1 on failure
5063 *
5064 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5065 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5066 * module path fails the paths will be reset to the default value (NULL).
5067 */
5068int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5069 const char *pkcs11_engine_path,
5070 const char *pkcs11_module_path)
5071{
5072 char *pkcs11_engine_path_copy = NULL;
5073 char *pkcs11_module_path_copy = NULL;
5074
5075 if (pkcs11_engine_path != NULL) {
5076 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5077 if (pkcs11_engine_path_copy == NULL)
5078 return -1;
5079 }
5080 if (pkcs11_module_path != NULL) {
5081 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005082 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005083 os_free(pkcs11_engine_path_copy);
5084 return -1;
5085 }
5086 }
5087
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005088#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005089 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005090 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005091#endif /* CONFIG_PKCS11_ENGINE_PATH */
5092#ifndef CONFIG_PKCS11_MODULE_PATH
5093 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005094 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005095#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005096
5097 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5098 eapol_sm_deinit(wpa_s->eapol);
5099 wpa_s->eapol = NULL;
5100 if (wpa_supplicant_init_eapol(wpa_s)) {
5101 /* Error -> Reset paths to the default value (NULL) once. */
5102 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5103 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5104 NULL);
5105
5106 return -1;
5107 }
5108 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5109
5110 return 0;
5111}
5112
5113
5114/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005115 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5116 * @wpa_s: wpa_supplicant structure for a network interface
5117 * @ap_scan: AP scan mode
5118 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5119 *
5120 */
5121int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5122{
5123
5124 int old_ap_scan;
5125
5126 if (ap_scan < 0 || ap_scan > 2)
5127 return -1;
5128
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005129 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5130 wpa_printf(MSG_INFO,
5131 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5132 }
5133
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005134#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005135 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5136 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5137 wpa_s->wpa_state < WPA_COMPLETED) {
5138 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5139 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005140 return 0;
5141 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005142#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005143
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005144 old_ap_scan = wpa_s->conf->ap_scan;
5145 wpa_s->conf->ap_scan = ap_scan;
5146
5147 if (old_ap_scan != wpa_s->conf->ap_scan)
5148 wpas_notify_ap_scan_changed(wpa_s);
5149
5150 return 0;
5151}
5152
5153
5154/**
5155 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5156 * @wpa_s: wpa_supplicant structure for a network interface
5157 * @expire_age: Expiration age in seconds
5158 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5159 *
5160 */
5161int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5162 unsigned int bss_expire_age)
5163{
5164 if (bss_expire_age < 10) {
5165 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5166 bss_expire_age);
5167 return -1;
5168 }
5169 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5170 bss_expire_age);
5171 wpa_s->conf->bss_expiration_age = bss_expire_age;
5172
5173 return 0;
5174}
5175
5176
5177/**
5178 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5179 * @wpa_s: wpa_supplicant structure for a network interface
5180 * @expire_count: number of scans after which an unseen BSS is reclaimed
5181 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5182 *
5183 */
5184int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5185 unsigned int bss_expire_count)
5186{
5187 if (bss_expire_count < 1) {
5188 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5189 bss_expire_count);
5190 return -1;
5191 }
5192 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5193 bss_expire_count);
5194 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5195
5196 return 0;
5197}
5198
5199
5200/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005201 * wpa_supplicant_set_scan_interval - Set scan interval
5202 * @wpa_s: wpa_supplicant structure for a network interface
5203 * @scan_interval: scan interval in seconds
5204 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5205 *
5206 */
5207int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5208 int scan_interval)
5209{
5210 if (scan_interval < 0) {
5211 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5212 scan_interval);
5213 return -1;
5214 }
5215 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5216 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005217 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005218
5219 return 0;
5220}
5221
5222
5223/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005224 * wpa_supplicant_set_debug_params - Set global debug params
5225 * @global: wpa_global structure
5226 * @debug_level: debug level
5227 * @debug_timestamp: determines if show timestamp in debug data
5228 * @debug_show_keys: determines if show keys in debug data
5229 * Returns: 0 if succeed or -1 if debug_level has wrong value
5230 */
5231int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5232 int debug_timestamp, int debug_show_keys)
5233{
5234
5235 int old_level, old_timestamp, old_show_keys;
5236
5237 /* check for allowed debuglevels */
5238 if (debug_level != MSG_EXCESSIVE &&
5239 debug_level != MSG_MSGDUMP &&
5240 debug_level != MSG_DEBUG &&
5241 debug_level != MSG_INFO &&
5242 debug_level != MSG_WARNING &&
5243 debug_level != MSG_ERROR)
5244 return -1;
5245
5246 old_level = wpa_debug_level;
5247 old_timestamp = wpa_debug_timestamp;
5248 old_show_keys = wpa_debug_show_keys;
5249
5250 wpa_debug_level = debug_level;
5251 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5252 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5253
5254 if (wpa_debug_level != old_level)
5255 wpas_notify_debug_level_changed(global);
5256 if (wpa_debug_timestamp != old_timestamp)
5257 wpas_notify_debug_timestamp_changed(global);
5258 if (wpa_debug_show_keys != old_show_keys)
5259 wpas_notify_debug_show_keys_changed(global);
5260
5261 return 0;
5262}
5263
5264
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005265#ifdef CONFIG_OWE
5266static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5267 const u8 *entry_ssid, size_t entry_ssid_len)
5268{
5269 const u8 *owe, *pos, *end;
5270 u8 ssid_len;
5271 struct wpa_bss *bss;
5272
5273 /* Check network profile SSID aganst the SSID in the
5274 * OWE Transition Mode element. */
5275
5276 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5277 if (!bss)
5278 return 0;
5279
5280 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5281 if (!owe)
5282 return 0;
5283
5284 pos = owe + 6;
5285 end = owe + 2 + owe[1];
5286
5287 if (end - pos < ETH_ALEN + 1)
5288 return 0;
5289 pos += ETH_ALEN;
5290 ssid_len = *pos++;
5291 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5292 return 0;
5293
5294 return entry_ssid_len == ssid_len &&
5295 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5296}
5297#endif /* CONFIG_OWE */
5298
5299
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005300/**
5301 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5302 * @wpa_s: Pointer to wpa_supplicant data
5303 * Returns: A pointer to the current network structure or %NULL on failure
5304 */
5305struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5306{
5307 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005308 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005309 int res;
5310 size_t ssid_len;
5311 u8 bssid[ETH_ALEN];
5312 int wired;
5313
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005314 res = wpa_drv_get_ssid(wpa_s, ssid);
5315 if (res < 0) {
5316 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5317 "driver");
5318 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005319 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005320 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005321
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005322 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005323 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5324 "driver");
5325 return NULL;
5326 }
5327
5328 wired = wpa_s->conf->ap_scan == 0 &&
5329 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5330
5331 entry = wpa_s->conf->ssid;
5332 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005333 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005334 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005335 (!entry->ssid ||
5336 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5337 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005338 (!entry->bssid_set ||
5339 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5340 return entry;
5341#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005342 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005343 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5344 (entry->ssid == NULL || entry->ssid_len == 0) &&
5345 (!entry->bssid_set ||
5346 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5347 return entry;
5348#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005349
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005350#ifdef CONFIG_OWE
5351 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005352 (entry->ssid &&
5353 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5354 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005355 (!entry->bssid_set ||
5356 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5357 return entry;
5358#endif /* CONFIG_OWE */
5359
Dmitry Shmidt04949592012-07-19 12:16:46 -07005360 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005361 entry->ssid_len == 0 &&
5362 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5363 return entry;
5364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005365 entry = entry->next;
5366 }
5367
5368 return NULL;
5369}
5370
5371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005372static int select_driver(struct wpa_supplicant *wpa_s, int i)
5373{
5374 struct wpa_global *global = wpa_s->global;
5375
5376 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005377 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005378 if (global->drv_priv[i] == NULL) {
5379 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5380 "'%s'", wpa_drivers[i]->name);
5381 return -1;
5382 }
5383 }
5384
5385 wpa_s->driver = wpa_drivers[i];
5386 wpa_s->global_drv_priv = global->drv_priv[i];
5387
5388 return 0;
5389}
5390
5391
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5393 const char *name)
5394{
5395 int i;
5396 size_t len;
5397 const char *pos, *driver = name;
5398
5399 if (wpa_s == NULL)
5400 return -1;
5401
5402 if (wpa_drivers[0] == NULL) {
5403 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5404 "wpa_supplicant");
5405 return -1;
5406 }
5407
5408 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005409 /* Default to first successful driver in the list */
5410 for (i = 0; wpa_drivers[i]; i++) {
5411 if (select_driver(wpa_s, i) == 0)
5412 return 0;
5413 }
5414 /* Drivers have each reported failure, so no wpa_msg() here. */
5415 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005416 }
5417
5418 do {
5419 pos = os_strchr(driver, ',');
5420 if (pos)
5421 len = pos - driver;
5422 else
5423 len = os_strlen(driver);
5424
5425 for (i = 0; wpa_drivers[i]; i++) {
5426 if (os_strlen(wpa_drivers[i]->name) == len &&
5427 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005428 0) {
5429 /* First driver that succeeds wins */
5430 if (select_driver(wpa_s, i) == 0)
5431 return 0;
5432 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005433 }
5434
5435 driver = pos + 1;
5436 } while (pos);
5437
5438 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5439 return -1;
5440}
5441
5442
5443/**
5444 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5445 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5446 * with struct wpa_driver_ops::init()
5447 * @src_addr: Source address of the EAPOL frame
5448 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5449 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005450 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005451 *
5452 * This function is called for each received EAPOL frame. Most driver
5453 * interfaces rely on more generic OS mechanism for receiving frames through
5454 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5455 * take care of received EAPOL frames and deliver them to the core supplicant
5456 * code by calling this function.
5457 */
5458void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005459 const u8 *buf, size_t len,
5460 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005461{
5462 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005463 const u8 *connected_addr = wpa_s->valid_links ?
5464 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005465
Sunil8cd6f4d2022-06-28 18:40:46 +00005466 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5467 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005468 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5469
Hai Shalomc1a21442022-02-04 13:43:00 -08005470 if (wpa_s->own_disconnect_req) {
5471 wpa_printf(MSG_DEBUG,
5472 "Drop received EAPOL frame as we are disconnecting");
5473 return;
5474 }
5475
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005476#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005477 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5478 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005479 if (wpa_s->ignore_auth_resp) {
5480 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5481 return;
5482 }
5483#endif /* CONFIG_TESTING_OPTIONS */
5484
Jouni Malinena05074c2012-12-21 21:35:35 +02005485 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5486 (wpa_s->last_eapol_matches_bssid &&
5487#ifdef CONFIG_AP
5488 !wpa_s->ap_iface &&
5489#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005490 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005491 /*
5492 * There is possible race condition between receiving the
5493 * association event and the EAPOL frame since they are coming
5494 * through different paths from the driver. In order to avoid
5495 * issues in trying to process the EAPOL frame before receiving
5496 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005497 * the association event is received. This may also be needed in
5498 * driver-based roaming case, so also use src_addr != BSSID as a
5499 * trigger if we have previously confirmed that the
5500 * Authenticator uses BSSID as the src_addr (which is not the
5501 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005502 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005503 wpa_dbg(wpa_s, MSG_DEBUG,
5504 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5505 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005506 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005507 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005508 wpabuf_free(wpa_s->pending_eapol_rx);
5509 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5510 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005511 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5513 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005514 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005515 }
5516 return;
5517 }
5518
Jouni Malinena05074c2012-12-21 21:35:35 +02005519 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005520 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522#ifdef CONFIG_AP
5523 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005524 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5525 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005526 return;
5527 }
5528#endif /* CONFIG_AP */
5529
5530 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5531 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5532 "no key management is configured");
5533 return;
5534 }
5535
5536 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005537 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005538 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5539 wpa_s->wpa_state != WPA_COMPLETED) &&
5540 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005541 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005543 int timeout = 10;
5544
5545 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5546 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5547 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5548 /* Use longer timeout for IEEE 802.1X/EAP */
5549 timeout = 70;
5550 }
5551
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005552#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005553 if (wpa_s->current_ssid && wpa_s->current_bss &&
5554 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5555 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5556 /*
5557 * Use shorter timeout if going through WPS AP iteration
5558 * for PIN config method with an AP that does not
5559 * advertise Selected Registrar.
5560 */
5561 struct wpabuf *wps_ie;
5562
5563 wps_ie = wpa_bss_get_vendor_ie_multi(
5564 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5565 if (wps_ie &&
5566 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5567 timeout = 10;
5568 wpabuf_free(wps_ie);
5569 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005570#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005571
5572 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573 }
5574 wpa_s->eapol_received++;
5575
5576 if (wpa_s->countermeasures) {
5577 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5578 "EAPOL packet");
5579 return;
5580 }
5581
5582#ifdef CONFIG_IBSS_RSN
5583 if (wpa_s->current_ssid &&
5584 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005585 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5586 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005587 return;
5588 }
5589#endif /* CONFIG_IBSS_RSN */
5590
5591 /* Source address of the incoming EAPOL frame could be compared to the
5592 * current BSSID. However, it is possible that a centralized
5593 * Authenticator could be using another MAC address than the BSSID of
5594 * an AP, so just allow any address to be used for now. The replies are
5595 * still sent to the current BSSID (if available), though. */
5596
5597 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5598 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005599 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5600 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005601 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5602 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005603 return;
5604 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005605 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005606 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005607 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5608 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005609 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610 * handshake processing which would normally set portValid. We
5611 * need this to allow the EAPOL state machines to be completed
5612 * without going through EAPOL-Key handshake.
5613 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005614 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615 }
5616}
5617
5618
Sunil8cd6f4d2022-06-28 18:40:46 +00005619static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5620 const u8 *buf, size_t len)
5621{
5622 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5623 FRAME_ENCRYPTION_UNKNOWN);
5624}
5625
5626
Hai Shalomb755a2a2020-04-23 21:49:02 -07005627static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5628{
5629 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5630 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5631}
5632
5633
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005634int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005636 u8 prev_mac_addr[ETH_ALEN];
5637
5638 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5639
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005640 if ((!wpa_s->p2p_mgmt ||
5641 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5642 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005643 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005644 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5645 wpa_drv_get_mac_addr(wpa_s),
5646 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005647 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005648 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005649 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005650 if (wpa_s->l2 == NULL)
5651 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005652
5653 if (l2_packet_set_packet_filter(wpa_s->l2,
5654 L2_PACKET_FILTER_PKTTYPE))
5655 wpa_dbg(wpa_s, MSG_DEBUG,
5656 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005657
5658 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5659 wpa_msg(wpa_s, MSG_ERROR,
5660 "Failed to get own L2 address");
5661 return -1;
5662 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005663 } else {
5664 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5665 if (addr)
5666 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5667 }
5668
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005669 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005670 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005671
Hai Shalomc3565922019-10-28 11:58:20 -07005672#ifdef CONFIG_FST
5673 if (wpa_s->fst)
5674 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5675#endif /* CONFIG_FST */
5676
Sunil Ravi77d572f2023-01-17 23:58:31 +00005677 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5678 wpas_notify_mac_address_changed(wpa_s);
5679
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005680 return 0;
5681}
5682
5683
Dmitry Shmidt04949592012-07-19 12:16:46 -07005684static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5685 const u8 *buf, size_t len)
5686{
5687 struct wpa_supplicant *wpa_s = ctx;
5688 const struct l2_ethhdr *eth;
5689
5690 if (len < sizeof(*eth))
5691 return;
5692 eth = (const struct l2_ethhdr *) buf;
5693
5694 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5695 !(eth->h_dest[0] & 0x01)) {
5696 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5697 " (bridge - not for this interface - ignore)",
5698 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5699 return;
5700 }
5701
5702 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5703 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5704 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005705 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005706}
5707
5708
Hai Shalom899fcc72020-10-19 14:38:18 -07005709int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5710 const char *bridge_ifname)
5711{
5712 if (wpa_s->wpa_state > WPA_SCANNING)
5713 return -EBUSY;
5714
5715 if (bridge_ifname &&
5716 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5717 return -EINVAL;
5718
5719 if (!bridge_ifname)
5720 bridge_ifname = "";
5721
5722 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5723 return 0;
5724
5725 if (wpa_s->l2_br) {
5726 l2_packet_deinit(wpa_s->l2_br);
5727 wpa_s->l2_br = NULL;
5728 }
5729
5730 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5731 sizeof(wpa_s->bridge_ifname));
5732
5733 if (wpa_s->bridge_ifname[0]) {
5734 wpa_dbg(wpa_s, MSG_DEBUG,
5735 "Receiving packets from bridge interface '%s'",
5736 wpa_s->bridge_ifname);
5737 wpa_s->l2_br = l2_packet_init_bridge(
5738 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5739 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5740 if (!wpa_s->l2_br) {
5741 wpa_msg(wpa_s, MSG_ERROR,
5742 "Failed to open l2_packet connection for the bridge interface '%s'",
5743 wpa_s->bridge_ifname);
5744 goto fail;
5745 }
5746 }
5747
5748#ifdef CONFIG_TDLS
5749 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5750 goto fail;
5751#endif /* CONFIG_TDLS */
5752
5753 return 0;
5754fail:
5755 wpa_s->bridge_ifname[0] = 0;
5756 if (wpa_s->l2_br) {
5757 l2_packet_deinit(wpa_s->l2_br);
5758 wpa_s->l2_br = NULL;
5759 }
5760#ifdef CONFIG_TDLS
5761 if (!wpa_s->p2p_mgmt)
5762 wpa_tdls_init(wpa_s->wpa);
5763#endif /* CONFIG_TDLS */
5764 return -EIO;
5765}
5766
5767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005768/**
5769 * wpa_supplicant_driver_init - Initialize driver interface parameters
5770 * @wpa_s: Pointer to wpa_supplicant data
5771 * Returns: 0 on success, -1 on failure
5772 *
5773 * This function is called to initialize driver interface parameters.
5774 * wpa_drv_init() must have been called before this function to initialize the
5775 * driver interface.
5776 */
5777int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5778{
5779 static int interface_count = 0;
5780
5781 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5782 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005783
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005784 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5785 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005786 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005787 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5788
Hai Shalomb755a2a2020-04-23 21:49:02 -07005789 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005790 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5791 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005792 wpa_s->l2_br = l2_packet_init_bridge(
5793 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5794 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005795 if (wpa_s->l2_br == NULL) {
5796 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5797 "connection for the bridge interface '%s'",
5798 wpa_s->bridge_ifname);
5799 return -1;
5800 }
5801 }
5802
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005803 if (wpa_s->conf->ap_scan == 2 &&
5804 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5805 wpa_printf(MSG_INFO,
5806 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5807 }
5808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005809 wpa_clear_keys(wpa_s, NULL);
5810
5811 /* Make sure that TKIP countermeasures are not left enabled (could
5812 * happen if wpa_supplicant is killed during countermeasures. */
5813 wpa_drv_set_countermeasures(wpa_s, 0);
5814
5815 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5816 wpa_drv_flush_pmkid(wpa_s);
5817
5818 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005819 wpa_s->prev_scan_wildcard = 0;
5820
Dmitry Shmidt04949592012-07-19 12:16:46 -07005821 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005822 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5823 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5824 interface_count = 0;
5825 }
Keith Mok4389c282022-11-23 21:36:48 +00005826#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005827 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005828 wpa_supplicant_delayed_sched_scan(wpa_s,
5829 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005830 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005831 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005832 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005833#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005834 interface_count++;
5835 } else
5836 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5837
5838 return 0;
5839}
5840
5841
5842static int wpa_supplicant_daemon(const char *pid_file)
5843{
5844 wpa_printf(MSG_DEBUG, "Daemonize..");
5845 return os_daemonize(pid_file);
5846}
5847
5848
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005849static struct wpa_supplicant *
5850wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851{
5852 struct wpa_supplicant *wpa_s;
5853
5854 wpa_s = os_zalloc(sizeof(*wpa_s));
5855 if (wpa_s == NULL)
5856 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005857 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005858 wpa_s->scan_interval = 5;
5859 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005860 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005861 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005862 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005863 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005864
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005865 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005866 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005867#ifdef CONFIG_TESTING_OPTIONS
5868 dl_list_init(&wpa_s->drv_signal_override);
5869#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005870 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005871 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005872
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005873 return wpa_s;
5874}
5875
5876
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005877#ifdef CONFIG_HT_OVERRIDES
5878
5879static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5880 struct ieee80211_ht_capabilities *htcaps,
5881 struct ieee80211_ht_capabilities *htcaps_mask,
5882 const char *ht_mcs)
5883{
5884 /* parse ht_mcs into hex array */
5885 int i;
5886 const char *tmp = ht_mcs;
5887 char *end = NULL;
5888
5889 /* If ht_mcs is null, do not set anything */
5890 if (!ht_mcs)
5891 return 0;
5892
5893 /* This is what we are setting in the kernel */
5894 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5895
5896 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5897
5898 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005899 long v;
5900
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005901 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005902 v = strtol(tmp, &end, 16);
5903
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005904 if (errno == 0) {
5905 wpa_msg(wpa_s, MSG_DEBUG,
5906 "htcap value[%i]: %ld end: %p tmp: %p",
5907 i, v, end, tmp);
5908 if (end == tmp)
5909 break;
5910
5911 htcaps->supported_mcs_set[i] = v;
5912 tmp = end;
5913 } else {
5914 wpa_msg(wpa_s, MSG_ERROR,
5915 "Failed to parse ht-mcs: %s, error: %s\n",
5916 ht_mcs, strerror(errno));
5917 return -1;
5918 }
5919 }
5920
5921 /*
5922 * If we were able to parse any values, then set mask for the MCS set.
5923 */
5924 if (i) {
5925 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5926 IEEE80211_HT_MCS_MASK_LEN - 1);
5927 /* skip the 3 reserved bits */
5928 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5929 0x1f;
5930 }
5931
5932 return 0;
5933}
5934
5935
5936static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5937 struct ieee80211_ht_capabilities *htcaps,
5938 struct ieee80211_ht_capabilities *htcaps_mask,
5939 int disabled)
5940{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005941 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005942
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005943 if (disabled == -1)
5944 return 0;
5945
Hai Shalom74f70d42019-02-11 14:42:39 -08005946 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5947
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005948 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5949 htcaps_mask->ht_capabilities_info |= msk;
5950 if (disabled)
5951 htcaps->ht_capabilities_info &= msk;
5952 else
5953 htcaps->ht_capabilities_info |= msk;
5954
5955 return 0;
5956}
5957
5958
5959static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5960 struct ieee80211_ht_capabilities *htcaps,
5961 struct ieee80211_ht_capabilities *htcaps_mask,
5962 int factor)
5963{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005964 if (factor == -1)
5965 return 0;
5966
Hai Shalom74f70d42019-02-11 14:42:39 -08005967 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5968
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005969 if (factor < 0 || factor > 3) {
5970 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5971 "Must be 0-3 or -1", factor);
5972 return -EINVAL;
5973 }
5974
5975 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5976 htcaps->a_mpdu_params &= ~0x3;
5977 htcaps->a_mpdu_params |= factor & 0x3;
5978
5979 return 0;
5980}
5981
5982
5983static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5984 struct ieee80211_ht_capabilities *htcaps,
5985 struct ieee80211_ht_capabilities *htcaps_mask,
5986 int density)
5987{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005988 if (density == -1)
5989 return 0;
5990
Hai Shalom74f70d42019-02-11 14:42:39 -08005991 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5992
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005993 if (density < 0 || density > 7) {
5994 wpa_msg(wpa_s, MSG_ERROR,
5995 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5996 density);
5997 return -EINVAL;
5998 }
5999
6000 htcaps_mask->a_mpdu_params |= 0x1C;
6001 htcaps->a_mpdu_params &= ~(0x1C);
6002 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6003
6004 return 0;
6005}
6006
6007
6008static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6009 struct ieee80211_ht_capabilities *htcaps,
6010 struct ieee80211_ht_capabilities *htcaps_mask,
6011 int disabled)
6012{
Hai Shalom74f70d42019-02-11 14:42:39 -08006013 if (disabled)
6014 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006015
Paul Stewart092955c2017-02-06 09:13:09 -08006016 set_disable_ht40(htcaps, disabled);
6017 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006018
6019 return 0;
6020}
6021
6022
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006023static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6024 struct ieee80211_ht_capabilities *htcaps,
6025 struct ieee80211_ht_capabilities *htcaps_mask,
6026 int disabled)
6027{
6028 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006029 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6030 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006031
Hai Shalom74f70d42019-02-11 14:42:39 -08006032 if (disabled)
6033 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006034
6035 if (disabled)
6036 htcaps->ht_capabilities_info &= ~msk;
6037 else
6038 htcaps->ht_capabilities_info |= msk;
6039
6040 htcaps_mask->ht_capabilities_info |= msk;
6041
6042 return 0;
6043}
6044
6045
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006046static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6047 struct ieee80211_ht_capabilities *htcaps,
6048 struct ieee80211_ht_capabilities *htcaps_mask,
6049 int disabled)
6050{
6051 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006052 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006053
Hai Shalom74f70d42019-02-11 14:42:39 -08006054 if (disabled)
6055 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006056
6057 if (disabled)
6058 htcaps->ht_capabilities_info &= ~msk;
6059 else
6060 htcaps->ht_capabilities_info |= msk;
6061
6062 htcaps_mask->ht_capabilities_info |= msk;
6063
6064 return 0;
6065}
6066
6067
Hai Shalom74f70d42019-02-11 14:42:39 -08006068static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6069 struct ieee80211_ht_capabilities *htcaps,
6070 struct ieee80211_ht_capabilities *htcaps_mask,
6071 int tx_stbc)
6072{
6073 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6074
6075 if (tx_stbc == -1)
6076 return 0;
6077
6078 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6079
6080 if (tx_stbc < 0 || tx_stbc > 1) {
6081 wpa_msg(wpa_s, MSG_ERROR,
6082 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6083 return -EINVAL;
6084 }
6085
6086 htcaps_mask->ht_capabilities_info |= msk;
6087 htcaps->ht_capabilities_info &= ~msk;
6088 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6089
6090 return 0;
6091}
6092
6093
6094static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6095 struct ieee80211_ht_capabilities *htcaps,
6096 struct ieee80211_ht_capabilities *htcaps_mask,
6097 int rx_stbc)
6098{
6099 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6100
6101 if (rx_stbc == -1)
6102 return 0;
6103
6104 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6105
6106 if (rx_stbc < 0 || rx_stbc > 3) {
6107 wpa_msg(wpa_s, MSG_ERROR,
6108 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6109 return -EINVAL;
6110 }
6111
6112 htcaps_mask->ht_capabilities_info |= msk;
6113 htcaps->ht_capabilities_info &= ~msk;
6114 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6115
6116 return 0;
6117}
6118
6119
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006120void wpa_supplicant_apply_ht_overrides(
6121 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6122 struct wpa_driver_associate_params *params)
6123{
6124 struct ieee80211_ht_capabilities *htcaps;
6125 struct ieee80211_ht_capabilities *htcaps_mask;
6126
6127 if (!ssid)
6128 return;
6129
6130 params->disable_ht = ssid->disable_ht;
6131 if (!params->htcaps || !params->htcaps_mask)
6132 return;
6133
6134 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6135 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6136 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6137 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6138 ssid->disable_max_amsdu);
6139 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6140 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6141 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006142 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006143 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006144 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6145 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006146
6147 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006148 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006149 htcaps->ht_capabilities_info |= bit;
6150 htcaps_mask->ht_capabilities_info |= bit;
6151 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006152}
6153
6154#endif /* CONFIG_HT_OVERRIDES */
6155
6156
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006157#ifdef CONFIG_VHT_OVERRIDES
6158void wpa_supplicant_apply_vht_overrides(
6159 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6160 struct wpa_driver_associate_params *params)
6161{
6162 struct ieee80211_vht_capabilities *vhtcaps;
6163 struct ieee80211_vht_capabilities *vhtcaps_mask;
6164
6165 if (!ssid)
6166 return;
6167
6168 params->disable_vht = ssid->disable_vht;
6169
6170 vhtcaps = (void *) params->vhtcaps;
6171 vhtcaps_mask = (void *) params->vhtcaps_mask;
6172
6173 if (!vhtcaps || !vhtcaps_mask)
6174 return;
6175
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006176 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6177 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006178
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006179#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006180 if (ssid->disable_sgi) {
6181 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6182 VHT_CAP_SHORT_GI_160);
6183 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6184 VHT_CAP_SHORT_GI_160);
6185 wpa_msg(wpa_s, MSG_DEBUG,
6186 "disable-sgi override specified, vht-caps: 0x%x",
6187 vhtcaps->vht_capabilities_info);
6188 }
6189
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006190 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006191 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6192 int max_ampdu;
6193
6194 max_ampdu = (ssid->vht_capa &
6195 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6196 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006197
6198 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6199 wpa_set_ampdu_factor(wpa_s,
6200 (void *) params->htcaps,
6201 (void *) params->htcaps_mask,
6202 max_ampdu);
6203 }
6204#endif /* CONFIG_HT_OVERRIDES */
6205
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006206#define OVERRIDE_MCS(i) \
6207 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6208 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006209 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006210 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006211 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6212 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006213 } \
6214 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6215 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006216 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006217 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006218 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6219 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006220 }
6221
6222 OVERRIDE_MCS(1);
6223 OVERRIDE_MCS(2);
6224 OVERRIDE_MCS(3);
6225 OVERRIDE_MCS(4);
6226 OVERRIDE_MCS(5);
6227 OVERRIDE_MCS(6);
6228 OVERRIDE_MCS(7);
6229 OVERRIDE_MCS(8);
6230}
6231#endif /* CONFIG_VHT_OVERRIDES */
6232
6233
Hai Shalomfdcde762020-04-02 11:19:20 -07006234#ifdef CONFIG_HE_OVERRIDES
6235void wpa_supplicant_apply_he_overrides(
6236 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6237 struct wpa_driver_associate_params *params)
6238{
6239 if (!ssid)
6240 return;
6241
6242 params->disable_he = ssid->disable_he;
6243}
6244#endif /* CONFIG_HE_OVERRIDES */
6245
6246
Sunil Ravi77d572f2023-01-17 23:58:31 +00006247void wpa_supplicant_apply_eht_overrides(
6248 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6249 struct wpa_driver_associate_params *params)
6250{
6251 if (!ssid)
6252 return;
6253
6254 params->disable_eht = ssid->disable_eht;
6255}
6256
6257
Dmitry Shmidt04949592012-07-19 12:16:46 -07006258static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6259{
6260#ifdef PCSC_FUNCS
6261 size_t len;
6262
6263 if (!wpa_s->conf->pcsc_reader)
6264 return 0;
6265
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006266 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006267 if (!wpa_s->scard)
6268 return 1;
6269
6270 if (wpa_s->conf->pcsc_pin &&
6271 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6272 scard_deinit(wpa_s->scard);
6273 wpa_s->scard = NULL;
6274 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6275 return -1;
6276 }
6277
6278 len = sizeof(wpa_s->imsi) - 1;
6279 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6280 scard_deinit(wpa_s->scard);
6281 wpa_s->scard = NULL;
6282 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6283 return -1;
6284 }
6285 wpa_s->imsi[len] = '\0';
6286
6287 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6288
6289 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6290 wpa_s->imsi, wpa_s->mnc_len);
6291
6292 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6293 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6294#endif /* PCSC_FUNCS */
6295
6296 return 0;
6297}
6298
6299
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006300int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6301{
6302 char *val, *pos;
6303
6304 ext_password_deinit(wpa_s->ext_pw);
6305 wpa_s->ext_pw = NULL;
6306 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6307
6308 if (!wpa_s->conf->ext_password_backend)
6309 return 0;
6310
6311 val = os_strdup(wpa_s->conf->ext_password_backend);
6312 if (val == NULL)
6313 return -1;
6314 pos = os_strchr(val, ':');
6315 if (pos)
6316 *pos++ = '\0';
6317
6318 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6319
6320 wpa_s->ext_pw = ext_password_init(val, pos);
6321 os_free(val);
6322 if (wpa_s->ext_pw == NULL) {
6323 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6324 return -1;
6325 }
6326 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6327
6328 return 0;
6329}
6330
6331
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006332#ifdef CONFIG_FST
6333
6334static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6335{
6336 struct wpa_supplicant *wpa_s = ctx;
6337
6338 return (is_zero_ether_addr(wpa_s->bssid) ||
6339 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6340}
6341
6342
6343static void wpas_fst_get_channel_info_cb(void *ctx,
6344 enum hostapd_hw_mode *hw_mode,
6345 u8 *channel)
6346{
6347 struct wpa_supplicant *wpa_s = ctx;
6348
6349 if (wpa_s->current_bss) {
6350 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6351 channel);
6352 } else if (wpa_s->hw.num_modes) {
6353 *hw_mode = wpa_s->hw.modes[0].mode;
6354 } else {
6355 WPA_ASSERT(0);
6356 *hw_mode = 0;
6357 }
6358}
6359
6360
6361static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6362{
6363 struct wpa_supplicant *wpa_s = ctx;
6364
6365 *modes = wpa_s->hw.modes;
6366 return wpa_s->hw.num_modes;
6367}
6368
6369
6370static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6371{
6372 struct wpa_supplicant *wpa_s = ctx;
6373
6374 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6375 wpa_s->fst_ies = fst_ies;
6376}
6377
6378
6379static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6380{
6381 struct wpa_supplicant *wpa_s = ctx;
6382
Paul Stewart092955c2017-02-06 09:13:09 -08006383 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6384 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6385 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6386 return -1;
6387 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006388 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006389 wpa_s->own_addr, wpa_s->bssid,
6390 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006391 0);
6392}
6393
6394
6395static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6396{
6397 struct wpa_supplicant *wpa_s = ctx;
6398
6399 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6400 return wpa_s->received_mb_ies;
6401}
6402
6403
6404static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6405 const u8 *buf, size_t size)
6406{
6407 struct wpa_supplicant *wpa_s = ctx;
6408 struct mb_ies_info info;
6409
6410 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6411
6412 if (!mb_ies_info_by_ies(&info, buf, size)) {
6413 wpabuf_free(wpa_s->received_mb_ies);
6414 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6415 }
6416}
6417
6418
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006419static const u8 * wpas_fst_get_peer_first(void *ctx,
6420 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006421 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006422{
6423 struct wpa_supplicant *wpa_s = ctx;
6424
6425 *get_ctx = NULL;
6426 if (!is_zero_ether_addr(wpa_s->bssid))
6427 return (wpa_s->received_mb_ies || !mb_only) ?
6428 wpa_s->bssid : NULL;
6429 return NULL;
6430}
6431
6432
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006433static const u8 * wpas_fst_get_peer_next(void *ctx,
6434 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006435 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006436{
6437 return NULL;
6438}
6439
6440void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6441 struct fst_wpa_obj *iface_obj)
6442{
Sunil8cd6f4d2022-06-28 18:40:46 +00006443 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006444 iface_obj->ctx = wpa_s;
6445 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6446 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6447 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6448 iface_obj->set_ies = wpas_fst_set_ies_cb;
6449 iface_obj->send_action = wpas_fst_send_action_cb;
6450 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6451 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6452 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6453 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6454}
6455#endif /* CONFIG_FST */
6456
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006457static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006458 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006459{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006460 struct wowlan_triggers *triggers;
6461 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006462
6463 if (!wpa_s->conf->wowlan_triggers)
6464 return 0;
6465
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006466 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6467 if (triggers) {
6468 ret = wpa_drv_wowlan(wpa_s, triggers);
6469 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006470 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006471 return ret;
6472}
6473
6474
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006475enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006476{
6477 if (freq < 3000)
6478 return BAND_2_4_GHZ;
6479 if (freq > 50000)
6480 return BAND_60_GHZ;
6481 return BAND_5_GHZ;
6482}
6483
6484
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006485unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006486{
6487 int i;
6488 unsigned int band = 0;
6489
6490 if (freqs) {
6491 /* freqs are specified for the radio work */
6492 for (i = 0; freqs[i]; i++)
6493 band |= wpas_freq_to_band(freqs[i]);
6494 } else {
6495 /*
6496 * freqs are not specified, implies all
6497 * the supported freqs by HW
6498 */
6499 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6500 if (wpa_s->hw.modes[i].num_channels != 0) {
6501 if (wpa_s->hw.modes[i].mode ==
6502 HOSTAPD_MODE_IEEE80211B ||
6503 wpa_s->hw.modes[i].mode ==
6504 HOSTAPD_MODE_IEEE80211G)
6505 band |= BAND_2_4_GHZ;
6506 else if (wpa_s->hw.modes[i].mode ==
6507 HOSTAPD_MODE_IEEE80211A)
6508 band |= BAND_5_GHZ;
6509 else if (wpa_s->hw.modes[i].mode ==
6510 HOSTAPD_MODE_IEEE80211AD)
6511 band |= BAND_60_GHZ;
6512 else if (wpa_s->hw.modes[i].mode ==
6513 HOSTAPD_MODE_IEEE80211ANY)
6514 band = BAND_2_4_GHZ | BAND_5_GHZ |
6515 BAND_60_GHZ;
6516 }
6517 }
6518 }
6519
6520 return band;
6521}
6522
6523
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006524static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6525 const char *rn)
6526{
6527 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6528 struct wpa_radio *radio;
6529
6530 while (rn && iface) {
6531 radio = iface->radio;
6532 if (radio && os_strcmp(rn, radio->name) == 0) {
6533 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6534 wpa_s->ifname, rn);
6535 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6536 return radio;
6537 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006538
6539 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006540 }
6541
6542 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6543 wpa_s->ifname, rn ? rn : "N/A");
6544 radio = os_zalloc(sizeof(*radio));
6545 if (radio == NULL)
6546 return NULL;
6547
6548 if (rn)
6549 os_strlcpy(radio->name, rn, sizeof(radio->name));
6550 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006551 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006552 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6553
6554 return radio;
6555}
6556
6557
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006558static void radio_work_free(struct wpa_radio_work *work)
6559{
6560 if (work->wpa_s->scan_work == work) {
6561 /* This should not really happen. */
6562 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6563 work->type, work, work->started);
6564 work->wpa_s->scan_work = NULL;
6565 }
6566
6567#ifdef CONFIG_P2P
6568 if (work->wpa_s->p2p_scan_work == work) {
6569 /* This should not really happen. */
6570 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6571 work->type, work, work->started);
6572 work->wpa_s->p2p_scan_work = NULL;
6573 }
6574#endif /* CONFIG_P2P */
6575
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006576 if (work->started) {
6577 work->wpa_s->radio->num_active_works--;
6578 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006579 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006580 work->type, work,
6581 work->wpa_s->radio->num_active_works);
6582 }
6583
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006584 dl_list_del(&work->list);
6585 os_free(work);
6586}
6587
6588
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006589static int radio_work_is_connect(struct wpa_radio_work *work)
6590{
6591 return os_strcmp(work->type, "sme-connect") == 0 ||
6592 os_strcmp(work->type, "connect") == 0;
6593}
6594
6595
6596static int radio_work_is_scan(struct wpa_radio_work *work)
6597{
6598 return os_strcmp(work->type, "scan") == 0 ||
6599 os_strcmp(work->type, "p2p-scan") == 0;
6600}
6601
6602
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006603static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6604{
6605 struct wpa_radio_work *active_work = NULL;
6606 struct wpa_radio_work *tmp;
6607
6608 /* Get the active work to know the type and band. */
6609 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6610 if (tmp->started) {
6611 active_work = tmp;
6612 break;
6613 }
6614 }
6615
6616 if (!active_work) {
6617 /* No active work, start one */
6618 radio->num_active_works = 0;
6619 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6620 list) {
6621 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006622 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006623 (((struct wpa_driver_scan_params *)
6624 tmp->ctx)->only_new_results ||
6625 tmp->wpa_s->clear_driver_scan_cache))
6626 continue;
6627 return tmp;
6628 }
6629 return NULL;
6630 }
6631
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006632 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006633 /*
6634 * If the active work is either connect or sme-connect,
6635 * do not parallelize them with other radio works.
6636 */
6637 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6638 "Do not parallelize radio work with %s",
6639 active_work->type);
6640 return NULL;
6641 }
6642
6643 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6644 if (tmp->started)
6645 continue;
6646
6647 /*
6648 * If connect or sme-connect are enqueued, parallelize only
6649 * those operations ahead of them in the queue.
6650 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006651 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006652 break;
6653
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006654 /* Serialize parallel scan and p2p_scan operations on the same
6655 * interface since the driver_nl80211 mechanism for tracking
6656 * scan cookies does not yet have support for this. */
6657 if (active_work->wpa_s == tmp->wpa_s &&
6658 radio_work_is_scan(active_work) &&
6659 radio_work_is_scan(tmp)) {
6660 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6661 "Do not start work '%s' when another work '%s' is already scheduled",
6662 tmp->type, active_work->type);
6663 continue;
6664 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006665 /*
6666 * Check that the radio works are distinct and
6667 * on different bands.
6668 */
6669 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6670 (active_work->bands != tmp->bands)) {
6671 /*
6672 * If a scan has to be scheduled through nl80211 scan
6673 * interface and if an external scan is already running,
6674 * do not schedule the scan since it is likely to get
6675 * rejected by kernel.
6676 */
6677 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006678 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006679 (((struct wpa_driver_scan_params *)
6680 tmp->ctx)->only_new_results ||
6681 tmp->wpa_s->clear_driver_scan_cache))
6682 continue;
6683
6684 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6685 "active_work:%s new_work:%s",
6686 active_work->type, tmp->type);
6687 return tmp;
6688 }
6689 }
6690
6691 /* Did not find a radio work to schedule in parallel. */
6692 return NULL;
6693}
6694
6695
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006696static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6697{
6698 struct wpa_radio *radio = eloop_ctx;
6699 struct wpa_radio_work *work;
6700 struct os_reltime now, diff;
6701 struct wpa_supplicant *wpa_s;
6702
6703 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006704 if (work == NULL) {
6705 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006706 return;
6707 }
6708
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006709 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6710 radio_list);
6711
6712 if (!(wpa_s &&
6713 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6714 if (work->started)
6715 return; /* already started and still in progress */
6716
Hai Shalom60840252021-02-19 19:02:11 -08006717 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006718 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6719 return;
6720 }
6721 } else {
6722 work = NULL;
6723 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6724 /* get the work to schedule next */
6725 work = radio_work_get_next_work(radio);
6726 }
6727 if (!work)
6728 return;
6729 }
6730
6731 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006732 os_get_reltime(&now);
6733 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006734 wpa_dbg(wpa_s, MSG_DEBUG,
6735 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006736 work->type, work, diff.sec, diff.usec);
6737 work->started = 1;
6738 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006739 radio->num_active_works++;
6740
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006741 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006742
6743 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6744 radio->num_active_works < MAX_ACTIVE_WORKS)
6745 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006746}
6747
6748
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006749/*
6750 * This function removes both started and pending radio works running on
6751 * the provided interface's radio.
6752 * Prior to the removal of the radio work, its callback (cb) is called with
6753 * deinit set to be 1. Each work's callback is responsible for clearing its
6754 * internal data and restoring to a correct state.
6755 * @wpa_s: wpa_supplicant data
6756 * @type: type of works to be removed
6757 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6758 * this interface's works.
6759 */
6760void radio_remove_works(struct wpa_supplicant *wpa_s,
6761 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006762{
6763 struct wpa_radio_work *work, *tmp;
6764 struct wpa_radio *radio = wpa_s->radio;
6765
6766 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6767 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006768 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006769 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006770
6771 /* skip other ifaces' works */
6772 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006773 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006774
6775 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6776 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006777 work->cb(work, 1);
6778 radio_work_free(work);
6779 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006780
6781 /* in case we removed the started work */
6782 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006783}
6784
6785
Roshan Pius3a1667e2018-07-03 15:17:14 -07006786void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6787{
6788 struct wpa_radio_work *work;
6789 struct wpa_radio *radio = wpa_s->radio;
6790
6791 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6792 if (work->ctx != ctx)
6793 continue;
6794 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6795 work->type, work, work->started ? " (started)" : "");
6796 radio_work_free(work);
6797 break;
6798 }
6799}
6800
6801
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006802static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6803{
6804 struct wpa_radio *radio = wpa_s->radio;
6805
6806 if (!radio)
6807 return;
6808
6809 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6810 wpa_s->ifname, radio->name);
6811 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006812 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006813 /* If the interface that triggered the external scan was removed, the
6814 * external scan is no longer running. */
6815 if (wpa_s == radio->external_scan_req_interface)
6816 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006817 wpa_s->radio = NULL;
6818 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006819 return; /* Interfaces remain for this radio */
6820
6821 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006822 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006823 os_free(radio);
6824}
6825
6826
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006827void radio_work_check_next(struct wpa_supplicant *wpa_s)
6828{
6829 struct wpa_radio *radio = wpa_s->radio;
6830
6831 if (dl_list_empty(&radio->work))
6832 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006833 if (wpa_s->ext_work_in_progress) {
6834 wpa_printf(MSG_DEBUG,
6835 "External radio work in progress - delay start of pending item");
6836 return;
6837 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006838 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6839 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6840}
6841
6842
6843/**
6844 * radio_add_work - Add a radio work item
6845 * @wpa_s: Pointer to wpa_supplicant data
6846 * @freq: Frequency of the offchannel operation in MHz or 0
6847 * @type: Unique identifier for each type of work
6848 * @next: Force as the next work to be executed
6849 * @cb: Callback function for indicating when radio is available
6850 * @ctx: Context pointer for the work (work->ctx in cb())
6851 * Returns: 0 on success, -1 on failure
6852 *
6853 * This function is used to request time for an operation that requires
6854 * exclusive radio control. Once the radio is available, the registered callback
6855 * function will be called. radio_work_done() must be called once the exclusive
6856 * radio operation has been completed, so that the radio is freed for other
6857 * operations. The special case of deinit=1 is used to free the context data
6858 * during interface removal. That does not allow the callback function to start
6859 * the radio operation, i.e., it must free any resources allocated for the radio
6860 * work and return.
6861 *
6862 * The @freq parameter can be used to indicate a single channel on which the
6863 * offchannel operation will occur. This may allow multiple radio work
6864 * operations to be performed in parallel if they apply for the same channel.
6865 * Setting this to 0 indicates that the work item may use multiple channels or
6866 * requires exclusive control of the radio.
6867 */
6868int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6869 const char *type, int next,
6870 void (*cb)(struct wpa_radio_work *work, int deinit),
6871 void *ctx)
6872{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006873 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006874 struct wpa_radio_work *work;
6875 int was_empty;
6876
6877 work = os_zalloc(sizeof(*work));
6878 if (work == NULL)
6879 return -1;
6880 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6881 os_get_reltime(&work->time);
6882 work->freq = freq;
6883 work->type = type;
6884 work->wpa_s = wpa_s;
6885 work->cb = cb;
6886 work->ctx = ctx;
6887
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006888 if (freq)
6889 work->bands = wpas_freq_to_band(freq);
6890 else if (os_strcmp(type, "scan") == 0 ||
6891 os_strcmp(type, "p2p-scan") == 0)
6892 work->bands = wpas_get_bands(wpa_s,
6893 ((struct wpa_driver_scan_params *)
6894 ctx)->freqs);
6895 else
6896 work->bands = wpas_get_bands(wpa_s, NULL);
6897
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006898 was_empty = dl_list_empty(&wpa_s->radio->work);
6899 if (next)
6900 dl_list_add(&wpa_s->radio->work, &work->list);
6901 else
6902 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6903 if (was_empty) {
6904 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6905 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006906 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6907 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6908 wpa_dbg(wpa_s, MSG_DEBUG,
6909 "Try to schedule a radio work (num_active_works=%u)",
6910 radio->num_active_works);
6911 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006912 }
6913
6914 return 0;
6915}
6916
6917
6918/**
6919 * radio_work_done - Indicate that a radio work item has been completed
6920 * @work: Completed work
6921 *
6922 * This function is called once the callback function registered with
6923 * radio_add_work() has completed its work.
6924 */
6925void radio_work_done(struct wpa_radio_work *work)
6926{
6927 struct wpa_supplicant *wpa_s = work->wpa_s;
6928 struct os_reltime now, diff;
6929 unsigned int started = work->started;
6930
6931 os_get_reltime(&now);
6932 os_reltime_sub(&now, &work->time, &diff);
6933 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6934 work->type, work, started ? "done" : "canceled",
6935 diff.sec, diff.usec);
6936 radio_work_free(work);
6937 if (started)
6938 radio_work_check_next(wpa_s);
6939}
6940
6941
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006942struct wpa_radio_work *
6943radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006944{
6945 struct wpa_radio_work *work;
6946 struct wpa_radio *radio = wpa_s->radio;
6947
6948 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6949 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006950 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006951 }
6952
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006953 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006954}
6955
6956
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006957static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006958 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006959{
6960 const char *ifname, *driver, *rn;
6961
6962 driver = iface->driver;
6963next_driver:
6964 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6965 return -1;
6966
6967 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6968 if (wpa_s->drv_priv == NULL) {
6969 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006970 int level = MSG_ERROR;
6971
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006972 pos = driver ? os_strchr(driver, ',') : NULL;
6973 if (pos) {
6974 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6975 "driver interface - try next driver wrapper");
6976 driver = pos + 1;
6977 goto next_driver;
6978 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006979
6980#ifdef CONFIG_MATCH_IFACE
6981 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6982 level = MSG_DEBUG;
6983#endif /* CONFIG_MATCH_IFACE */
6984 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006985 return -1;
6986 }
6987 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6988 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6989 "driver_param '%s'", wpa_s->conf->driver_param);
6990 return -1;
6991 }
6992
6993 ifname = wpa_drv_get_ifname(wpa_s);
6994 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6995 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6996 "interface name with '%s'", ifname);
6997 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6998 }
6999
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007000 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007001 if (rn && rn[0] == '\0')
7002 rn = NULL;
7003
7004 wpa_s->radio = radio_add_interface(wpa_s, rn);
7005 if (wpa_s->radio == NULL)
7006 return -1;
7007
7008 return 0;
7009}
7010
7011
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007012#ifdef CONFIG_GAS_SERVER
7013
7014static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7015 unsigned int freq, const u8 *dst,
7016 const u8 *src, const u8 *bssid,
7017 const u8 *data, size_t data_len,
7018 enum offchannel_send_action_result result)
7019{
7020 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7021 " result=%s",
7022 freq, MAC2STR(dst),
7023 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7024 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7025 "FAILED"));
7026 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7027 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7028}
7029
7030
7031static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7032 struct wpabuf *buf, unsigned int wait_time)
7033{
7034 struct wpa_supplicant *wpa_s = ctx;
7035 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7036
7037 if (wait_time > wpa_s->max_remain_on_chan)
7038 wait_time = wpa_s->max_remain_on_chan;
7039
7040 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7041 wpabuf_head(buf), wpabuf_len(buf),
7042 wait_time, wpas_gas_server_tx_status, 0);
7043}
7044
7045#endif /* CONFIG_GAS_SERVER */
7046
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007048 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007049{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007050 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007051 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007052 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007053
7054 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7055 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7056 iface->confname ? iface->confname : "N/A",
7057 iface->driver ? iface->driver : "default",
7058 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7059 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7060
7061 if (iface->confname) {
7062#ifdef CONFIG_BACKEND_FILE
7063 wpa_s->confname = os_rel2abs_path(iface->confname);
7064 if (wpa_s->confname == NULL) {
7065 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7066 "for configuration file '%s'.",
7067 iface->confname);
7068 return -1;
7069 }
7070 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7071 iface->confname, wpa_s->confname);
7072#else /* CONFIG_BACKEND_FILE */
7073 wpa_s->confname = os_strdup(iface->confname);
7074#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007075 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007076 if (wpa_s->conf == NULL) {
7077 wpa_printf(MSG_ERROR, "Failed to read or parse "
7078 "configuration '%s'.", wpa_s->confname);
7079 return -1;
7080 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007081 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007082 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007083 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007084 wpa_printf(MSG_ERROR,
7085 "Failed to read or parse configuration '%s'.",
7086 wpa_s->confanother);
7087 return -1;
7088 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007089
7090 /*
7091 * Override ctrl_interface and driver_param if set on command
7092 * line.
7093 */
7094 if (iface->ctrl_interface) {
7095 os_free(wpa_s->conf->ctrl_interface);
7096 wpa_s->conf->ctrl_interface =
7097 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007098 if (!wpa_s->conf->ctrl_interface) {
7099 wpa_printf(MSG_ERROR,
7100 "Failed to duplicate control interface '%s'.",
7101 iface->ctrl_interface);
7102 return -1;
7103 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007104 }
7105
7106 if (iface->driver_param) {
7107 os_free(wpa_s->conf->driver_param);
7108 wpa_s->conf->driver_param =
7109 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007110 if (!wpa_s->conf->driver_param) {
7111 wpa_printf(MSG_ERROR,
7112 "Failed to duplicate driver param '%s'.",
7113 iface->driver_param);
7114 return -1;
7115 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007116 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007117
7118 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7119 os_free(wpa_s->conf->ctrl_interface);
7120 wpa_s->conf->ctrl_interface = NULL;
7121 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007122 } else
7123 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7124 iface->driver_param);
7125
7126 if (wpa_s->conf == NULL) {
7127 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7128 return -1;
7129 }
7130
7131 if (iface->ifname == NULL) {
7132 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7133 return -1;
7134 }
7135 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7136 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7137 iface->ifname);
7138 return -1;
7139 }
7140 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007141#ifdef CONFIG_MATCH_IFACE
7142 wpa_s->matched = iface->matched;
7143#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144
7145 if (iface->bridge_ifname) {
7146 if (os_strlen(iface->bridge_ifname) >=
7147 sizeof(wpa_s->bridge_ifname)) {
7148 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7149 "name '%s'.", iface->bridge_ifname);
7150 return -1;
7151 }
7152 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7153 sizeof(wpa_s->bridge_ifname));
7154 }
7155
7156 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007157 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7158 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007159
7160 /* Initialize driver interface and register driver event handler before
7161 * L2 receive handler so that association events are processed before
7162 * EAPOL-Key packets if both become available for the same select()
7163 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007164 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007165 return -1;
7166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007167 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7168 return -1;
7169
7170 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7171 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7172 NULL);
7173 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7174
7175 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7176 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7177 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7178 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7179 "dot11RSNAConfigPMKLifetime");
7180 return -1;
7181 }
7182
7183 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7184 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7185 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7186 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7187 "dot11RSNAConfigPMKReauthThreshold");
7188 return -1;
7189 }
7190
7191 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7192 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7193 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7194 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7195 "dot11RSNAConfigSATimeout");
7196 return -1;
7197 }
7198
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007199 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7200 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007201 &wpa_s->hw.flags,
7202 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007203 if (wpa_s->hw.modes) {
7204 u16 i;
7205
7206 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7207 if (wpa_s->hw.modes[i].vht_capab) {
7208 wpa_s->hw_capab = CAPAB_VHT;
7209 break;
7210 }
7211
7212 if (wpa_s->hw.modes[i].ht_capab &
7213 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7214 wpa_s->hw_capab = CAPAB_HT40;
7215 else if (wpa_s->hw.modes[i].ht_capab &&
7216 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7217 wpa_s->hw_capab = CAPAB_HT;
7218 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007219 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007220 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007221
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007222 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7223 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007224 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007225 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007226 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007227 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007228 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007229 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007230 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007231 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007232 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007233 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7234 wpa_s->max_sched_scan_plan_interval =
7235 capa.max_sched_scan_plan_interval;
7236 wpa_s->max_sched_scan_plan_iterations =
7237 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007238 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7239 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007240 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7241 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007242 wpa_s->extended_capa = capa.extended_capa;
7243 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7244 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007245 wpa_s->num_multichan_concurrent =
7246 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007247 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007248 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007249
7250 if (capa.mac_addr_rand_scan_supported)
7251 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7252 if (wpa_s->sched_scan_supported &&
7253 capa.mac_addr_rand_sched_scan_supported)
7254 wpa_s->mac_addr_rand_supported |=
7255 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007256
7257 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7258 if (wpa_s->extended_capa &&
7259 wpa_s->extended_capa_len >= 3 &&
7260 wpa_s->extended_capa[2] & 0x40)
7261 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007262 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007263#ifdef CONFIG_PASN
7264 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7265#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007266 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7267 !!(wpa_s->drv_flags &
7268 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007269 if (wpa_s->max_remain_on_chan == 0)
7270 wpa_s->max_remain_on_chan = 1000;
7271
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007272 /*
7273 * Only take p2p_mgmt parameters when P2P Device is supported.
7274 * Doing it here as it determines whether l2_packet_init() will be done
7275 * during wpa_supplicant_driver_init().
7276 */
7277 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7278 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007279
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007280 if (wpa_s->num_multichan_concurrent == 0)
7281 wpa_s->num_multichan_concurrent = 1;
7282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007283 if (wpa_supplicant_driver_init(wpa_s) < 0)
7284 return -1;
7285
7286#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007287 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007288 return -1;
7289#endif /* CONFIG_TDLS */
7290
7291 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7292 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7293 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7294 return -1;
7295 }
7296
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007297#ifdef CONFIG_FST
7298 if (wpa_s->conf->fst_group_id) {
7299 struct fst_iface_cfg cfg;
7300 struct fst_wpa_obj iface_obj;
7301
7302 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7303 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7304 sizeof(cfg.group_id));
7305 cfg.priority = wpa_s->conf->fst_priority;
7306 cfg.llt = wpa_s->conf->fst_llt;
7307
7308 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7309 &iface_obj, &cfg);
7310 if (!wpa_s->fst) {
7311 wpa_msg(wpa_s, MSG_ERROR,
7312 "FST: Cannot attach iface %s to group %s",
7313 wpa_s->ifname, cfg.group_id);
7314 return -1;
7315 }
7316 }
7317#endif /* CONFIG_FST */
7318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007319 if (wpas_wps_init(wpa_s))
7320 return -1;
7321
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007322#ifdef CONFIG_GAS_SERVER
7323 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7324 if (!wpa_s->gas_server) {
7325 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7326 return -1;
7327 }
7328#endif /* CONFIG_GAS_SERVER */
7329
7330#ifdef CONFIG_DPP
7331 if (wpas_dpp_init(wpa_s) < 0)
7332 return -1;
7333#endif /* CONFIG_DPP */
7334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007335 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7336 return -1;
7337 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7338
7339 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7340 if (wpa_s->ctrl_iface == NULL) {
7341 wpa_printf(MSG_ERROR,
7342 "Failed to initialize control interface '%s'.\n"
7343 "You may have another wpa_supplicant process "
7344 "already running or the file was\n"
7345 "left by an unclean termination of wpa_supplicant "
7346 "in which case you will need\n"
7347 "to manually remove this file before starting "
7348 "wpa_supplicant again.\n",
7349 wpa_s->conf->ctrl_interface);
7350 return -1;
7351 }
7352
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007353 wpa_s->gas = gas_query_init(wpa_s);
7354 if (wpa_s->gas == NULL) {
7355 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7356 return -1;
7357 }
7358
Roshan Pius3a1667e2018-07-03 15:17:14 -07007359 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7360 wpa_s->p2p_mgmt) &&
7361 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007362 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7363 return -1;
7364 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007365
7366 if (wpa_bss_init(wpa_s) < 0)
7367 return -1;
7368
Paul Stewart092955c2017-02-06 09:13:09 -08007369#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7370#ifdef CONFIG_MESH
7371 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7372#endif /* CONFIG_MESH */
7373#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7374
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007375 /*
7376 * Set Wake-on-WLAN triggers, if configured.
7377 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7378 * have effect anyway when the interface is down).
7379 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007380 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007381 return -1;
7382
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007383#ifdef CONFIG_EAP_PROXY
7384{
7385 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007386 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7387 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007388 if (wpa_s->mnc_len > 0) {
7389 wpa_s->imsi[len] = '\0';
7390 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7391 wpa_s->imsi, wpa_s->mnc_len);
7392 } else {
7393 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7394 }
7395}
7396#endif /* CONFIG_EAP_PROXY */
7397
Dmitry Shmidt04949592012-07-19 12:16:46 -07007398 if (pcsc_reader_init(wpa_s) < 0)
7399 return -1;
7400
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007401 if (wpas_init_ext_pw(wpa_s) < 0)
7402 return -1;
7403
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007404 wpas_rrm_reset(wpa_s);
7405
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007406 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7407
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007408#ifdef CONFIG_HS20
7409 hs20_init(wpa_s);
7410#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007411#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007412 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007413 if ((wpa_s->conf->oce & OCE_STA) &&
7414 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7415 wpa_s->enable_oce = OCE_STA;
7416 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7417 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7418 /* TODO: Need to add STA-CFON support */
7419 wpa_printf(MSG_ERROR,
7420 "OCE STA-CFON feature is not yet supported");
7421 }
7422 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007423 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7424#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007425
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007426 wpa_supplicant_set_default_scan_ies(wpa_s);
7427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428 return 0;
7429}
7430
7431
7432static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007433 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007434{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007435 struct wpa_global *global = wpa_s->global;
7436 struct wpa_supplicant *iface, *prev;
7437
Jimmy Chen0e73c002021-08-18 13:21:30 +08007438 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007439 wpas_p2p_group_remove(wpa_s, "*");
7440
7441 iface = global->ifaces;
7442 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007443 if (iface->p2pdev == wpa_s)
7444 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007445 if (iface == wpa_s || iface->parent != wpa_s) {
7446 iface = iface->next;
7447 continue;
7448 }
7449 wpa_printf(MSG_DEBUG,
7450 "Remove remaining child interface %s from parent %s",
7451 iface->ifname, wpa_s->ifname);
7452 prev = iface;
7453 iface = iface->next;
7454 wpa_supplicant_remove_iface(global, prev, terminate);
7455 }
7456
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007457 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007458 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007459 /*
7460 * Don't deauthenticate if WoWLAN is enable and not explicitly
7461 * been configured to disconnect.
7462 */
7463 if (!wpa_drv_get_wowlan(wpa_s) ||
7464 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007465 wpa_supplicant_deauthenticate(
7466 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467
Hai Shalomfdcde762020-04-02 11:19:20 -07007468 wpa_drv_set_countermeasures(wpa_s, 0);
7469 wpa_clear_keys(wpa_s, NULL);
7470 } else {
7471 wpa_msg(wpa_s, MSG_INFO,
7472 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7473 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007474 }
7475
7476 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007477 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007478
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007479 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007480 radio_remove_interface(wpa_s);
7481
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007482#ifdef CONFIG_FST
7483 if (wpa_s->fst) {
7484 fst_detach(wpa_s->fst);
7485 wpa_s->fst = NULL;
7486 }
7487 if (wpa_s->received_mb_ies) {
7488 wpabuf_free(wpa_s->received_mb_ies);
7489 wpa_s->received_mb_ies = NULL;
7490 }
7491#endif /* CONFIG_FST */
7492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007493 if (wpa_s->drv_priv)
7494 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007495
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007496 if (notify)
7497 wpas_notify_iface_removed(wpa_s);
7498
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007499 if (terminate)
7500 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007501
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007502 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7503 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007504
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007505#ifdef CONFIG_MESH
7506 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007507 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007508 wpa_s->ifmsh = NULL;
7509 }
7510#endif /* CONFIG_MESH */
7511
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007512 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007513 wpa_config_free(wpa_s->conf);
7514 wpa_s->conf = NULL;
7515 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007516
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007517 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007518 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007519
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007520 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007521}
7522
7523
Dmitry Shmidte4663042016-04-04 10:07:49 -07007524#ifdef CONFIG_MATCH_IFACE
7525
7526/**
7527 * wpa_supplicant_match_iface - Match an interface description to a name
7528 * @global: Pointer to global data from wpa_supplicant_init()
7529 * @ifname: Name of the interface to match
7530 * Returns: Pointer to the created interface description or %NULL on failure
7531 */
7532struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7533 const char *ifname)
7534{
7535 int i;
7536 struct wpa_interface *iface, *miface;
7537
7538 for (i = 0; i < global->params.match_iface_count; i++) {
7539 miface = &global->params.match_ifaces[i];
7540 if (!miface->ifname ||
7541 fnmatch(miface->ifname, ifname, 0) == 0) {
7542 iface = os_zalloc(sizeof(*iface));
7543 if (!iface)
7544 return NULL;
7545 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007546 if (!miface->ifname)
7547 iface->matched = WPA_IFACE_MATCHED_NULL;
7548 else
7549 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007550 iface->ifname = ifname;
7551 return iface;
7552 }
7553 }
7554
7555 return NULL;
7556}
7557
7558
7559/**
7560 * wpa_supplicant_match_existing - Match existing interfaces
7561 * @global: Pointer to global data from wpa_supplicant_init()
7562 * Returns: 0 on success, -1 on failure
7563 */
7564static int wpa_supplicant_match_existing(struct wpa_global *global)
7565{
7566 struct if_nameindex *ifi, *ifp;
7567 struct wpa_supplicant *wpa_s;
7568 struct wpa_interface *iface;
7569
7570 ifp = if_nameindex();
7571 if (!ifp) {
7572 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7573 return -1;
7574 }
7575
7576 for (ifi = ifp; ifi->if_name; ifi++) {
7577 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7578 if (wpa_s)
7579 continue;
7580 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7581 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007582 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007583 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007584 }
7585 }
7586
7587 if_freenameindex(ifp);
7588 return 0;
7589}
7590
7591#endif /* CONFIG_MATCH_IFACE */
7592
7593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007594/**
7595 * wpa_supplicant_add_iface - Add a new network interface
7596 * @global: Pointer to global data from wpa_supplicant_init()
7597 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007598 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007599 * Returns: Pointer to the created interface or %NULL on failure
7600 *
7601 * This function is used to add new network interfaces for %wpa_supplicant.
7602 * This can be called before wpa_supplicant_run() to add interfaces before the
7603 * main event loop has been started. In addition, new interfaces can be added
7604 * dynamically while %wpa_supplicant is already running. This could happen,
7605 * e.g., when a hotplug network adapter is inserted.
7606 */
7607struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007608 struct wpa_interface *iface,
7609 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007610{
7611 struct wpa_supplicant *wpa_s;
7612 struct wpa_interface t_iface;
7613 struct wpa_ssid *ssid;
7614
7615 if (global == NULL || iface == NULL)
7616 return NULL;
7617
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007618 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007619 if (wpa_s == NULL)
7620 return NULL;
7621
7622 wpa_s->global = global;
7623
7624 t_iface = *iface;
7625 if (global->params.override_driver) {
7626 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7627 "('%s' -> '%s')",
7628 iface->driver, global->params.override_driver);
7629 t_iface.driver = global->params.override_driver;
7630 }
7631 if (global->params.override_ctrl_interface) {
7632 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7633 "ctrl_interface ('%s' -> '%s')",
7634 iface->ctrl_interface,
7635 global->params.override_ctrl_interface);
7636 t_iface.ctrl_interface =
7637 global->params.override_ctrl_interface;
7638 }
7639 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7640 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7641 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007642 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007643 return NULL;
7644 }
7645
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007646 /* Notify the control interfaces about new iface */
7647 if (wpas_notify_iface_added(wpa_s)) {
7648 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7649 return NULL;
7650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007651
Jimmy Chene2206be2022-07-10 10:25:21 +08007652 /* Notify the control interfaces about new networks */
7653 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7654 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007655 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007656 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7657 && os_strncmp((const char *) ssid->ssid,
7658 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7659 wpas_notify_persistent_group_added(wpa_s, ssid);
7660 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007661 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007662
7663 wpa_s->next = global->ifaces;
7664 global->ifaces = wpa_s;
7665
7666 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007667 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007668
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007669#ifdef CONFIG_P2P
7670 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007671 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007672 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007673 wpas_p2p_add_p2pdev_interface(
7674 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007675 wpa_printf(MSG_INFO,
7676 "P2P: Failed to enable P2P Device interface");
7677 /* Try to continue without. P2P will be disabled. */
7678 }
7679#endif /* CONFIG_P2P */
7680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007681 return wpa_s;
7682}
7683
7684
7685/**
7686 * wpa_supplicant_remove_iface - Remove a network interface
7687 * @global: Pointer to global data from wpa_supplicant_init()
7688 * @wpa_s: Pointer to the network interface to be removed
7689 * Returns: 0 if interface was removed, -1 if interface was not found
7690 *
7691 * This function can be used to dynamically remove network interfaces from
7692 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7693 * addition, this function is used to remove all remaining interfaces when
7694 * %wpa_supplicant is terminated.
7695 */
7696int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007697 struct wpa_supplicant *wpa_s,
7698 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007699{
7700 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007701#ifdef CONFIG_MESH
7702 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7703 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007704 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007705#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007706
7707 /* Remove interface from the global list of interfaces */
7708 prev = global->ifaces;
7709 if (prev == wpa_s) {
7710 global->ifaces = wpa_s->next;
7711 } else {
7712 while (prev && prev->next != wpa_s)
7713 prev = prev->next;
7714 if (prev == NULL)
7715 return -1;
7716 prev->next = wpa_s->next;
7717 }
7718
7719 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7720
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007721#ifdef CONFIG_MESH
7722 if (mesh_if_created) {
7723 ifname = os_strdup(wpa_s->ifname);
7724 if (ifname == NULL) {
7725 wpa_dbg(wpa_s, MSG_ERROR,
7726 "mesh: Failed to malloc ifname");
7727 return -1;
7728 }
7729 }
7730#endif /* CONFIG_MESH */
7731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007732 if (global->p2p_group_formation == wpa_s)
7733 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007734 if (global->p2p_invite_group == wpa_s)
7735 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007736 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007737
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007738#ifdef CONFIG_MESH
7739 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007740 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007741 os_free(ifname);
7742 }
7743#endif /* CONFIG_MESH */
7744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007745 return 0;
7746}
7747
7748
7749/**
7750 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7751 * @wpa_s: Pointer to the network interface
7752 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7753 */
7754const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7755{
7756 const char *eapol_method;
7757
7758 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7759 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7760 return "NO-EAP";
7761 }
7762
7763 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7764 if (eapol_method == NULL)
7765 return "UNKNOWN-EAP";
7766
7767 return eapol_method;
7768}
7769
7770
7771/**
7772 * wpa_supplicant_get_iface - Get a new network interface
7773 * @global: Pointer to global data from wpa_supplicant_init()
7774 * @ifname: Interface name
7775 * Returns: Pointer to the interface or %NULL if not found
7776 */
7777struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7778 const char *ifname)
7779{
7780 struct wpa_supplicant *wpa_s;
7781
7782 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7783 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7784 return wpa_s;
7785 }
7786 return NULL;
7787}
7788
7789
7790#ifndef CONFIG_NO_WPA_MSG
7791static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7792{
7793 struct wpa_supplicant *wpa_s = ctx;
7794 if (wpa_s == NULL)
7795 return NULL;
7796 return wpa_s->ifname;
7797}
7798#endif /* CONFIG_NO_WPA_MSG */
7799
7800
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007801#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7802#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7803#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7804
7805/* Periodic cleanup tasks */
7806static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7807{
7808 struct wpa_global *global = eloop_ctx;
7809 struct wpa_supplicant *wpa_s;
7810
7811 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7812 wpas_periodic, global, NULL);
7813
7814#ifdef CONFIG_P2P
7815 if (global->p2p)
7816 p2p_expire_peers(global->p2p);
7817#endif /* CONFIG_P2P */
7818
7819 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7820 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7821#ifdef CONFIG_AP
7822 ap_periodic(wpa_s);
7823#endif /* CONFIG_AP */
7824 }
7825}
7826
7827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007828/**
7829 * wpa_supplicant_init - Initialize %wpa_supplicant
7830 * @params: Parameters for %wpa_supplicant
7831 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7832 *
7833 * This function is used to initialize %wpa_supplicant. After successful
7834 * initialization, the returned data pointer can be used to add and remove
7835 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7836 */
7837struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7838{
7839 struct wpa_global *global;
7840 int ret, i;
7841
7842 if (params == NULL)
7843 return NULL;
7844
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007845#ifdef CONFIG_DRIVER_NDIS
7846 {
7847 void driver_ndis_init_ops(void);
7848 driver_ndis_init_ops();
7849 }
7850#endif /* CONFIG_DRIVER_NDIS */
7851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007852#ifndef CONFIG_NO_WPA_MSG
7853 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7854#endif /* CONFIG_NO_WPA_MSG */
7855
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007856 if (params->wpa_debug_file_path)
7857 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007858 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007859 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007860 if (params->wpa_debug_syslog)
7861 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007862 if (params->wpa_debug_tracing) {
7863 ret = wpa_debug_open_linux_tracing();
7864 if (ret) {
7865 wpa_printf(MSG_ERROR,
7866 "Failed to enable trace logging");
7867 return NULL;
7868 }
7869 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007870
7871 ret = eap_register_methods();
7872 if (ret) {
7873 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7874 if (ret == -2)
7875 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7876 "the same EAP type.");
7877 return NULL;
7878 }
7879
7880 global = os_zalloc(sizeof(*global));
7881 if (global == NULL)
7882 return NULL;
7883 dl_list_init(&global->p2p_srv_bonjour);
7884 dl_list_init(&global->p2p_srv_upnp);
7885 global->params.daemonize = params->daemonize;
7886 global->params.wait_for_monitor = params->wait_for_monitor;
7887 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007888
7889 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007890 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007891 if (!global->params.pid_file) {
7892 wpa_supplicant_deinit(global);
7893 return NULL;
7894 }
7895 }
7896
7897 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007898 global->params.ctrl_interface =
7899 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007900 if (!global->params.ctrl_interface) {
7901 wpa_supplicant_deinit(global);
7902 return NULL;
7903 }
7904 }
7905
7906 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007907 global->params.ctrl_interface_group =
7908 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007909 if (!global->params.ctrl_interface_group) {
7910 wpa_supplicant_deinit(global);
7911 return NULL;
7912 }
7913 }
7914
7915 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007916 global->params.override_driver =
7917 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007918 if (!global->params.override_driver) {
7919 wpa_supplicant_deinit(global);
7920 return NULL;
7921 }
7922 }
7923
7924 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007925 global->params.override_ctrl_interface =
7926 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007927 if (!global->params.override_ctrl_interface) {
7928 wpa_supplicant_deinit(global);
7929 return NULL;
7930 }
7931 }
7932
Dmitry Shmidte4663042016-04-04 10:07:49 -07007933#ifdef CONFIG_MATCH_IFACE
7934 global->params.match_iface_count = params->match_iface_count;
7935 if (params->match_iface_count) {
7936 global->params.match_ifaces =
7937 os_calloc(params->match_iface_count,
7938 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007939 if (!global->params.match_ifaces) {
7940 wpa_printf(MSG_ERROR,
7941 "Failed to allocate match interfaces");
7942 wpa_supplicant_deinit(global);
7943 return NULL;
7944 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007945 os_memcpy(global->params.match_ifaces,
7946 params->match_ifaces,
7947 params->match_iface_count *
7948 sizeof(struct wpa_interface));
7949 }
7950#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007951#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007952 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007953 global->params.conf_p2p_dev =
7954 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007955 if (!global->params.conf_p2p_dev) {
7956 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7957 wpa_supplicant_deinit(global);
7958 return NULL;
7959 }
7960 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007961#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007962 wpa_debug_level = global->params.wpa_debug_level =
7963 params->wpa_debug_level;
7964 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7965 params->wpa_debug_show_keys;
7966 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7967 params->wpa_debug_timestamp;
7968
Hai Shalomfdcde762020-04-02 11:19:20 -07007969 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007970
7971 if (eloop_init()) {
7972 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7973 wpa_supplicant_deinit(global);
7974 return NULL;
7975 }
7976
Jouni Malinen75ecf522011-06-27 15:19:46 -07007977 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007978
7979 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7980 if (global->ctrl_iface == NULL) {
7981 wpa_supplicant_deinit(global);
7982 return NULL;
7983 }
7984
7985 if (wpas_notify_supplicant_initialized(global)) {
7986 wpa_supplicant_deinit(global);
7987 return NULL;
7988 }
7989
7990 for (i = 0; wpa_drivers[i]; i++)
7991 global->drv_count++;
7992 if (global->drv_count == 0) {
7993 wpa_printf(MSG_ERROR, "No drivers enabled");
7994 wpa_supplicant_deinit(global);
7995 return NULL;
7996 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007997 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007998 if (global->drv_priv == NULL) {
7999 wpa_supplicant_deinit(global);
8000 return NULL;
8001 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008002
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008003#ifdef CONFIG_WIFI_DISPLAY
8004 if (wifi_display_init(global) < 0) {
8005 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8006 wpa_supplicant_deinit(global);
8007 return NULL;
8008 }
8009#endif /* CONFIG_WIFI_DISPLAY */
8010
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008011 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8012 wpas_periodic, global, NULL);
8013
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008014 return global;
8015}
8016
8017
8018/**
8019 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8020 * @global: Pointer to global data from wpa_supplicant_init()
8021 * Returns: 0 after successful event loop run, -1 on failure
8022 *
8023 * This function starts the main event loop and continues running as long as
8024 * there are any remaining events. In most cases, this function is running as
8025 * long as the %wpa_supplicant process in still in use.
8026 */
8027int wpa_supplicant_run(struct wpa_global *global)
8028{
8029 struct wpa_supplicant *wpa_s;
8030
8031 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008032 (wpa_supplicant_daemon(global->params.pid_file) ||
8033 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008034 return -1;
8035
Dmitry Shmidte4663042016-04-04 10:07:49 -07008036#ifdef CONFIG_MATCH_IFACE
8037 if (wpa_supplicant_match_existing(global))
8038 return -1;
8039#endif
8040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008041 if (global->params.wait_for_monitor) {
8042 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008043 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008044 wpa_supplicant_ctrl_iface_wait(
8045 wpa_s->ctrl_iface);
8046 }
8047
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008048#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008049 // If daemonize is enabled, initialize AIDL here.
8050 if (global->params.daemonize) {
8051 global->aidl = wpas_aidl_init(global);
8052 if (!global->aidl)
8053 return -1;
8054 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008055#endif /* CONFIG_AIDL */
8056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008057 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8058 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8059
8060 eloop_run();
8061
8062 return 0;
8063}
8064
8065
8066/**
8067 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8068 * @global: Pointer to global data from wpa_supplicant_init()
8069 *
8070 * This function is called to deinitialize %wpa_supplicant and to free all
8071 * allocated resources. Remaining network interfaces will also be removed.
8072 */
8073void wpa_supplicant_deinit(struct wpa_global *global)
8074{
8075 int i;
8076
8077 if (global == NULL)
8078 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008079
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008080 eloop_cancel_timeout(wpas_periodic, global, NULL);
8081
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008082#ifdef CONFIG_WIFI_DISPLAY
8083 wifi_display_deinit(global);
8084#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008085
8086 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008087 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008088
8089 if (global->ctrl_iface)
8090 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8091
8092 wpas_notify_supplicant_deinitialized(global);
8093
8094 eap_peer_unregister_methods();
8095#ifdef CONFIG_AP
8096 eap_server_unregister_methods();
8097#endif /* CONFIG_AP */
8098
8099 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8100 if (!global->drv_priv[i])
8101 continue;
8102 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8103 }
8104 os_free(global->drv_priv);
8105
8106 random_deinit();
8107
8108 eloop_destroy();
8109
8110 if (global->params.pid_file) {
8111 os_daemonize_terminate(global->params.pid_file);
8112 os_free(global->params.pid_file);
8113 }
8114 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008115 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008116 os_free(global->params.override_driver);
8117 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008118#ifdef CONFIG_MATCH_IFACE
8119 os_free(global->params.match_ifaces);
8120#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008121#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008122 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008123#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008124
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008125 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008126 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008127 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008128
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008129 os_free(global);
8130 wpa_debug_close_syslog();
8131 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008132 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008133}
8134
8135
8136void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8137{
8138 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8139 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8140 char country[3];
8141 country[0] = wpa_s->conf->country[0];
8142 country[1] = wpa_s->conf->country[1];
8143 country[2] = '\0';
8144 if (wpa_drv_set_country(wpa_s, country) < 0) {
8145 wpa_printf(MSG_ERROR, "Failed to set country code "
8146 "'%s'", country);
8147 }
8148 }
8149
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008150 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8151 wpas_init_ext_pw(wpa_s);
8152
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008153 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8154 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8155
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008156 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8157 struct wpa_driver_capa capa;
8158 int res = wpa_drv_get_capa(wpa_s, &capa);
8159
8160 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8161 wpa_printf(MSG_ERROR,
8162 "Failed to update wowlan_triggers to '%s'",
8163 wpa_s->conf->wowlan_triggers);
8164 }
8165
Hai Shalom81f62d82019-07-22 12:10:00 -07008166 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8167 wpa_supplicant_set_default_scan_ies(wpa_s);
8168
Hai Shalom899fcc72020-10-19 14:38:18 -07008169#ifdef CONFIG_BGSCAN
8170 /*
8171 * We default to global bgscan parameters only when per-network bgscan
8172 * parameters aren't set. Only bother resetting bgscan parameters if
8173 * this is the case.
8174 */
8175 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8176 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8177 wpa_s->wpa_state == WPA_COMPLETED)
8178 wpa_supplicant_reset_bgscan(wpa_s);
8179#endif /* CONFIG_BGSCAN */
8180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008181#ifdef CONFIG_WPS
8182 wpas_wps_update_config(wpa_s);
8183#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008184 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008185 wpa_s->conf->changed_parameters = 0;
8186}
8187
8188
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008189void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008190{
8191 int i;
8192
8193 for (i = 0; i < *num_freqs; i++) {
8194 if (freqs[i] == freq)
8195 return;
8196 }
8197
8198 freqs[*num_freqs] = freq;
8199 (*num_freqs)++;
8200}
8201
8202
8203static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8204{
8205 struct wpa_bss *bss, *cbss;
8206 const int max_freqs = 10;
8207 int *freqs;
8208 int num_freqs = 0;
8209
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008210 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008211 if (freqs == NULL)
8212 return NULL;
8213
8214 cbss = wpa_s->current_bss;
8215
8216 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8217 if (bss == cbss)
8218 continue;
8219 if (bss->ssid_len == cbss->ssid_len &&
8220 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008221 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008222 add_freq(freqs, &num_freqs, bss->freq);
8223 if (num_freqs == max_freqs)
8224 break;
8225 }
8226 }
8227
8228 if (num_freqs == 0) {
8229 os_free(freqs);
8230 freqs = NULL;
8231 }
8232
8233 return freqs;
8234}
8235
8236
8237void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8238{
8239 int timeout;
8240 int count;
8241 int *freqs = NULL;
8242
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008243 wpas_connect_work_done(wpa_s);
8244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008245 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008246 * Remove possible authentication timeout since the connection failed.
8247 */
8248 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8249
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008250 /*
Hai Shalom60840252021-02-19 19:02:11 -08008251 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008252 * generated based on local request to disconnect.
8253 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008254 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008255 wpa_s->own_disconnect_req = 0;
8256 wpa_dbg(wpa_s, MSG_DEBUG,
8257 "Ignore connection failure due to local request to disconnect");
8258 return;
8259 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008260 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008261 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8262 "indication since interface has been put into "
8263 "disconnected state");
8264 return;
8265 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008266 if (wpa_s->auto_reconnect_disabled) {
8267 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8268 "indication since auto connect is disabled");
8269 return;
8270 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008271
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008272 /*
Hai Shalom60840252021-02-19 19:02:11 -08008273 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008274 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008275 */
Hai Shalom60840252021-02-19 19:02:11 -08008276 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008277 if (count == 1 && wpa_s->current_bss) {
8278 /*
Hai Shalom60840252021-02-19 19:02:11 -08008279 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008280 * another BSS available for the same ESS, we should try that
8281 * next. Otherwise, we may as well try this one once more
8282 * before allowing other, likely worse, ESSes to be considered.
8283 */
8284 freqs = get_bss_freqs_in_ess(wpa_s);
8285 if (freqs) {
8286 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8287 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008288 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008289 /*
8290 * On the next scan, go through only the known channels
8291 * used in this ESS based on previous scans to speed up
8292 * common load balancing use case.
8293 */
8294 os_free(wpa_s->next_scan_freqs);
8295 wpa_s->next_scan_freqs = freqs;
8296 }
8297 }
8298
Hai Shalom899fcc72020-10-19 14:38:18 -07008299 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008300
Hai Shalom899fcc72020-10-19 14:38:18 -07008301 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008302 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8303 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008304 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008305 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008306 /*
8307 * Multiple consecutive connection failures mean that other APs are
8308 * either not available or have already been tried, so we can start
8309 * increasing the delay here to avoid constant scanning.
8310 */
8311 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008312 case 1:
8313 timeout = 100;
8314 break;
8315 case 2:
8316 timeout = 500;
8317 break;
8318 case 3:
8319 timeout = 1000;
8320 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008321 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008322 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008323 break;
8324 default:
8325 timeout = 10000;
8326 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008327 }
8328
Hai Shalom899fcc72020-10-19 14:38:18 -07008329 wpa_dbg(wpa_s, MSG_DEBUG,
8330 "Consecutive connection failures: %d --> request scan in %d ms",
8331 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008333 /*
8334 * TODO: if more than one possible AP is available in scan results,
8335 * could try the other ones before requesting a new scan.
8336 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008337
8338 /* speed up the connection attempt with normal scan */
8339 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008340 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8341 1000 * (timeout % 1000));
8342}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008343
8344
Hai Shalomce48b4a2018-09-05 11:41:35 -07008345#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008346
8347void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8348{
8349 struct wpa_ssid *ssid = wpa_s->current_ssid;
8350 const u8 *realm, *username, *rrk;
8351 size_t realm_len, username_len, rrk_len;
8352 u16 next_seq_num;
8353
8354 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8355 * Check for ERP keys existing to limit when this can be done since
8356 * the rejection response is not protected and such triggers should
8357 * really not allow internal state to be modified unless required to
8358 * avoid significant issues in functionality. In addition, drop
8359 * externally configure PMKSA entries even without ERP keys since it
8360 * is possible for an external component to add PMKSA entries for FILS
8361 * authentication without restoring previously generated ERP keys.
8362 *
8363 * In this case, this is needed to allow recovery from cases where the
8364 * AP or authentication server has dropped PMKSAs and ERP keys. */
8365 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8366 return;
8367
8368 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8369 &username, &username_len,
8370 &realm, &realm_len, &next_seq_num,
8371 &rrk, &rrk_len) != 0 ||
8372 !realm) {
8373 wpa_dbg(wpa_s, MSG_DEBUG,
8374 "FILS: Drop external PMKSA cache entry");
8375 wpa_sm_aborted_external_cached(wpa_s->wpa);
8376 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8377 return;
8378 }
8379
8380 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8381 wpa_sm_aborted_cached(wpa_s->wpa);
8382 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8383}
8384
8385
Hai Shalomce48b4a2018-09-05 11:41:35 -07008386void fils_connection_failure(struct wpa_supplicant *wpa_s)
8387{
8388 struct wpa_ssid *ssid = wpa_s->current_ssid;
8389 const u8 *realm, *username, *rrk;
8390 size_t realm_len, username_len, rrk_len;
8391 u16 next_seq_num;
8392
8393 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8394 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8395 &username, &username_len,
8396 &realm, &realm_len, &next_seq_num,
8397 &rrk, &rrk_len) != 0 ||
8398 !realm)
8399 return;
8400
8401 wpa_hexdump_ascii(MSG_DEBUG,
8402 "FILS: Store last connection failure realm",
8403 realm, realm_len);
8404 os_free(wpa_s->last_con_fail_realm);
8405 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8406 if (wpa_s->last_con_fail_realm) {
8407 wpa_s->last_con_fail_realm_len = realm_len;
8408 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8409 }
8410}
8411#endif /* CONFIG_FILS */
8412
8413
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008414int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8415{
8416 return wpa_s->conf->ap_scan == 2 ||
8417 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8418}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008419
Dmitry Shmidt04949592012-07-19 12:16:46 -07008420
Gabriel Biren57ededa2021-09-03 16:08:50 +00008421#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008422int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8423 struct wpa_ssid *ssid,
8424 const char *field,
8425 const char *value)
8426{
8427#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008428 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008429
8430 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8431 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8432 (const u8 *) value, os_strlen(value));
8433
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008434 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008435 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008436#else /* IEEE8021X_EAPOL */
8437 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8438 return -1;
8439#endif /* IEEE8021X_EAPOL */
8440}
8441
8442int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8443 struct wpa_ssid *ssid,
8444 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008445 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008446{
8447#ifdef IEEE8021X_EAPOL
8448 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008449 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008450
8451 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008452 case WPA_CTRL_REQ_EAP_IDENTITY:
8453 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008454 os_free(eap->imsi_identity);
8455 if (value == NULL)
8456 return -1;
8457 identity = os_strchr(value, ':');
8458 if (identity == NULL) {
8459 /* plain identity */
8460 eap->identity = (u8 *)os_strdup(value);
8461 eap->identity_len = os_strlen(value);
8462 } else {
8463 /* have both plain identity and encrypted identity */
8464 imsi_identity = value;
8465 *identity++ = '\0';
8466 /* plain identity */
8467 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8468 eap->imsi_identity_len = strlen(imsi_identity);
8469 /* encrypted identity */
8470 eap->identity = (u8 *)dup_binstr(identity,
8471 value_len - strlen(imsi_identity) - 1);
8472 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8473 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008474 eap->pending_req_identity = 0;
8475 if (ssid == wpa_s->current_ssid)
8476 wpa_s->reassociate = 1;
8477 break;
8478 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008479 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008480 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008481 if (!eap->password)
8482 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008483 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008484 eap->pending_req_password = 0;
8485 if (ssid == wpa_s->current_ssid)
8486 wpa_s->reassociate = 1;
8487 break;
8488 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008489 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008490 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008491 if (!eap->new_password)
8492 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008493 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008494 eap->pending_req_new_password = 0;
8495 if (ssid == wpa_s->current_ssid)
8496 wpa_s->reassociate = 1;
8497 break;
8498 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008499 str_clear_free(eap->cert.pin);
8500 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008501 if (!eap->cert.pin)
8502 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008503 eap->pending_req_pin = 0;
8504 if (ssid == wpa_s->current_ssid)
8505 wpa_s->reassociate = 1;
8506 break;
8507 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008508 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008509 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008510 if (!eap->otp)
8511 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008512 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008513 os_free(eap->pending_req_otp);
8514 eap->pending_req_otp = NULL;
8515 eap->pending_req_otp_len = 0;
8516 break;
8517 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008518 str_clear_free(eap->cert.private_key_passwd);
8519 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008520 if (!eap->cert.private_key_passwd)
8521 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008522 eap->pending_req_passphrase = 0;
8523 if (ssid == wpa_s->current_ssid)
8524 wpa_s->reassociate = 1;
8525 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008526 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008527 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008528 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008529 if (!eap->external_sim_resp)
8530 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008531 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008532 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008533 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8534 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8535 return -1;
8536 ssid->mem_only_psk = 1;
8537 if (ssid->passphrase)
8538 wpa_config_update_psk(ssid);
8539 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8540 wpa_supplicant_req_scan(wpa_s, 0, 0);
8541 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008542 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8543 if (eap->pending_ext_cert_check != PENDING_CHECK)
8544 return -1;
8545 if (os_strcmp(value, "good") == 0)
8546 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8547 else if (os_strcmp(value, "bad") == 0)
8548 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8549 else
8550 return -1;
8551 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008552 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008553 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008554 return -1;
8555 }
8556
8557 return 0;
8558#else /* IEEE8021X_EAPOL */
8559 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8560 return -1;
8561#endif /* IEEE8021X_EAPOL */
8562}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008563#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008564
8565
8566int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8567{
Hai Shalomfdcde762020-04-02 11:19:20 -07008568#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008569 int i;
8570 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008571#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008572
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008573 if (wpa_s->p2p_mgmt)
8574 return 1; /* no normal network profiles on p2p_mgmt interface */
8575
Dmitry Shmidt04949592012-07-19 12:16:46 -07008576 if (ssid == NULL)
8577 return 1;
8578
8579 if (ssid->disabled)
8580 return 1;
8581
Hai Shalomfdcde762020-04-02 11:19:20 -07008582#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008583 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008584 drv_enc = wpa_s->drv_enc;
8585 else
8586 drv_enc = (unsigned int) -1;
8587
8588 for (i = 0; i < NUM_WEP_KEYS; i++) {
8589 size_t len = ssid->wep_key_len[i];
8590 if (len == 0)
8591 continue;
8592 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8593 continue;
8594 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8595 continue;
8596 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8597 continue;
8598 return 1; /* invalid WEP key */
8599 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008600#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008601
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008602 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008603 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008604 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008605 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008606 return 1;
8607
Sunil Ravi89eba102022-09-13 21:04:37 -07008608#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008609#ifdef CRYPTO_RSA_OAEP_SHA256
8610 if (ssid->eap.imsi_privacy_cert) {
8611 struct crypto_rsa_key *key;
8612 bool failed = false;
8613
8614 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8615 if (!key)
8616 failed = true;
8617 crypto_rsa_key_free(key);
8618 if (failed) {
8619 wpa_printf(MSG_DEBUG,
8620 "Invalid imsi_privacy_cert (%s) - disable network",
8621 ssid->eap.imsi_privacy_cert);
8622 return 1;
8623 }
8624 }
8625#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008626#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008627
Dmitry Shmidt04949592012-07-19 12:16:46 -07008628 return 0;
8629}
8630
8631
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008632int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8633{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008634 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8635 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8636 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8637 /*
8638 * Driver does not support BIP -- ignore pmf=1 default
8639 * since the connection with PMF would fail and the
8640 * configuration does not require PMF to be enabled.
8641 */
8642 return NO_MGMT_FRAME_PROTECTION;
8643 }
8644
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008645 if (ssid &&
8646 (ssid->key_mgmt &
8647 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8648 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8649 /*
8650 * Do not use the default PMF value for non-RSN networks
8651 * since PMF is available only with RSN and pmf=2
8652 * configuration would otherwise prevent connections to
8653 * all open networks.
8654 */
8655 return NO_MGMT_FRAME_PROTECTION;
8656 }
8657
Sunil Ravi77d572f2023-01-17 23:58:31 +00008658#ifdef CONFIG_OCV
8659 /* Enable PMF if OCV is being enabled */
8660 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8661 ssid && ssid->ocv)
8662 return MGMT_FRAME_PROTECTION_OPTIONAL;
8663#endif /* CONFIG_OCV */
8664
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008665 return wpa_s->conf->pmf;
8666 }
8667
8668 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008669}
8670
8671
Sunil Ravi77d572f2023-01-17 23:58:31 +00008672#ifdef CONFIG_SAE
8673bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8674 struct wpa_ssid *ssid,
8675 const struct wpa_ie_data *ie)
8676{
8677 return wpa_s->conf->sae_check_mfp &&
8678 (!(ie->capabilities &
8679 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8680 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8681}
8682#endif /* CONFIG_SAE */
8683
8684
Hai Shalomc1a21442022-02-04 13:43:00 -08008685int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8686{
8687 if (wpa_s->current_ssid == NULL ||
8688 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8689 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8690 return 0;
8691 return wpa_sm_pmf_enabled(wpa_s->wpa);
8692}
8693
8694
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008695int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008696{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008697 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008698 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008699 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008700 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008701 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008702}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008703
8704
Sunil Ravi77d572f2023-01-17 23:58:31 +00008705void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8706 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008707{
8708 struct wpa_ssid *ssid = wpa_s->current_ssid;
8709 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008710 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008711
8712 if (ssid == NULL) {
8713 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8714 "SSID block");
8715 return;
8716 }
8717
8718 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8719 return;
8720
8721 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008722
8723#ifdef CONFIG_P2P
8724 if (ssid->p2p_group &&
8725 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8726 /*
8727 * Skip the wait time since there is a short timeout on the
8728 * connection to a P2P group.
8729 */
8730 return;
8731 }
8732#endif /* CONFIG_P2P */
8733
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008734 if (ssid->auth_failures > 50)
8735 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008736 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008737 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008738 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008739 dur = 90;
8740 else if (ssid->auth_failures > 3)
8741 dur = 60;
8742 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008743 dur = 30;
8744 else if (ssid->auth_failures > 1)
8745 dur = 20;
8746 else
8747 dur = 10;
8748
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008749 if (ssid->auth_failures > 1 &&
8750 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8751 dur += os_random() % (ssid->auth_failures * 10);
8752
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008753 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008754 if (now.sec + dur <= ssid->disabled_until.sec)
8755 return;
8756
8757 ssid->disabled_until.sec = now.sec + dur;
8758
8759 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008760 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008761 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008762 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008763
8764 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8765 int msg_len = snprintf(NULL, 0, format_str,
8766 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8767 ssid->auth_failures, dur, reason) + 1;
8768 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308769 if (!msg)
8770 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008771 snprintf(msg, msg_len, format_str,
8772 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8773 ssid->auth_failures, dur, reason);
8774 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8775 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008776
8777 if (bssid)
8778 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008779}
8780
8781
8782void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8783 struct wpa_ssid *ssid, int clear_failures)
8784{
8785 if (ssid == NULL)
8786 return;
8787
8788 if (ssid->disabled_until.sec) {
8789 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8790 "id=%d ssid=\"%s\"",
8791 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8792 }
8793 ssid->disabled_until.sec = 0;
8794 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008795 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008796 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008797 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8798 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8799 " ignored to allow a lower priority BSS, if any, to be tried next",
8800 MAC2STR(ssid->disabled_due_to));
8801 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8802 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8803 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008804}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008805
8806
8807int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8808{
8809 size_t i;
8810
8811 if (wpa_s->disallow_aps_bssid == NULL)
8812 return 0;
8813
8814 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8815 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8816 bssid, ETH_ALEN) == 0)
8817 return 1;
8818 }
8819
8820 return 0;
8821}
8822
8823
8824int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8825 size_t ssid_len)
8826{
8827 size_t i;
8828
8829 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8830 return 0;
8831
8832 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8833 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8834 if (ssid_len == s->ssid_len &&
8835 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8836 return 1;
8837 }
8838
8839 return 0;
8840}
8841
8842
8843/**
8844 * wpas_request_connection - Request a new connection
8845 * @wpa_s: Pointer to the network interface
8846 *
8847 * This function is used to request a new connection to be found. It will mark
8848 * the interface to allow reassociation and request a new scan to find a
8849 * suitable network to connect to.
8850 */
8851void wpas_request_connection(struct wpa_supplicant *wpa_s)
8852{
8853 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008854 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008855 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008856 wpa_s->disconnected = 0;
8857 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008858 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008859
8860 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8861 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008862 else
8863 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008864}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008865
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008866
Roshan Pius02242d72016-08-09 15:31:48 -07008867/**
8868 * wpas_request_disconnection - Request disconnection
8869 * @wpa_s: Pointer to the network interface
8870 *
8871 * This function is used to request disconnection from the currently connected
8872 * network. This will stop any ongoing scans and initiate deauthentication.
8873 */
8874void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8875{
8876#ifdef CONFIG_SME
8877 wpa_s->sme.prev_bssid_set = 0;
8878#endif /* CONFIG_SME */
8879 wpa_s->reassociate = 0;
8880 wpa_s->disconnected = 1;
8881 wpa_supplicant_cancel_sched_scan(wpa_s);
8882 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008883 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008884 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8885 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008886 radio_remove_works(wpa_s, "connect", 0);
8887 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008888 wpa_s->roam_in_progress = false;
8889#ifdef CONFIG_WNM
8890 wpa_s->bss_trans_mgmt_in_progress = false;
8891#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008892}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008893
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008894
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008895void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8896 struct wpa_used_freq_data *freqs_data,
8897 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008898{
8899 unsigned int i;
8900
8901 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8902 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008903 for (i = 0; i < len; i++) {
8904 struct wpa_used_freq_data *cur = &freqs_data[i];
8905 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8906 i, cur->freq, cur->flags);
8907 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008908}
8909
8910
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008911/*
8912 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008913 * are using the same radio as the current interface, and in addition, get
8914 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008915 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008916int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8917 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008918 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008919{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008920 struct wpa_supplicant *ifs;
8921 u8 bssid[ETH_ALEN];
8922 int freq;
8923 unsigned int idx = 0, i;
8924
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008925 wpa_dbg(wpa_s, MSG_DEBUG,
8926 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008927 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008928
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008929 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8930 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008931 if (idx == len)
8932 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008933
Sunil Ravi77d572f2023-01-17 23:58:31 +00008934 if (exclude_current && ifs == wpa_s)
8935 continue;
8936
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008937 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8938 continue;
8939
8940 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008941 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8942 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008943 freq = ifs->current_ssid->frequency;
8944 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8945 freq = ifs->assoc_freq;
8946 else
8947 continue;
8948
8949 /* Hold only distinct freqs */
8950 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008951 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008952 break;
8953
8954 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008955 freqs_data[idx++].freq = freq;
8956
8957 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008958 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008959 WPA_FREQ_USED_BY_P2P_CLIENT :
8960 WPA_FREQ_USED_BY_INFRA_STATION;
8961 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008962 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008963
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008964 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008965 return idx;
8966}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008967
8968
8969/*
8970 * Find the operating frequencies of any of the virtual interfaces that
8971 * are using the same radio as the current interface.
8972 */
8973int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008974 int *freq_array, unsigned int len,
8975 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008976{
8977 struct wpa_used_freq_data *freqs_data;
8978 int num, i;
8979
8980 os_memset(freq_array, 0, sizeof(int) * len);
8981
8982 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8983 if (!freqs_data)
8984 return -1;
8985
Sunil Ravi77d572f2023-01-17 23:58:31 +00008986 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8987 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008988 for (i = 0; i < num; i++)
8989 freq_array[i] = freqs_data[i].freq;
8990
8991 os_free(freqs_data);
8992
8993 return num;
8994}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008995
8996
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008997struct wpa_supplicant *
8998wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8999{
9000 switch (frame) {
9001#ifdef CONFIG_P2P
9002 case VENDOR_ELEM_PROBE_REQ_P2P:
9003 case VENDOR_ELEM_PROBE_RESP_P2P:
9004 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9005 case VENDOR_ELEM_BEACON_P2P_GO:
9006 case VENDOR_ELEM_P2P_PD_REQ:
9007 case VENDOR_ELEM_P2P_PD_RESP:
9008 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9009 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9010 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9011 case VENDOR_ELEM_P2P_INV_REQ:
9012 case VENDOR_ELEM_P2P_INV_RESP:
9013 case VENDOR_ELEM_P2P_ASSOC_REQ:
9014 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009015 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009016#endif /* CONFIG_P2P */
9017 default:
9018 return wpa_s;
9019 }
9020}
9021
9022
9023void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9024{
9025 unsigned int i;
9026 char buf[30];
9027
9028 wpa_printf(MSG_DEBUG, "Update vendor elements");
9029
9030 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9031 if (wpa_s->vendor_elem[i]) {
9032 int res;
9033
9034 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9035 if (!os_snprintf_error(sizeof(buf), res)) {
9036 wpa_hexdump_buf(MSG_DEBUG, buf,
9037 wpa_s->vendor_elem[i]);
9038 }
9039 }
9040 }
9041
9042#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009043 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009044 wpa_s->global->p2p &&
9045 !wpa_s->global->p2p_disabled)
9046 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9047#endif /* CONFIG_P2P */
9048}
9049
9050
9051int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9052 const u8 *elem, size_t len)
9053{
9054 u8 *ie, *end;
9055
9056 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9057 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9058
9059 for (; ie + 1 < end; ie += 2 + ie[1]) {
9060 if (ie + len > end)
9061 break;
9062 if (os_memcmp(ie, elem, len) != 0)
9063 continue;
9064
9065 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9066 wpabuf_free(wpa_s->vendor_elem[frame]);
9067 wpa_s->vendor_elem[frame] = NULL;
9068 } else {
9069 os_memmove(ie, ie + len, end - (ie + len));
9070 wpa_s->vendor_elem[frame]->used -= len;
9071 }
9072 wpas_vendor_elem_update(wpa_s);
9073 return 0;
9074 }
9075
9076 return -1;
9077}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009078
9079
9080struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009081 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009082 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009083{
9084 u16 i;
9085
Hai Shalomc1a21442022-02-04 13:43:00 -08009086 if (!modes)
9087 return NULL;
9088
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009089 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009090 if (modes[i].mode != mode ||
9091 !modes[i].num_channels || !modes[i].channels)
9092 continue;
9093 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
9094 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009095 return &modes[i];
9096 }
9097
9098 return NULL;
9099}
9100
9101
Hai Shalomc1a21442022-02-04 13:43:00 -08009102struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9103 u16 num_modes, int freq)
9104{
9105 int i, j;
9106
9107 for (i = 0; i < num_modes; i++) {
9108 for (j = 0; j < modes[i].num_channels; j++) {
9109 if (freq == modes[i].channels[j].freq)
9110 return &modes[i];
9111 }
9112 }
9113
9114 return NULL;
9115}
9116
9117
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009118static struct
9119wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9120 const u8 *bssid)
9121{
9122 struct wpa_bss_tmp_disallowed *bss;
9123
9124 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9125 struct wpa_bss_tmp_disallowed, list) {
9126 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
9127 return bss;
9128 }
9129
9130 return NULL;
9131}
9132
9133
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009134static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9135{
9136 struct wpa_bss_tmp_disallowed *tmp;
9137 unsigned int num_bssid = 0;
9138 u8 *bssids;
9139 int ret;
9140
9141 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9142 if (!bssids)
9143 return -1;
9144 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9145 struct wpa_bss_tmp_disallowed, list) {
9146 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9147 ETH_ALEN);
9148 num_bssid++;
9149 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009150 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009151 os_free(bssids);
9152 return ret;
9153}
9154
9155
9156static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9157{
9158 struct wpa_supplicant *wpa_s = eloop_ctx;
9159 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9160
9161 /* Make sure the bss is not already freed */
9162 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9163 struct wpa_bss_tmp_disallowed, list) {
9164 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009165 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009166 wpa_set_driver_tmp_disallow_list(wpa_s);
9167 break;
9168 }
9169 }
9170}
9171
9172
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009173void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009174 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009175{
9176 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009177
9178 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9179 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009180 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009181 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009182 }
9183
9184 bss = os_malloc(sizeof(*bss));
9185 if (!bss) {
9186 wpa_printf(MSG_DEBUG,
9187 "Failed to allocate memory for temp disallow BSS");
9188 return;
9189 }
9190
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009191 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9192 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009193 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009194
9195finish:
9196 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009197 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9198 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009199}
9200
9201
Hai Shalom74f70d42019-02-11 14:42:39 -08009202int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9203 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009204{
Hai Shalom74f70d42019-02-11 14:42:39 -08009205 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009206
9207 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9208 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009209 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9210 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009211 break;
9212 }
9213 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009214 if (!disallowed)
9215 return 0;
9216
9217 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009218 bss->level > disallowed->rssi_threshold) {
9219 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9220 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009221 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009222 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009223
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009224 return 1;
9225}
Hai Shalom81f62d82019-07-22 12:10:00 -07009226
9227
9228int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9229 unsigned int type, const u8 *addr,
9230 const u8 *mask)
9231{
9232 if ((addr && !mask) || (!addr && mask)) {
9233 wpa_printf(MSG_INFO,
9234 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9235 return -1;
9236 }
9237
9238 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9239 wpa_printf(MSG_INFO,
9240 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9241 return -1;
9242 }
9243
9244 if (type & MAC_ADDR_RAND_SCAN) {
9245 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9246 addr, mask))
9247 return -1;
9248 }
9249
9250 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9251 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9252 addr, mask))
9253 return -1;
9254
9255 if (wpa_s->sched_scanning && !wpa_s->pno)
9256 wpas_scan_restart_sched_scan(wpa_s);
9257 }
9258
9259 if (type & MAC_ADDR_RAND_PNO) {
9260 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9261 addr, mask))
9262 return -1;
9263
9264 if (wpa_s->pno) {
9265 wpas_stop_pno(wpa_s);
9266 wpas_start_pno(wpa_s);
9267 }
9268 }
9269
9270 return 0;
9271}
9272
9273
9274int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9275 unsigned int type)
9276{
9277 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9278 if (wpa_s->pno) {
9279 if (type & MAC_ADDR_RAND_PNO) {
9280 wpas_stop_pno(wpa_s);
9281 wpas_start_pno(wpa_s);
9282 }
9283 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9284 wpas_scan_restart_sched_scan(wpa_s);
9285 }
9286
9287 return 0;
9288}
Hai Shalomfdcde762020-04-02 11:19:20 -07009289
9290
9291int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9292 struct wpa_signal_info *si)
9293{
9294 int res;
9295
9296 if (!wpa_s->driver->signal_poll)
9297 return -1;
9298
9299 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9300
9301#ifdef CONFIG_TESTING_OPTIONS
9302 if (res == 0) {
9303 struct driver_signal_override *dso;
9304
9305 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9306 struct driver_signal_override, list) {
9307 if (os_memcmp(wpa_s->bssid, dso->bssid,
9308 ETH_ALEN) != 0)
9309 continue;
9310 wpa_printf(MSG_DEBUG,
9311 "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 +00009312 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009313 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009314 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009315 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009316 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009317 dso->si_avg_beacon_signal,
9318 si->current_noise,
9319 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009320 si->data.signal = dso->si_current_signal;
9321 si->data.avg_signal = dso->si_avg_signal;
9322 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009323 si->current_noise = dso->si_current_noise;
9324 break;
9325 }
9326 }
9327#endif /* CONFIG_TESTING_OPTIONS */
9328
9329 return res;
9330}
9331
9332
9333struct wpa_scan_results *
9334wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9335{
9336 struct wpa_scan_results *scan_res;
9337#ifdef CONFIG_TESTING_OPTIONS
9338 size_t idx;
9339#endif /* CONFIG_TESTING_OPTIONS */
9340
9341 if (!wpa_s->driver->get_scan_results2)
9342 return NULL;
9343
9344 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9345
9346#ifdef CONFIG_TESTING_OPTIONS
9347 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9348 struct driver_signal_override *dso;
9349 struct wpa_scan_res *res = scan_res->res[idx];
9350
9351 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9352 struct driver_signal_override, list) {
9353 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9354 continue;
9355 wpa_printf(MSG_DEBUG,
9356 "Override driver scan signal level %d->%d for "
9357 MACSTR,
9358 res->level, dso->scan_level,
9359 MAC2STR(res->bssid));
9360 res->flags |= WPA_SCAN_QUAL_INVALID;
9361 if (dso->scan_level < 0)
9362 res->flags |= WPA_SCAN_LEVEL_DBM;
9363 else
9364 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9365 res->level = dso->scan_level;
9366 break;
9367 }
9368 }
9369#endif /* CONFIG_TESTING_OPTIONS */
9370
9371 return scan_res;
9372}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009373
9374
9375static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9376{
9377 int i;
9378
9379 if (!wpa_s->valid_links)
9380 return false;
9381
9382 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9383 if (!(wpa_s->valid_links & BIT(i)))
9384 continue;
9385
9386 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9387 return true;
9388 }
9389
9390 return false;
9391}
9392
9393
9394int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9395 unsigned int wait, const u8 *dst, const u8 *src,
9396 const u8 *bssid, const u8 *data, size_t data_len,
9397 int no_cck)
9398{
9399 if (!wpa_s->driver->send_action)
9400 return -1;
9401
9402 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9403 if (wpas_ap_link_address(wpa_s, dst))
9404 dst = wpa_s->ap_mld_addr;
9405
9406 if (wpas_ap_link_address(wpa_s, bssid))
9407 bssid = wpa_s->ap_mld_addr;
9408 }
9409
9410 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9411 bssid, data, data_len, no_cck);
9412}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009413
9414
9415bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9416{
9417 struct hostapd_channel_data *chnl;
9418 int i, j;
9419
9420 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9421 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9422 chnl = wpa_s->hw.modes[i].channels;
9423 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9424 if (only_enabled &&
9425 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9426 continue;
9427 if (is_6ghz_freq(chnl[j].freq))
9428 return true;
9429 }
9430 }
9431 }
9432
9433 return false;
9434}