blob: d4401ff5b5ad615002716c6ea04feaa4c80712d7 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Sunil Ravieb83e2a2024-06-28 17:34:56 +00003 * 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);
Sunil Ravi88611412024-06-28 17:34:56 +0000678#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,
Sunil Ravi88611412024-06-28 17:34:56 +0000884 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700885 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)
Sunil Ravieb83e2a2024-06-28 17:34:56 +00002012 wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002013 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 */
Sunil Ravieb83e2a2024-06-28 17:34:56 +00002130 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. */
Sunil Ravieb83e2a2024-06-28 17:34:56 +00002318 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2319 ETH_ALEN) == 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +00002320 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);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302560 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2561 ssid->mode == WPAS_MODE_P2P_GO) {
2562 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002563 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302564 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002565 return;
2566 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 wpa_s->current_bss = bss;
2568#else /* CONFIG_AP */
2569 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2570 "the build");
2571#endif /* CONFIG_AP */
2572 return;
2573 }
2574
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002575 if (ssid->mode == WPAS_MODE_MESH) {
2576#ifdef CONFIG_MESH
2577 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2578 wpa_msg(wpa_s, MSG_INFO,
2579 "Driver does not support mesh mode");
2580 return;
2581 }
2582 if (bss)
2583 ssid->frequency = bss->freq;
2584 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002585 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002586 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2587 return;
2588 }
2589 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002590#else /* CONFIG_MESH */
2591 wpa_msg(wpa_s, MSG_ERROR,
2592 "mesh mode support not included in the build");
2593#endif /* CONFIG_MESH */
2594 return;
2595 }
2596
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002597 /*
2598 * Set WPA state machine configuration to match the selected network now
2599 * so that the information is available before wpas_start_assoc_cb()
2600 * gets called. This is needed at least for RSN pre-authentication where
2601 * candidate APs are added to a list based on scan result processing
2602 * before completion of the first association.
2603 */
2604 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2605
2606#ifdef CONFIG_DPP
2607 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2608 return;
2609#endif /* CONFIG_DPP */
2610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611#ifdef CONFIG_TDLS
2612 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002613 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614#endif /* CONFIG_TDLS */
2615
Hai Shalomc3565922019-10-28 11:58:20 -07002616#ifdef CONFIG_MBO
2617 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2618#endif /* CONFIG_MBO */
2619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002621 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 sme_authenticate(wpa_s, bss, ssid);
2623 return;
2624 }
2625
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002626 if (wpa_s->connect_work) {
2627 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2628 return;
2629 }
2630
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002631 if (radio_work_pending(wpa_s, "connect")) {
2632 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2633 return;
2634 }
2635
Dmitry Shmidt29333592017-01-09 12:27:11 -08002636#ifdef CONFIG_SME
2637 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2638 /* Clear possibly set auth_alg, if any, from last attempt. */
2639 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2640 }
2641#endif /* CONFIG_SME */
2642
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002643 wpas_abort_ongoing_scan(wpa_s);
2644
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002645 cwork = os_zalloc(sizeof(*cwork));
2646 if (cwork == NULL)
2647 return;
2648
2649 cwork->bss = bss;
2650 cwork->ssid = ssid;
2651
2652 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2653 wpas_start_assoc_cb, cwork) < 0) {
2654 os_free(cwork);
2655 }
2656}
2657
2658
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002659static int bss_is_ibss(struct wpa_bss *bss)
2660{
2661 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2662 IEEE80211_CAP_IBSS;
2663}
2664
2665
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002666static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2667 const struct wpa_ssid *ssid)
2668{
2669 enum hostapd_hw_mode hw_mode;
2670 struct hostapd_hw_modes *mode = NULL;
2671 u8 channel;
2672 int i;
2673
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002674 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2675 if (hw_mode == NUM_HOSTAPD_MODES)
2676 return 0;
2677 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2678 if (wpa_s->hw.modes[i].mode == hw_mode) {
2679 mode = &wpa_s->hw.modes[i];
2680 break;
2681 }
2682 }
2683
2684 if (!mode)
2685 return 0;
2686
2687 return mode->vht_capab != 0;
2688}
2689
2690
Hai Shalomc1a21442022-02-04 13:43:00 -08002691static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2692{
2693 int i;
2694
2695 for (i = channel; i < channel + 16; i += 4) {
2696 struct hostapd_channel_data *chan;
2697
2698 chan = hw_get_channel_chan(mode, i, NULL);
2699 if (!chan ||
2700 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2701 return false;
2702 }
2703
2704 return true;
2705}
2706
2707
Sunil Ravi036cec52023-03-29 11:35:17 -07002708static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2709 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002710{
Sunil Ravi036cec52023-03-29 11:35:17 -07002711 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002712
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002713 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2714 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2715
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002716 if (!bss_is_ibss(bss))
2717 continue;
2718
2719 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002720 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2721 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002722 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002723 return NULL;
2724}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002725
Sunil Ravi036cec52023-03-29 11:35:17 -07002726
2727static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2728 const struct wpa_ssid *ssid,
2729 struct hostapd_hw_modes *mode)
2730{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002731 /* For IBSS check HT_IBSS flag */
2732 if (ssid->mode == WPAS_MODE_IBSS &&
2733 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002734 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002735
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002736 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2737 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2738 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2739 wpa_printf(MSG_DEBUG,
2740 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002741 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002742 }
2743
Sunil Ravi036cec52023-03-29 11:35:17 -07002744 if (!ht_supported(mode))
2745 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002746
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002747#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002748 if (ssid->disable_ht)
2749 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002750#endif /* CONFIG_HT_OVERRIDES */
2751
Sunil Ravi036cec52023-03-29 11:35:17 -07002752 return true;
2753}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002754
Sunil Ravi036cec52023-03-29 11:35:17 -07002755
2756static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2757 const struct wpa_ssid *ssid,
2758 struct hostapd_hw_modes *mode)
2759{
2760 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2761 return false;
2762
2763 if (!drv_supports_vht(wpa_s, ssid))
2764 return false;
2765
2766 /* For IBSS check VHT_IBSS flag */
2767 if (ssid->mode == WPAS_MODE_IBSS &&
2768 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2769 return false;
2770
2771 if (!vht_supported(mode))
2772 return false;
2773
2774#ifdef CONFIG_VHT_OVERRIDES
2775 if (ssid->disable_vht)
2776 return false;
2777#endif /* CONFIG_VHT_OVERRIDES */
2778
2779 return true;
2780}
2781
2782
2783static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2784 const struct wpa_ssid *ssid,
2785 const struct hostapd_hw_modes *mode,
2786 int ieee80211_mode)
2787{
Hai Shalomfdcde762020-04-02 11:19:20 -07002788#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002789 if (ssid->disable_he)
2790 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002791#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002792
Sunil Ravi036cec52023-03-29 11:35:17 -07002793 switch (mode->mode) {
2794 case HOSTAPD_MODE_IEEE80211G:
2795 case HOSTAPD_MODE_IEEE80211B:
2796 case HOSTAPD_MODE_IEEE80211A:
2797 return mode->he_capab[ieee80211_mode].he_supported;
2798 default:
2799 return false;
2800 }
2801}
2802
2803
2804static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2805 const struct wpa_ssid *ssid,
2806 const struct hostapd_hw_modes *mode,
2807 int ieee80211_mode)
2808{
2809 if (ssid->disable_eht)
2810 return false;
2811
2812 switch(mode->mode) {
2813 case HOSTAPD_MODE_IEEE80211G:
2814 case HOSTAPD_MODE_IEEE80211B:
2815 case HOSTAPD_MODE_IEEE80211A:
2816 return mode->eht_capab[ieee80211_mode].eht_supported;
2817 default:
2818 return false;
2819 }
2820}
2821
2822
2823static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2824 const struct wpa_ssid *ssid,
2825 struct hostapd_hw_modes *mode,
2826 struct hostapd_freq_params *freq,
2827 int obss_scan) {
2828 int chan_idx;
2829 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2830 int i, res;
2831 unsigned int j;
2832 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002833 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2834 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002835 };
2836 int ht40 = -1;
2837
2838 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002839 return;
2840
2841 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2842 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002843 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002844 break;
2845 pri_chan = NULL;
2846 }
2847 if (!pri_chan)
2848 return;
2849
2850 /* Check primary channel flags */
2851 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2852 return;
2853
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002854#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002855 if (ssid->disable_ht40)
2856 return;
2857#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002858
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002859 /* Check/setup HT40+/HT40- */
2860 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002861 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002862 ht40 = 1;
2863 break;
2864 }
2865 }
2866
2867 /* Find secondary channel */
2868 for (i = 0; i < mode->num_channels; i++) {
2869 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002870 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002871 break;
2872 sec_chan = NULL;
2873 }
2874 if (!sec_chan)
2875 return;
2876
2877 /* Check secondary channel flags */
2878 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2879 return;
2880
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002881 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002882 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2883 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002884 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002885 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2886 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002887 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002888 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002889
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002890 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002891 struct wpa_scan_results *scan_res;
2892
Sunil Ravi88611412024-06-28 17:34:56 +00002893 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002894 if (scan_res == NULL) {
2895 /* Back to HT20 */
2896 freq->sec_channel_offset = 0;
2897 return;
2898 }
2899
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002900 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002901 switch (res) {
2902 case 0:
2903 /* Back to HT20 */
2904 freq->sec_channel_offset = 0;
2905 break;
2906 case 1:
2907 /* Configuration allowed */
2908 break;
2909 case 2:
2910 /* Switch pri/sec channels */
2911 freq->freq = hw_get_freq(mode, sec_chan->chan);
2912 freq->sec_channel_offset = -freq->sec_channel_offset;
2913 freq->channel = sec_chan->chan;
2914 break;
2915 default:
2916 freq->sec_channel_offset = 0;
2917 break;
2918 }
2919
2920 wpa_scan_results_free(scan_res);
2921 }
2922
2923 wpa_printf(MSG_DEBUG,
2924 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2925 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002926}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002927
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002928
Sunil Ravi036cec52023-03-29 11:35:17 -07002929static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2930 const struct wpa_ssid *ssid,
2931 struct hostapd_hw_modes *mode,
2932 struct hostapd_freq_params *freq,
2933 int ieee80211_mode, bool is_6ghz) {
2934 static const int bw80[] = {
2935 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2936 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2937 6515, 6595, 6675, 6755, 6835, 6915, 6995
2938 };
2939 static const int bw160[] = {
2940 5955, 6115, 6275, 6435, 6595, 6755, 6915
2941 };
2942 struct hostapd_freq_params vht_freq;
2943 int i;
2944 unsigned int j, k;
2945 int chwidth, seg0, seg1;
2946 u32 vht_caps = 0;
2947 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002948
Sunil Ravi036cec52023-03-29 11:35:17 -07002949 if (!freq->vht_enabled && !freq->he_enabled)
2950 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002951
Hai Shalomc1a21442022-02-04 13:43:00 -08002952 vht_freq = *freq;
2953
Sunil Ravi036cec52023-03-29 11:35:17 -07002954 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2955 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2956 seg1 = 0;
2957 if (freq->sec_channel_offset == 0) {
2958 seg0 = 0;
2959 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2960 if (freq->ht_enabled && !is_6ghz)
2961 goto skip_80mhz;
2962 }
2963 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2964 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002965
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002966 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002967 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2968 if (freq->freq >= bw80[j] &&
2969 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002970 break;
2971 }
2972
Hai Shalomc1a21442022-02-04 13:43:00 -08002973 if (j == ARRAY_SIZE(bw80) ||
2974 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002975 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002976
Sunil Ravi036cec52023-03-29 11:35:17 -07002977 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002978 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002979 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002980
Sunil8cd6f4d2022-06-28 18:40:46 +00002981 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002982 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002983 seg1 = 0;
2984
Sunil Ravi036cec52023-03-29 11:35:17 -07002985 /* In 160 MHz, the initial four 20 MHz channels were validated
2986 * above. If 160 MHz is supported, check the remaining four 20 MHz
2987 * channels for the total of 160 MHz bandwidth for 6 GHz.
2988 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002989 if ((mode->he_capab[ieee80211_mode].phy_cap[
2990 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002991 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2992 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002993 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2994 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002995 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002996 seg0 = channel + 14;
2997 break;
2998 }
2999 }
3000 }
3001
Sunil8cd6f4d2022-06-28 18:40:46 +00003002 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003003 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003004 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003005 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003006 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003007 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003008
3009 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3010 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003011 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003012
3013 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003014 struct hostapd_channel_data *chan;
3015
3016 chan = hw_get_channel_chan(mode, i, NULL);
3017 if (!chan)
3018 continue;
3019
3020 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3021 HOSTAPD_CHAN_NO_IR |
3022 HOSTAPD_CHAN_RADAR))
3023 continue;
3024
3025 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003026 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003027 if (!is_6ghz)
3028 vht_caps |=
3029 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3030 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003031 }
3032
Sunil8cd6f4d2022-06-28 18:40:46 +00003033 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003034 break;
3035 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003036 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003037 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003038 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003039 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3040 seg0 = 50;
3041 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003042 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003043 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3044 seg0 = 114;
3045 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003046 }
3047
Sunil Ravi036cec52023-03-29 11:35:17 -07003048skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003049 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003050 freq->channel, ssid->enable_edmg,
3051 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003052 freq->vht_enabled, freq->he_enabled,
3053 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003054 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003055 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003056 &mode->he_capab[ieee80211_mode],
Sunil Ravi88611412024-06-28 17:34:56 +00003057 &mode->eht_capab[ieee80211_mode]) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003058 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003059
3060 *freq = vht_freq;
3061
3062 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3063 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003064 return true;
3065}
3066
3067
3068void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3069 const struct wpa_ssid *ssid,
3070 struct hostapd_freq_params *freq)
3071{
3072 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3073 enum hostapd_hw_mode hw_mode;
3074 struct hostapd_hw_modes *mode = NULL;
3075 int i, obss_scan = 1;
3076 u8 channel;
Sunil Ravieb83e2a2024-06-28 17:34:56 +00003077 bool is_6ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003078
3079 freq->freq = ssid->frequency;
3080
3081 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3082 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3083
3084 if (bss) {
3085 wpa_printf(MSG_DEBUG,
3086 "IBSS already found in scan results, adjust control freq: %d",
3087 bss->freq);
3088 freq->freq = bss->freq;
3089 obss_scan = 0;
3090 }
3091 }
3092
3093 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3094 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3095 if (wpa_s->hw.modes[i].mode == hw_mode &&
3096 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3097 NULL) != NULL) {
3098 mode = &wpa_s->hw.modes[i];
3099 break;
3100 }
3101 }
3102
3103 if (!mode)
3104 return;
3105
3106 is_6ghz = is_6ghz_freq(freq->freq);
3107
3108 freq->ht_enabled = 0;
3109 freq->vht_enabled = 0;
3110 freq->he_enabled = 0;
3111 freq->eht_enabled = 0;
3112
3113 if (!is_6ghz)
3114 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3115 if (freq->ht_enabled)
3116 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravieb83e2a2024-06-28 17:34:56 +00003117 if (freq->vht_enabled || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003118 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3119 ieee80211_mode);
3120 freq->channel = channel;
3121 /* Setup higher BW only for 5 GHz */
3122 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3123 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3124 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3125 ieee80211_mode, is_6ghz))
3126 freq->he_enabled = freq->vht_enabled = false;
3127 }
3128
3129 if (freq->he_enabled)
3130 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3131 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003132}
3133
3134
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003135#ifdef CONFIG_FILS
3136static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3137 size_t ie_buf_len)
3138{
3139 struct fils_hlp_req *req;
3140 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3141 const u8 *pos;
3142 u8 *buf = ie_buf;
3143
3144 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3145 list) {
3146 rem_len = ie_buf_len - ie_len;
3147 pos = wpabuf_head(req->pkt);
3148 hdr_len = 1 + 2 * ETH_ALEN + 6;
3149 hlp_len = wpabuf_len(req->pkt);
3150
3151 if (rem_len < 2 + hdr_len + hlp_len) {
3152 wpa_printf(MSG_ERROR,
3153 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3154 (unsigned long) rem_len,
3155 (unsigned long) (2 + hdr_len + hlp_len));
3156 break;
3157 }
3158
3159 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3160 /* Element ID */
3161 *buf++ = WLAN_EID_EXTENSION;
3162 /* Length */
3163 *buf++ = len;
3164 /* Element ID Extension */
3165 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3166 /* Destination MAC address */
3167 os_memcpy(buf, req->dst, ETH_ALEN);
3168 buf += ETH_ALEN;
3169 /* Source MAC address */
3170 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3171 buf += ETH_ALEN;
3172 /* LLC/SNAP Header */
3173 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3174 buf += 6;
3175 /* HLP Packet */
3176 os_memcpy(buf, pos, len - hdr_len);
3177 buf += len - hdr_len;
3178 pos += len - hdr_len;
3179
3180 hlp_len -= len - hdr_len;
3181 ie_len += 2 + len;
3182 rem_len -= 2 + len;
3183
3184 while (hlp_len) {
3185 len = (hlp_len > 255) ? 255 : hlp_len;
3186 if (rem_len < 2 + len)
3187 break;
3188 *buf++ = WLAN_EID_FRAGMENT;
3189 *buf++ = len;
3190 os_memcpy(buf, pos, len);
3191 buf += len;
3192 pos += len;
3193
3194 hlp_len -= len;
3195 ie_len += 2 + len;
3196 rem_len -= 2 + len;
3197 }
3198 }
3199
3200 return ie_len;
3201}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003202
3203
3204int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3205{
3206 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3207 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3208 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3209 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3210}
3211
3212
3213int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3214{
3215#ifdef CONFIG_FILS_SK_PFS
3216 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3217 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3218#else /* CONFIG_FILS_SK_PFS */
3219 return 0;
3220#endif /* CONFIG_FILS_SK_PFS */
3221}
3222
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003223#endif /* CONFIG_FILS */
3224
3225
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003226bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3227{
3228 const u8 *wfa_capa;
3229
3230 if (!bss)
3231 return false;
3232
3233 /* Get WFA capability from Beacon or Probe Response frame elements */
3234 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3235 if (!wfa_capa)
3236 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3237 bss, WFA_CAPA_IE_VENDOR_TYPE);
3238
3239 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3240 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3241 /* AP does not enable QM non EHT traffic description policy */
3242 return false;
3243 }
3244
3245 return true;
3246}
3247
3248
Hai Shalomc1a21442022-02-04 13:43:00 -08003249static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3250 struct wpa_bss *bss,
3251 u8 *wpa_ie, size_t wpa_ie_len,
3252 size_t max_wpa_ie_len)
3253{
3254 struct wpabuf *wfa_ie = NULL;
3255 u8 wfa_capa[1];
3256 size_t wfa_ie_len, buf_len;
3257
3258 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3259 if (wpa_s->enable_dscp_policy_capa)
3260 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3261
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003262 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3263 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3264
Hai Shalomc1a21442022-02-04 13:43:00 -08003265 if (!wfa_capa[0])
3266 return wpa_ie_len;
3267
3268 /* Wi-Fi Alliance element */
3269 buf_len = 1 + /* Element ID */
3270 1 + /* Length */
3271 3 + /* OUI */
3272 1 + /* OUI Type */
3273 1 + /* Capabilities Length */
3274 sizeof(wfa_capa); /* Capabilities */
3275 wfa_ie = wpabuf_alloc(buf_len);
3276 if (!wfa_ie)
3277 return wpa_ie_len;
3278
3279 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3280 wpabuf_put_u8(wfa_ie, buf_len - 2);
3281 wpabuf_put_be24(wfa_ie, OUI_WFA);
3282 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3283 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3284 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3285
3286 wfa_ie_len = wpabuf_len(wfa_ie);
3287 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3288 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3289 wfa_ie);
3290 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3291 wfa_ie_len);
3292 wpa_ie_len += wfa_ie_len;
3293 }
3294
3295 wpabuf_free(wfa_ie);
3296 return wpa_ie_len;
3297}
3298
3299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003300static u8 * wpas_populate_assoc_ies(
3301 struct wpa_supplicant *wpa_s,
3302 struct wpa_bss *bss, struct wpa_ssid *ssid,
3303 struct wpa_driver_associate_params *params,
3304 enum wpa_drv_update_connect_params_mask *mask)
3305{
3306 u8 *wpa_ie;
3307 size_t max_wpa_ie_len = 500;
3308 size_t wpa_ie_len;
3309 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003310#ifdef CONFIG_MBO
3311 const u8 *mbo_ie;
3312#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303313#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3314 int pmksa_cached = 0;
3315#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003316#ifdef CONFIG_FILS
3317 const u8 *realm, *username, *rrk;
3318 size_t realm_len, username_len, rrk_len;
3319 u16 next_seq_num;
3320 struct fils_hlp_req *req;
3321
3322 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3323 list) {
3324 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3325 2 + 2 * wpabuf_len(req->pkt) / 255;
3326 }
3327#endif /* CONFIG_FILS */
3328
3329 wpa_ie = os_malloc(max_wpa_ie_len);
3330 if (!wpa_ie) {
3331 wpa_printf(MSG_ERROR,
3332 "Failed to allocate connect IE buffer for %lu bytes",
3333 (unsigned long) max_wpa_ie_len);
3334 return NULL;
3335 }
3336
3337 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3338 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3339 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3340 int try_opportunistic;
3341 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003342 const u8 *addr = bss->bssid;
3343
Sunil Ravi036cec52023-03-29 11:35:17 -07003344 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3345 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3346 !is_zero_ether_addr(bss->mld_addr))
3347 addr = bss->mld_addr;
3348
3349 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3350 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003351 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003352
3353 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3354 wpa_s->conf->okc :
3355 ssid->proactive_key_caching) &&
3356 (ssid->proto & WPA_PROTO_RSN);
3357#ifdef CONFIG_FILS
3358 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3359 cache_id = wpa_bss_get_fils_cache_id(bss);
3360#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003361 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003362 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003363 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003364 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303365#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3366 pmksa_cached = 1;
3367#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003368 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003369 wpa_ie_len = max_wpa_ie_len;
3370 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003371 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003372 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3373 "key management and encryption suites");
3374 os_free(wpa_ie);
3375 return NULL;
3376 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003377#ifdef CONFIG_HS20
3378 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3379 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3380 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3381 wpa_ie_len = max_wpa_ie_len;
3382 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003383 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003384 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3385 "key management and encryption suites");
3386 os_free(wpa_ie);
3387 return NULL;
3388 }
3389#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3391 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3392 /*
3393 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3394 * use non-WPA since the scan results did not indicate that the
3395 * AP is using WPA or WPA2.
3396 */
3397 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3398 wpa_ie_len = 0;
3399 wpa_s->wpa_proto = 0;
3400 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3401 wpa_ie_len = max_wpa_ie_len;
3402 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003403 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003404 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3405 "key management and encryption suites (no "
3406 "scan results)");
3407 os_free(wpa_ie);
3408 return NULL;
3409 }
3410#ifdef CONFIG_WPS
3411 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3412 struct wpabuf *wps_ie;
3413 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3414 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3415 wpa_ie_len = wpabuf_len(wps_ie);
3416 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3417 } else
3418 wpa_ie_len = 0;
3419 wpabuf_free(wps_ie);
3420 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3421 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3422 params->wps = WPS_MODE_PRIVACY;
3423 else
3424 params->wps = WPS_MODE_OPEN;
3425 wpa_s->wpa_proto = 0;
3426#endif /* CONFIG_WPS */
3427 } else {
3428 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3429 wpa_ie_len = 0;
3430 wpa_s->wpa_proto = 0;
3431 }
3432
3433#ifdef IEEE8021X_EAPOL
3434 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3435 if (ssid->leap) {
3436 if (ssid->non_leap == 0)
3437 algs = WPA_AUTH_ALG_LEAP;
3438 else
3439 algs |= WPA_AUTH_ALG_LEAP;
3440 }
3441 }
3442
3443#ifdef CONFIG_FILS
3444 /* Clear FILS association */
3445 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3446
3447 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3448 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3449 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3450 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003451 &next_seq_num, &rrk, &rrk_len) == 0 &&
3452 (!wpa_s->last_con_fail_realm ||
3453 wpa_s->last_con_fail_realm_len != realm_len ||
3454 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003455 algs = WPA_AUTH_ALG_FILS;
3456 params->fils_erp_username = username;
3457 params->fils_erp_username_len = username_len;
3458 params->fils_erp_realm = realm;
3459 params->fils_erp_realm_len = realm_len;
3460 params->fils_erp_next_seq_num = next_seq_num;
3461 params->fils_erp_rrk = rrk;
3462 params->fils_erp_rrk_len = rrk_len;
3463
3464 if (mask)
3465 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303466 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3467 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3468 pmksa_cached) {
3469 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003470 }
3471#endif /* CONFIG_FILS */
3472#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003473#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003474 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003475 algs = WPA_AUTH_ALG_SAE;
3476#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003477
3478 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3479 if (ssid->auth_alg) {
3480 algs = ssid->auth_alg;
3481 wpa_dbg(wpa_s, MSG_DEBUG,
3482 "Overriding auth_alg selection: 0x%x", algs);
3483 }
3484
Hai Shalom5f92bc92019-04-18 11:54:11 -07003485#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303486 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003487 wpa_dbg(wpa_s, MSG_DEBUG,
3488 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3489 algs = WPA_AUTH_ALG_OPEN;
3490 }
3491#endif /* CONFIG_SAE */
3492
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003493#ifdef CONFIG_P2P
3494 if (wpa_s->global->p2p) {
3495 u8 *pos;
3496 size_t len;
3497 int res;
3498 pos = wpa_ie + wpa_ie_len;
3499 len = max_wpa_ie_len - wpa_ie_len;
3500 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3501 ssid->p2p_group);
3502 if (res >= 0)
3503 wpa_ie_len += res;
3504 }
3505
3506 wpa_s->cross_connect_disallowed = 0;
3507 if (bss) {
3508 struct wpabuf *p2p;
3509 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3510 if (p2p) {
3511 wpa_s->cross_connect_disallowed =
3512 p2p_get_cross_connect_disallowed(p2p);
3513 wpabuf_free(p2p);
3514 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3515 "connection",
3516 wpa_s->cross_connect_disallowed ?
3517 "disallows" : "allows");
3518 }
3519 }
3520
3521 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3522#endif /* CONFIG_P2P */
3523
3524 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003525 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003526 wpa_ie + wpa_ie_len,
3527 max_wpa_ie_len -
3528 wpa_ie_len);
3529 }
3530
3531 /*
3532 * Workaround: Add Extended Capabilities element only if the AP
3533 * included this element in Beacon/Probe Response frames. Some older
3534 * APs seem to have interoperability issues if this element is
3535 * included, so while the standard may require us to include the
3536 * element in all cases, it is justifiable to skip it to avoid
3537 * interoperability issues.
3538 */
3539 if (ssid->p2p_group)
3540 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3541 else
3542 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3543
3544 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3545 u8 ext_capab[18];
3546 int ext_capab_len;
3547 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003548 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003549 if (ext_capab_len > 0 &&
3550 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3551 u8 *pos = wpa_ie;
3552 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3553 pos += 2 + pos[1];
3554 os_memmove(pos + ext_capab_len, pos,
3555 wpa_ie_len - (pos - wpa_ie));
3556 wpa_ie_len += ext_capab_len;
3557 os_memcpy(pos, ext_capab, ext_capab_len);
3558 }
3559 }
3560
3561#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003562 if (is_hs20_network(wpa_s, ssid, bss)
3563#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3564 && is_hs20_config(wpa_s)
3565#endif /* ANDROID */
3566 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003567 struct wpabuf *hs20;
3568
Roshan Pius3a1667e2018-07-03 15:17:14 -07003569 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003570 if (hs20) {
3571 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3572 size_t len;
3573
Hai Shalom74f70d42019-02-11 14:42:39 -08003574 wpas_hs20_add_indication(hs20, pps_mo_id,
3575 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003576 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003577 len = max_wpa_ie_len - wpa_ie_len;
3578 if (wpabuf_len(hs20) <= len) {
3579 os_memcpy(wpa_ie + wpa_ie_len,
3580 wpabuf_head(hs20), wpabuf_len(hs20));
3581 wpa_ie_len += wpabuf_len(hs20);
3582 }
3583 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003584 }
3585 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003586 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003587#endif /* CONFIG_HS20 */
3588
3589 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3590 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3591 size_t len;
3592
3593 len = max_wpa_ie_len - wpa_ie_len;
3594 if (wpabuf_len(buf) <= len) {
3595 os_memcpy(wpa_ie + wpa_ie_len,
3596 wpabuf_head(buf), wpabuf_len(buf));
3597 wpa_ie_len += wpabuf_len(buf);
3598 }
3599 }
3600
3601#ifdef CONFIG_FST
3602 if (wpa_s->fst_ies) {
3603 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3604
3605 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3606 os_memcpy(wpa_ie + wpa_ie_len,
3607 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3608 wpa_ie_len += fst_ies_len;
3609 }
3610 }
3611#endif /* CONFIG_FST */
3612
3613#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003614 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003615 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003616 int len;
3617
3618 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003619 max_wpa_ie_len - wpa_ie_len,
3620 !!mbo_attr_from_mbo_ie(mbo_ie,
3621 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003622 if (len >= 0)
3623 wpa_ie_len += len;
3624 }
3625#endif /* CONFIG_MBO */
3626
3627#ifdef CONFIG_FILS
3628 if (algs == WPA_AUTH_ALG_FILS) {
3629 size_t len;
3630
3631 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3632 max_wpa_ie_len - wpa_ie_len);
3633 wpa_ie_len += len;
3634 }
3635#endif /* CONFIG_FILS */
3636
3637#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003638#ifdef CONFIG_TESTING_OPTIONS
3639 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3640 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3641 } else
3642#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003643 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003644 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3645 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003646 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003647 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003648
Roshan Pius3a1667e2018-07-03 15:17:14 -07003649 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003650 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003651 } else if (wpa_s->assoc_status_code ==
3652 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003653 if (wpa_s->last_owe_group == 19)
3654 group = 20;
3655 else if (wpa_s->last_owe_group == 20)
3656 group = 21;
3657 else
3658 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003659 } else {
3660 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003661 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003662
Roshan Pius3a1667e2018-07-03 15:17:14 -07003663 wpa_s->last_owe_group = group;
3664 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003665 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3666 if (owe_ie &&
3667 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3668 os_memcpy(wpa_ie + wpa_ie_len,
3669 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3670 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003671 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003672 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003673 }
3674#endif /* CONFIG_OWE */
3675
Hai Shalom021b0b52019-04-10 11:17:58 -07003676#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003677 if (DPP_VERSION > 1 &&
3678 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003679 ssid->dpp_netaccesskey &&
3680 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003681 struct rsn_pmksa_cache_entry *pmksa;
3682
3683 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3684 if (!pmksa || !pmksa->dpp_pfs)
3685 goto pfs_fail;
3686
Hai Shalom021b0b52019-04-10 11:17:58 -07003687 dpp_pfs_free(wpa_s->dpp_pfs);
3688 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3689 ssid->dpp_netaccesskey_len);
3690 if (!wpa_s->dpp_pfs) {
3691 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3692 /* Try to continue without PFS */
3693 goto pfs_fail;
3694 }
3695 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3696 max_wpa_ie_len - wpa_ie_len) {
3697 os_memcpy(wpa_ie + wpa_ie_len,
3698 wpabuf_head(wpa_s->dpp_pfs->ie),
3699 wpabuf_len(wpa_s->dpp_pfs->ie));
3700 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3701 }
3702 }
3703pfs_fail:
3704#endif /* CONFIG_DPP2 */
3705
Roshan Pius3a1667e2018-07-03 15:17:14 -07003706#ifdef CONFIG_IEEE80211R
3707 /*
3708 * Add MDIE under these conditions: the network profile allows FT,
3709 * the AP supports FT, and the mobility domain ID matches.
3710 */
3711 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3712 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3713
3714 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3715 size_t len = 0;
3716 const u8 *md = mdie + 2;
3717 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3718
3719 if (os_memcmp(md, wpa_md,
3720 MOBILITY_DOMAIN_ID_LEN) == 0) {
3721 /* Add mobility domain IE */
3722 len = wpa_ft_add_mdie(
3723 wpa_s->wpa, wpa_ie + wpa_ie_len,
3724 max_wpa_ie_len - wpa_ie_len, mdie);
3725 wpa_ie_len += len;
3726 }
3727#ifdef CONFIG_SME
3728 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003729 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003730 wpa_dbg(wpa_s, MSG_DEBUG,
3731 "SME: Trying to use FT over-the-air");
3732 algs |= WPA_AUTH_ALG_FT;
3733 }
3734#endif /* CONFIG_SME */
3735 }
3736 }
3737#endif /* CONFIG_IEEE80211R */
3738
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003739#ifdef CONFIG_TESTING_OPTIONS
3740 if (wpa_s->rsnxe_override_assoc &&
3741 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3742 max_wpa_ie_len - wpa_ie_len) {
3743 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3744 os_memcpy(wpa_ie + wpa_ie_len,
3745 wpabuf_head(wpa_s->rsnxe_override_assoc),
3746 wpabuf_len(wpa_s->rsnxe_override_assoc));
3747 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3748 } else
3749#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003750 if (wpa_s->rsnxe_len > 0 &&
3751 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3752 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3753 wpa_ie_len += wpa_s->rsnxe_len;
3754 }
3755
Hai Shalomc1a21442022-02-04 13:43:00 -08003756#ifdef CONFIG_TESTING_OPTIONS
3757 if (wpa_s->disable_mscs_support)
3758 goto mscs_end;
3759#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003760 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3761 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003762 struct wpabuf *mscs_ie;
3763 size_t mscs_ie_len, buf_len;
3764
Hai Shalom899fcc72020-10-19 14:38:18 -07003765 buf_len = 3 + /* MSCS descriptor IE header */
3766 1 + /* Request type */
3767 2 + /* User priority control */
3768 4 + /* Stream timeout */
3769 3 + /* TCLAS Mask IE header */
3770 wpa_s->robust_av.frame_classifier_len;
3771 mscs_ie = wpabuf_alloc(buf_len);
3772 if (!mscs_ie) {
3773 wpa_printf(MSG_INFO,
3774 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003775 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003776 }
3777
3778 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3779 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3780 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3781 mscs_ie_len = wpabuf_len(mscs_ie);
3782 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3783 mscs_ie_len);
3784 wpa_ie_len += mscs_ie_len;
3785 }
3786
3787 wpabuf_free(mscs_ie);
3788 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003789mscs_end:
3790
3791 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3792 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003793
Hai Shalom74f70d42019-02-11 14:42:39 -08003794 if (ssid->multi_ap_backhaul_sta) {
3795 size_t multi_ap_ie_len;
3796
3797 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3798 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi88611412024-06-28 17:34:56 +00003799 MULTI_AP_BACKHAUL_STA);
Hai Shalom74f70d42019-02-11 14:42:39 -08003800 if (multi_ap_ie_len == 0) {
3801 wpa_printf(MSG_ERROR,
3802 "Multi-AP: Failed to build Multi-AP IE");
3803 os_free(wpa_ie);
3804 return NULL;
3805 }
3806 wpa_ie_len += multi_ap_ie_len;
3807 }
3808
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003809 params->wpa_ie = wpa_ie;
3810 params->wpa_ie_len = wpa_ie_len;
3811 params->auth_alg = algs;
3812 if (mask)
3813 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3814
3815 return wpa_ie;
3816}
3817
3818
Hai Shalomc3565922019-10-28 11:58:20 -07003819#ifdef CONFIG_OWE
3820static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3821{
3822 struct wpa_driver_associate_params params;
3823 u8 *wpa_ie;
3824
3825 os_memset(&params, 0, sizeof(params));
3826 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3827 wpa_s->current_ssid, &params, NULL);
3828 if (!wpa_ie)
3829 return;
3830
3831 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3832 os_free(wpa_ie);
3833}
3834#endif /* CONFIG_OWE */
3835
3836
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003837#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3838static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3839{
3840 struct wpa_driver_associate_params params;
3841 enum wpa_drv_update_connect_params_mask mask = 0;
3842 u8 *wpa_ie;
3843
3844 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3845 return; /* nothing to do */
3846
3847 os_memset(&params, 0, sizeof(params));
3848 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3849 wpa_s->current_ssid, &params, &mask);
3850 if (!wpa_ie)
3851 return;
3852
Hai Shalomc1a21442022-02-04 13:43:00 -08003853 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3854 wpa_s->auth_alg = params.auth_alg;
3855 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003856 }
3857
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003858 os_free(wpa_ie);
3859}
3860#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3861
3862
Hai Shalomc3565922019-10-28 11:58:20 -07003863static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3864{
3865 if (!edmg_ie || edmg_ie[1] < 6)
3866 return 0;
3867 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3868}
3869
3870
3871static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3872{
3873 if (!edmg_ie || edmg_ie[1] < 6)
3874 return 0;
3875 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3876}
3877
3878
3879/* Returns the intersection of two EDMG configurations.
3880 * Note: The current implementation is limited to CB2 only (CB1 included),
3881 * i.e., the implementation supports up to 2 contiguous channels.
3882 * For supporting non-contiguous (aggregated) channels and for supporting
3883 * CB3 and above, this function will need to be extended.
3884 */
3885static struct ieee80211_edmg_config
3886get_edmg_intersection(struct ieee80211_edmg_config a,
3887 struct ieee80211_edmg_config b,
3888 u8 primary_channel)
3889{
3890 struct ieee80211_edmg_config result;
3891 int i, contiguous = 0;
3892 int max_contiguous = 0;
3893
3894 result.channels = b.channels & a.channels;
3895 if (!result.channels) {
3896 wpa_printf(MSG_DEBUG,
3897 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3898 a.channels, b.channels);
3899 goto fail;
3900 }
3901
3902 if (!(result.channels & BIT(primary_channel - 1))) {
3903 wpa_printf(MSG_DEBUG,
3904 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3905 primary_channel, result.channels);
3906 goto fail;
3907 }
3908
3909 /* Find max contiguous channels */
3910 for (i = 0; i < 6; i++) {
3911 if (result.channels & BIT(i))
3912 contiguous++;
3913 else
3914 contiguous = 0;
3915
3916 if (contiguous > max_contiguous)
3917 max_contiguous = contiguous;
3918 }
3919
3920 /* Assuming AP and STA supports ONLY contiguous channels,
3921 * bw configuration can have value between 4-7.
3922 */
3923 if ((b.bw_config < a.bw_config))
3924 result.bw_config = b.bw_config;
3925 else
3926 result.bw_config = a.bw_config;
3927
3928 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3929 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3930 wpa_printf(MSG_DEBUG,
3931 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3932 max_contiguous);
3933 goto fail;
3934 }
3935
3936 return result;
3937
3938fail:
3939 result.channels = 0;
3940 result.bw_config = 0;
3941 return result;
3942}
3943
3944
3945static struct ieee80211_edmg_config
3946get_supported_edmg(struct wpa_supplicant *wpa_s,
3947 struct hostapd_freq_params *freq,
3948 struct ieee80211_edmg_config request_edmg)
3949{
3950 enum hostapd_hw_mode hw_mode;
3951 struct hostapd_hw_modes *mode = NULL;
3952 u8 primary_channel;
3953
3954 if (!wpa_s->hw.modes)
3955 goto fail;
3956
3957 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3958 if (hw_mode == NUM_HOSTAPD_MODES)
3959 goto fail;
3960
Hai Shalom60840252021-02-19 19:02:11 -08003961 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003962 if (!mode)
3963 goto fail;
3964
3965 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3966
3967fail:
3968 request_edmg.channels = 0;
3969 request_edmg.bw_config = 0;
3970 return request_edmg;
3971}
3972
3973
Hai Shalom021b0b52019-04-10 11:17:58 -07003974#ifdef CONFIG_MBO
3975void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3976{
3977 struct wpa_driver_associate_params params;
3978 u8 *wpa_ie;
3979
3980 /*
3981 * Update MBO connect params only in case of change of MBO attributes
3982 * when connected, if the AP support MBO.
3983 */
3984
3985 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3986 !wpa_s->current_bss ||
3987 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3988 return;
3989
3990 os_memset(&params, 0, sizeof(params));
3991 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3992 wpa_s->current_ssid, &params, NULL);
3993 if (!wpa_ie)
3994 return;
3995
3996 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3997 os_free(wpa_ie);
3998}
3999#endif /* CONFIG_MBO */
4000
4001
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004002static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4003{
4004 struct wpa_connect_work *cwork = work->ctx;
4005 struct wpa_bss *bss = cwork->bss;
4006 struct wpa_ssid *ssid = cwork->ssid;
4007 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004008 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004009 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004010 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004011 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004012 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004013 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004014#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004015 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004016#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004017 int assoc_failed = 0;
4018 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004019 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004020#ifdef CONFIG_HT_OVERRIDES
4021 struct ieee80211_ht_capabilities htcaps;
4022 struct ieee80211_ht_capabilities htcaps_mask;
4023#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004024#ifdef CONFIG_VHT_OVERRIDES
4025 struct ieee80211_vht_capabilities vhtcaps;
4026 struct ieee80211_vht_capabilities vhtcaps_mask;
4027#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004028
Hai Shalomc1a21442022-02-04 13:43:00 -08004029 wpa_s->roam_in_progress = false;
4030#ifdef CONFIG_WNM
4031 wpa_s->bss_trans_mgmt_in_progress = false;
4032#endif /* CONFIG_WNM */
4033
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004034 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004035 if (work->started) {
4036 wpa_s->connect_work = NULL;
4037
4038 /* cancel possible auth. timeout */
4039 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4040 NULL);
4041 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004042 wpas_connect_work_free(cwork);
4043 return;
4044 }
4045
4046 wpa_s->connect_work = work;
4047
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004048 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4049 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004050 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4051 wpas_connect_work_done(wpa_s);
4052 return;
4053 }
4054
Sunil Ravi640215c2023-06-28 23:08:09 +00004055 /*
4056 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4057 * (for MLO connection) as the previous BSSID for reassociation requests
4058 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4059 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4060 * will be zero.
4061 */
4062 os_memcpy(prev_bssid,
4063 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4064 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 os_memset(&params, 0, sizeof(params));
4066 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004067 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004068
4069 /* Starting new association, so clear the possibly used WPA IE from the
4070 * previous association. */
4071 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4072 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4073 wpa_s->rsnxe_len = 0;
4074 wpa_s->mscs_setup_done = false;
4075
4076 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4077 if (!wpa_ie) {
4078 wpas_connect_work_done(wpa_s);
4079 return;
4080 }
4081
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004082 if (bss &&
4083 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084#ifdef CONFIG_IEEE80211R
4085 const u8 *ie, *md = NULL;
4086#endif /* CONFIG_IEEE80211R */
4087 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4088 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4089 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4090 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4091 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4092 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4093 if (bssid_changed)
4094 wpas_notify_bssid_changed(wpa_s);
4095#ifdef CONFIG_IEEE80211R
4096 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4097 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4098 md = ie + 2;
4099 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4100 if (md) {
4101 /* Prepare for the next transition */
4102 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4103 }
4104#endif /* CONFIG_IEEE80211R */
4105#ifdef CONFIG_WPS
4106 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4107 wpa_s->conf->ap_scan == 2 &&
4108 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4109 /* Use ap_scan==1 style network selection to find the network
4110 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004111 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004112 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113 wpa_s->reassociate = 1;
4114 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004115 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 return;
4117#endif /* CONFIG_WPS */
4118 } else {
4119 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4120 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004121 if (bss)
4122 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4123 else
4124 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004125 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004126 if (!wpa_s->pno)
4127 wpa_supplicant_cancel_sched_scan(wpa_s);
4128
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 wpa_supplicant_cancel_scan(wpa_s);
4130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4132 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004133 cipher_pairwise = wpa_s->pairwise_cipher;
4134 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004135 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004136 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4137 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4138 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4139 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004140#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 if (wpa_set_wep_keys(wpa_s, ssid)) {
4142 use_crypt = 1;
4143 wep_keys_set = 1;
4144 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004145#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 }
4147 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4148 use_crypt = 0;
4149
4150#ifdef IEEE8021X_EAPOL
4151 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4152 if ((ssid->eapol_flags &
4153 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4154 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4155 !wep_keys_set) {
4156 use_crypt = 0;
4157 } else {
4158 /* Assume that dynamic WEP-104 keys will be used and
4159 * set cipher suites in order for drivers to expect
4160 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004161 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004162 }
4163 }
4164#endif /* IEEE8021X_EAPOL */
4165
4166 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4167 /* Set the key before (and later after) association */
4168 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4169 }
4170
Sunil8cd6f4d2022-06-28 18:40:46 +00004171 /* Set current_ssid before changing state to ASSOCIATING, so that the
4172 * selected SSID is available to wpas_notify_state_changed(). */
4173 old_ssid = wpa_s->current_ssid;
4174 wpa_s->current_ssid = ssid;
4175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4177 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004178 params.ssid = bss->ssid;
4179 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004180 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4181 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004182 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4183 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004184 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004185 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004186 ssid->bssid_set,
4187 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004188 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004189 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004190 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004191 params.bssid_hint = bss->bssid;
4192 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004193 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004195 if (ssid->bssid_hint_set)
4196 params.bssid_hint = ssid->bssid_hint;
4197
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198 params.ssid = ssid->ssid;
4199 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004200 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004202
4203 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4204 wpa_s->conf->ap_scan == 2) {
4205 params.bssid = ssid->bssid;
4206 params.fixed_bssid = 1;
4207 }
4208
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004209 /* Initial frequency for IBSS/mesh */
4210 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004211 ssid->frequency > 0 && params.freq.freq == 0)
4212 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004213
4214 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004215 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004216 if (ssid->beacon_int)
4217 params.beacon_int = ssid->beacon_int;
4218 else
4219 params.beacon_int = wpa_s->conf->beacon_int;
4220 }
4221
Hai Shalomc3565922019-10-28 11:58:20 -07004222 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004223 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4224 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004225 else
4226 edmg_ie_oper = NULL;
4227
4228 if (edmg_ie_oper) {
4229 params.freq.edmg.channels =
4230 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4231 params.freq.edmg.bw_config =
4232 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4233 wpa_printf(MSG_DEBUG,
4234 "AP supports EDMG channels 0x%x, bw_config %d",
4235 params.freq.edmg.channels,
4236 params.freq.edmg.bw_config);
4237
4238 /* User may ask for specific EDMG channel for EDMG connection
4239 * (must be supported by AP)
4240 */
4241 if (ssid->edmg_channel) {
4242 struct ieee80211_edmg_config configured_edmg;
4243 enum hostapd_hw_mode hw_mode;
4244 u8 primary_channel;
4245
4246 hw_mode = ieee80211_freq_to_chan(bss->freq,
4247 &primary_channel);
4248 if (hw_mode == NUM_HOSTAPD_MODES)
4249 goto edmg_fail;
4250
4251 hostapd_encode_edmg_chan(ssid->enable_edmg,
4252 ssid->edmg_channel,
4253 primary_channel,
4254 &configured_edmg);
4255
4256 if (ieee802_edmg_is_allowed(params.freq.edmg,
4257 configured_edmg)) {
4258 params.freq.edmg = configured_edmg;
4259 wpa_printf(MSG_DEBUG,
4260 "Use EDMG channel %d for connection",
4261 ssid->edmg_channel);
4262 } else {
4263 edmg_fail:
4264 params.freq.edmg.channels = 0;
4265 params.freq.edmg.bw_config = 0;
4266 wpa_printf(MSG_WARNING,
4267 "EDMG channel %d not supported by AP, fallback to DMG",
4268 ssid->edmg_channel);
4269 }
4270 }
4271
4272 if (params.freq.edmg.channels) {
4273 wpa_printf(MSG_DEBUG,
4274 "EDMG before: channels 0x%x, bw_config %d",
4275 params.freq.edmg.channels,
4276 params.freq.edmg.bw_config);
4277 params.freq.edmg = get_supported_edmg(wpa_s,
4278 &params.freq,
4279 params.freq.edmg);
4280 wpa_printf(MSG_DEBUG,
4281 "EDMG after: channels 0x%x, bw_config %d",
4282 params.freq.edmg.channels,
4283 params.freq.edmg.bw_config);
4284 }
4285 }
4286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287 params.pairwise_suite = cipher_pairwise;
4288 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004289 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004290 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004291 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004292 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004293 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004294 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004295 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004296#ifdef CONFIG_WEP
4297 {
4298 int i;
4299
4300 for (i = 0; i < NUM_WEP_KEYS; i++) {
4301 if (ssid->wep_key_len[i])
4302 params.wep_key[i] = ssid->wep_key[i];
4303 params.wep_key_len[i] = ssid->wep_key_len[i];
4304 }
4305 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004306 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004307#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004308
Hai Shalom74f70d42019-02-11 14:42:39 -08004309 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004310#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4311 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004312 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4313 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004314#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4315 defined(CONFIG_DRIVER_NL80211_SYNA)
4316 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4317 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4318 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4319 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304320#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004321 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4322 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4323 (params.allowed_key_mgmts &
4324 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004325#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4326 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004327 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004328 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4329 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004330 }
4331
Hai Shalom74f70d42019-02-11 14:42:39 -08004332 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4333 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4334 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4335 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004336 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4337 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004338 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004339
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004340 if (wpa_s->conf->key_mgmt_offload) {
4341 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4342 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004343 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004344 params.key_mgmt_suite ==
4345 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4346 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004347 params.req_key_mgmt_offload =
4348 ssid->proactive_key_caching < 0 ?
4349 wpa_s->conf->okc : ssid->proactive_key_caching;
4350 else
4351 params.req_key_mgmt_offload = 1;
4352
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004353#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4354 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004355 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004356 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4357 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004358#else
4359 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4360 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004361#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4362 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004363 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4364 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004365 }
4366
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004367 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4368 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4369 params.auth_alg = WPA_AUTH_ALG_SAE;
4370 if (ssid->sae_password) {
4371 params.sae_password = ssid->sae_password;
4372 params.sae_password_id = ssid->sae_password_id;
4373 } else if (ssid->passphrase) {
4374 params.passphrase = ssid->passphrase;
4375 }
4376 }
4377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378 params.drop_unencrypted = use_crypt;
4379
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004380 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004381 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004382 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4383 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004384 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4385 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386 ie.capabilities &
4387 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4388 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4389 "MFP: require MFP");
4390 params.mgmt_frame_protection =
4391 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004392#ifdef CONFIG_OWE
4393 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4394 !ssid->owe_only) {
4395 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4396#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 }
4398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004399
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004400 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004402 if (wpa_s->p2pdev->set_sta_uapsd)
4403 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 else
4405 params.uapsd = -1;
4406
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004407#ifdef CONFIG_HT_OVERRIDES
4408 os_memset(&htcaps, 0, sizeof(htcaps));
4409 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4410 params.htcaps = (u8 *) &htcaps;
4411 params.htcaps_mask = (u8 *) &htcaps_mask;
4412 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4413#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004414#ifdef CONFIG_VHT_OVERRIDES
4415 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4416 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4417 params.vhtcaps = &vhtcaps;
4418 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004419 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004420#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004421#ifdef CONFIG_HE_OVERRIDES
4422 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4423#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004424 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004425
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004426#ifdef CONFIG_P2P
4427 /*
4428 * If multi-channel concurrency is not supported, check for any
4429 * frequency conflict. In case of any frequency conflict, remove the
4430 * least prioritized connection.
4431 */
4432 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004433 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004434 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004435 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004436 wpa_printf(MSG_DEBUG,
4437 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004438 freq, params.freq.freq);
4439 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004440 wpa_s, params.freq.freq, ssid) < 0) {
4441 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004442 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004443 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004444 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004445 }
4446 }
4447#endif /* CONFIG_P2P */
4448
Dmitry Shmidte4663042016-04-04 10:07:49 -07004449 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004450 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004451 params.prev_bssid = prev_bssid;
4452
Hai Shalom60840252021-02-19 19:02:11 -08004453#ifdef CONFIG_SAE
4454 params.sae_pwe = wpa_s->conf->sae_pwe;
4455#endif /* CONFIG_SAE */
4456
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004457 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004458 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004459 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460 if (ret < 0) {
4461 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4462 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004463 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 /*
4465 * The driver is known to mean what is saying, so we
4466 * can stop right here; the association will not
4467 * succeed.
4468 */
Sunil Ravieb83e2a2024-06-28 17:34:56 +00004469 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004470 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004471 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004472 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004473 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4474 return;
4475 }
4476 /* try to continue anyway; new association will be tried again
4477 * after timeout */
4478 assoc_failed = 1;
4479 }
4480
4481 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4482 /* Set the key after the association just in case association
4483 * cleared the previously configured key. */
4484 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4485 /* No need to timeout authentication since there is no key
4486 * management. */
4487 wpa_supplicant_cancel_auth_timeout(wpa_s);
4488 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4489#ifdef CONFIG_IBSS_RSN
4490 } else if (ssid->mode == WPAS_MODE_IBSS &&
4491 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4492 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4493 /*
4494 * RSN IBSS authentication is per-STA and we can disable the
4495 * per-BSSID authentication.
4496 */
4497 wpa_supplicant_cancel_auth_timeout(wpa_s);
4498#endif /* CONFIG_IBSS_RSN */
4499 } else {
4500 /* Timeout for IEEE 802.11 authentication and association */
4501 int timeout = 60;
4502
4503 if (assoc_failed) {
4504 /* give IBSS a bit more time */
4505 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4506 } else if (wpa_s->conf->ap_scan == 1) {
4507 /* give IBSS a bit more time */
4508 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4509 }
4510 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4511 }
4512
Hai Shalomfdcde762020-04-02 11:19:20 -07004513#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004514 if (wep_keys_set &&
4515 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004516 /* Set static WEP keys again */
4517 wpa_set_wep_keys(wpa_s, ssid);
4518 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004519#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004520
Sunil8cd6f4d2022-06-28 18:40:46 +00004521 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 /*
4523 * Do not allow EAP session resumption between different
4524 * network configurations.
4525 */
4526 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4527 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004528
mtk30479d7f89782024-01-24 11:51:43 +08004529 if (!wpas_driver_bss_selection(wpa_s) ||
4530#ifdef CONFIG_P2P
4531 wpa_s->p2p_in_invitation ||
4532#endif /* CONFIG_P2P */
4533 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004534 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004535#ifdef CONFIG_HS20
4536 hs20_configure_frame_filters(wpa_s);
4537#endif /* CONFIG_HS20 */
4538 }
4539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004540 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4541 wpa_supplicant_initiate_eapol(wpa_s);
4542 if (old_ssid != wpa_s->current_ssid)
4543 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004544 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4545 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546}
4547
4548
4549static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4550 const u8 *addr)
4551{
4552 struct wpa_ssid *old_ssid;
4553
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004554 wpa_s->ml_connect_probe_ssid = NULL;
4555 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004556 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004558 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004559 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 wpa_sm_set_config(wpa_s->wpa, NULL);
4561 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4562 if (old_ssid != wpa_s->current_ssid)
4563 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004564
4565 wpas_scs_deinit(wpa_s);
4566 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004567 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4568}
4569
4570
4571/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004572 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4573 * @wpa_s: Pointer to wpa_supplicant data
4574 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4575 *
4576 * This function is used to request %wpa_supplicant to deauthenticate from the
4577 * current AP.
4578 */
4579void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004580 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004581{
4582 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004583 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004584 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004585
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004586 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004587 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004588 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004589 reason_code, reason2str(reason_code),
4590 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004591
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004592 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4593 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4594 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004595 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004596 else if (!is_zero_ether_addr(wpa_s->bssid))
4597 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004598 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4599 /*
4600 * When using driver-based BSS selection, we may not know the
4601 * BSSID with which we are currently trying to associate. We
4602 * need to notify the driver of this disconnection even in such
4603 * a case, so use the all zeros address here.
4604 */
4605 addr = wpa_s->bssid;
4606 zero_addr = 1;
4607 }
4608
Hai Shalom74f70d42019-02-11 14:42:39 -08004609 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4610 wpa_s->enabled_4addr_mode = 0;
4611
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004612#ifdef CONFIG_TDLS
4613 wpa_tdls_teardown_peers(wpa_s->wpa);
4614#endif /* CONFIG_TDLS */
4615
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004616#ifdef CONFIG_MESH
4617 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004618 struct mesh_conf *mconf;
4619
4620 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004621 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4622 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004623 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4624 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004625 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004626 }
4627#endif /* CONFIG_MESH */
4628
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004629 if (addr) {
4630 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004631 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004632 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004633 event.deauth_info.locally_generated = 1;
4634 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004635 if (zero_addr)
4636 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637 }
4638
4639 wpa_supplicant_clear_connection(wpa_s, addr);
4640}
4641
Hai Shalomfdcde762020-04-02 11:19:20 -07004642
4643void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4644{
4645 wpa_s->own_reconnect_req = 1;
4646 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4647
4648}
4649
4650
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004651static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4652 struct wpa_ssid *ssid)
4653{
4654 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4655 return;
4656
4657 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004658 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004659 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4660 wpas_notify_network_enabled_changed(wpa_s, ssid);
4661
4662 /*
4663 * Try to reassociate since there is no current configuration and a new
4664 * network was made available.
4665 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004666 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004667 wpa_s->reassociate = 1;
4668}
4669
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004670
Roshan Pius950bec92016-07-19 09:49:24 -07004671/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004672 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004673 * @wpa_s: wpa_supplicant structure for a network interface
4674 * Returns: The new network configuration or %NULL if operation failed
4675 *
4676 * This function performs the following operations:
4677 * 1. Adds a new network.
4678 * 2. Send network addition notification.
4679 * 3. Marks the network disabled.
4680 * 4. Set network default parameters.
4681 */
4682struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4683{
4684 struct wpa_ssid *ssid;
4685
4686 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004687 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004688 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004689 wpas_notify_network_added(wpa_s, ssid);
4690 ssid->disabled = 1;
4691 wpa_config_set_network_defaults(ssid);
4692
4693 return ssid;
4694}
4695
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004696
Roshan Pius950bec92016-07-19 09:49:24 -07004697/**
4698 * wpa_supplicant_remove_network - Remove a configured network based on id
4699 * @wpa_s: wpa_supplicant structure for a network interface
4700 * @id: Unique network id to search for
4701 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4702 * could not be removed
4703 *
4704 * This function performs the following operations:
4705 * 1. Removes the network.
4706 * 2. Send network removal notification.
4707 * 3. Update internal state machines.
4708 * 4. Stop any running sched scans.
4709 */
4710int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4711{
Sunil Ravia04bd252022-05-02 22:54:18 -07004712 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004713 int was_disabled;
4714
4715 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004716 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004717 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004718 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004719
Sunil Ravia04bd252022-05-02 22:54:18 -07004720 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004721#ifdef CONFIG_SME
4722 wpa_s->sme.prev_bssid_set = 0;
4723#endif /* CONFIG_SME */
4724 /*
4725 * Invalidate the EAP session cache if the current or
4726 * previously used network is removed.
4727 */
4728 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4729 }
4730
Sunil Ravia04bd252022-05-02 22:54:18 -07004731 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004732 wpa_sm_set_config(wpa_s->wpa, NULL);
4733 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4734
4735 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4736 wpa_s->own_disconnect_req = 1;
4737 wpa_supplicant_deauthenticate(wpa_s,
4738 WLAN_REASON_DEAUTH_LEAVING);
4739 }
4740
4741 was_disabled = ssid->disabled;
4742
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004743 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004744 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004745
4746 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004747 wpa_printf(MSG_DEBUG,
4748 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004749 wpa_supplicant_cancel_sched_scan(wpa_s);
4750 wpa_supplicant_req_scan(wpa_s, 0, 0);
4751 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004752
Roshan Pius950bec92016-07-19 09:49:24 -07004753 return 0;
4754}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004755
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004756
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004758 * wpa_supplicant_remove_all_networks - Remove all configured networks
4759 * @wpa_s: wpa_supplicant structure for a network interface
4760 * Returns: 0 on success (errors are currently ignored)
4761 *
4762 * This function performs the following operations:
4763 * 1. Remove all networks.
4764 * 2. Send network removal notifications.
4765 * 3. Update internal state machines.
4766 * 4. Stop any running sched scans.
4767 */
4768int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4769{
4770 struct wpa_ssid *ssid;
4771
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304772 if (wpa_s->drv_flags2 &
4773 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4774 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4775 wpa_drv_flush_pmkid(wpa_s);
4776
Hai Shalom899fcc72020-10-19 14:38:18 -07004777 if (wpa_s->sched_scanning)
4778 wpa_supplicant_cancel_sched_scan(wpa_s);
4779
4780 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4781 if (wpa_s->current_ssid) {
4782#ifdef CONFIG_SME
4783 wpa_s->sme.prev_bssid_set = 0;
4784#endif /* CONFIG_SME */
4785 wpa_sm_set_config(wpa_s->wpa, NULL);
4786 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4787 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4788 wpa_s->own_disconnect_req = 1;
4789 wpa_supplicant_deauthenticate(
4790 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4791 }
4792 ssid = wpa_s->conf->ssid;
4793 while (ssid) {
4794 struct wpa_ssid *remove_ssid = ssid;
4795 int id;
4796
4797 id = ssid->id;
4798 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004799 wpas_notify_network_removed(wpa_s, remove_ssid);
4800 wpa_config_remove_network(wpa_s->conf, id);
4801 }
4802 return 0;
4803}
4804
4805
4806/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004807 * wpa_supplicant_enable_network - Mark a configured network as enabled
4808 * @wpa_s: wpa_supplicant structure for a network interface
4809 * @ssid: wpa_ssid structure for a configured network or %NULL
4810 *
4811 * Enables the specified network or all networks if no network specified.
4812 */
4813void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4814 struct wpa_ssid *ssid)
4815{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004817 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4818 wpa_supplicant_enable_one_network(wpa_s, ssid);
4819 } else
4820 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004822 if (wpa_s->reassociate && !wpa_s->disconnected &&
4823 (!wpa_s->current_ssid ||
4824 wpa_s->wpa_state == WPA_DISCONNECTED ||
4825 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004826 if (wpa_s->sched_scanning) {
4827 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4828 "new network to scan filters");
4829 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004830 }
4831
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004832 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4833 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004834 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004835 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004836 }
4837}
4838
4839
4840/**
4841 * wpa_supplicant_disable_network - Mark a configured network as disabled
4842 * @wpa_s: wpa_supplicant structure for a network interface
4843 * @ssid: wpa_ssid structure for a configured network or %NULL
4844 *
4845 * Disables the specified network or all networks if no network specified.
4846 */
4847void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4848 struct wpa_ssid *ssid)
4849{
4850 struct wpa_ssid *other_ssid;
4851 int was_disabled;
4852
4853 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004854 if (wpa_s->sched_scanning)
4855 wpa_supplicant_cancel_sched_scan(wpa_s);
4856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004857 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4858 other_ssid = other_ssid->next) {
4859 was_disabled = other_ssid->disabled;
4860 if (was_disabled == 2)
4861 continue; /* do not change persistent P2P group
4862 * data */
4863
4864 other_ssid->disabled = 1;
4865
4866 if (was_disabled != other_ssid->disabled)
4867 wpas_notify_network_enabled_changed(
4868 wpa_s, other_ssid);
4869 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004870 if (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 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004877 if (ssid == wpa_s->current_ssid) {
4878 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4879 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004880 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004881 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004882 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883
4884 was_disabled = ssid->disabled;
4885
4886 ssid->disabled = 1;
4887
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004888 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004889 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004890 if (wpa_s->sched_scanning) {
4891 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4892 "to remove network from filters");
4893 wpa_supplicant_cancel_sched_scan(wpa_s);
4894 wpa_supplicant_req_scan(wpa_s, 0, 0);
4895 }
4896 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897 }
4898}
4899
4900
4901/**
4902 * wpa_supplicant_select_network - Attempt association with a network
4903 * @wpa_s: wpa_supplicant structure for a network interface
4904 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4905 */
4906void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4907 struct wpa_ssid *ssid)
4908{
4909
4910 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004911 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004913 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004914 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4915 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004916 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004918 disconnected = 1;
4919 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004920
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004921 if (ssid)
4922 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4923
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004924 /*
4925 * Mark all other networks disabled or mark all networks enabled if no
4926 * network specified.
4927 */
4928 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4929 other_ssid = other_ssid->next) {
4930 int was_disabled = other_ssid->disabled;
4931 if (was_disabled == 2)
4932 continue; /* do not change persistent P2P group data */
4933
4934 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004935 if (was_disabled && !other_ssid->disabled)
4936 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004937
4938 if (was_disabled != other_ssid->disabled)
4939 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4940 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004941
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004942 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4943 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004944 /* We are already associated with the selected network */
4945 wpa_printf(MSG_DEBUG, "Already associated with the "
4946 "selected network - do nothing");
4947 return;
4948 }
4949
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004950 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004951 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004952 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004953 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004954 (ssid->mode == WPAS_MODE_MESH ||
4955 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004956
4957 /*
4958 * Don't optimize next scan freqs since a new ESS has been
4959 * selected.
4960 */
4961 os_free(wpa_s->next_scan_freqs);
4962 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004963 } else {
4964 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004965 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967 wpa_s->disconnected = 0;
4968 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004969 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004970 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004971 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004972 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004973 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004974 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004975
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004976 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004977 wpa_supplicant_fast_associate(wpa_s) != 1) {
4978 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004979 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004980 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004981 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004982
4983 if (ssid)
4984 wpas_notify_network_selected(wpa_s, ssid);
4985}
4986
4987
4988/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004989 * wpas_remove_cred - Remove the specified credential and all the network
4990 * entries created based on the removed credential
4991 * @wpa_s: wpa_supplicant structure for a network interface
4992 * @cred: The credential to remove
4993 * Returns: 0 on success, -1 on failure
4994 */
4995int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4996{
4997 struct wpa_ssid *ssid, *next;
4998 int id;
4999
5000 if (!cred) {
5001 wpa_printf(MSG_DEBUG, "Could not find cred");
5002 return -1;
5003 }
5004
5005 id = cred->id;
5006 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5007 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5008 return -1;
5009 }
5010
5011 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5012
5013 /* Remove any network entry created based on the removed credential */
5014 ssid = wpa_s->conf->ssid;
5015 while (ssid) {
5016 next = ssid->next;
5017
5018 if (ssid->parent_cred == cred) {
5019 wpa_printf(MSG_DEBUG,
5020 "Remove network id %d since it used the removed credential",
5021 ssid->id);
5022 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5023 -1) {
5024 wpa_printf(MSG_DEBUG,
5025 "Could not find network id=%d",
5026 ssid->id);
5027 }
5028 }
5029
5030 ssid = next;
5031 }
5032
5033 return 0;
5034}
5035
5036
5037/**
5038 * wpas_remove_cred - Remove all the Interworking credentials
5039 * @wpa_s: wpa_supplicant structure for a network interface
5040 * Returns: 0 on success, -1 on failure
5041 */
5042int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5043{
5044 int res, ret = 0;
5045 struct wpa_cred *cred, *prev;
5046
5047 cred = wpa_s->conf->cred;
5048 while (cred) {
5049 prev = cred;
5050 cred = cred->next;
5051 res = wpas_remove_cred(wpa_s, prev);
5052 if (res < 0) {
5053 wpa_printf(MSG_DEBUG,
5054 "Removal of all credentials failed - failed to remove credential id=%d",
5055 prev->id);
5056 ret = -1;
5057 }
5058 }
5059
5060 return ret;
5061}
5062
5063
5064/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005065 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5066 * @wpa_s: wpa_supplicant structure for a network interface
5067 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5068 * @pkcs11_module_path: PKCS #11 module path or NULL
5069 * Returns: 0 on success; -1 on failure
5070 *
5071 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5072 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5073 * module path fails the paths will be reset to the default value (NULL).
5074 */
5075int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5076 const char *pkcs11_engine_path,
5077 const char *pkcs11_module_path)
5078{
5079 char *pkcs11_engine_path_copy = NULL;
5080 char *pkcs11_module_path_copy = NULL;
5081
5082 if (pkcs11_engine_path != NULL) {
5083 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5084 if (pkcs11_engine_path_copy == NULL)
5085 return -1;
5086 }
5087 if (pkcs11_module_path != NULL) {
5088 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005089 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005090 os_free(pkcs11_engine_path_copy);
5091 return -1;
5092 }
5093 }
5094
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005095#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005096 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005097 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005098#endif /* CONFIG_PKCS11_ENGINE_PATH */
5099#ifndef CONFIG_PKCS11_MODULE_PATH
5100 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005101 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005102#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005103
5104 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5105 eapol_sm_deinit(wpa_s->eapol);
5106 wpa_s->eapol = NULL;
5107 if (wpa_supplicant_init_eapol(wpa_s)) {
5108 /* Error -> Reset paths to the default value (NULL) once. */
5109 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5110 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5111 NULL);
5112
5113 return -1;
5114 }
5115 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5116
5117 return 0;
5118}
5119
5120
5121/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5123 * @wpa_s: wpa_supplicant structure for a network interface
5124 * @ap_scan: AP scan mode
5125 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5126 *
5127 */
5128int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5129{
5130
5131 int old_ap_scan;
5132
5133 if (ap_scan < 0 || ap_scan > 2)
5134 return -1;
5135
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005136 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5137 wpa_printf(MSG_INFO,
5138 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5139 }
5140
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005141#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005142 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5143 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5144 wpa_s->wpa_state < WPA_COMPLETED) {
5145 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5146 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005147 return 0;
5148 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005149#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151 old_ap_scan = wpa_s->conf->ap_scan;
5152 wpa_s->conf->ap_scan = ap_scan;
5153
5154 if (old_ap_scan != wpa_s->conf->ap_scan)
5155 wpas_notify_ap_scan_changed(wpa_s);
5156
5157 return 0;
5158}
5159
5160
5161/**
5162 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5163 * @wpa_s: wpa_supplicant structure for a network interface
5164 * @expire_age: Expiration age in seconds
5165 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5166 *
5167 */
5168int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5169 unsigned int bss_expire_age)
5170{
5171 if (bss_expire_age < 10) {
5172 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5173 bss_expire_age);
5174 return -1;
5175 }
5176 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5177 bss_expire_age);
5178 wpa_s->conf->bss_expiration_age = bss_expire_age;
5179
5180 return 0;
5181}
5182
5183
5184/**
5185 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5186 * @wpa_s: wpa_supplicant structure for a network interface
5187 * @expire_count: number of scans after which an unseen BSS is reclaimed
5188 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5189 *
5190 */
5191int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5192 unsigned int bss_expire_count)
5193{
5194 if (bss_expire_count < 1) {
5195 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5196 bss_expire_count);
5197 return -1;
5198 }
5199 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5200 bss_expire_count);
5201 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5202
5203 return 0;
5204}
5205
5206
5207/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005208 * wpa_supplicant_set_scan_interval - Set scan interval
5209 * @wpa_s: wpa_supplicant structure for a network interface
5210 * @scan_interval: scan interval in seconds
5211 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5212 *
5213 */
5214int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5215 int scan_interval)
5216{
5217 if (scan_interval < 0) {
5218 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5219 scan_interval);
5220 return -1;
5221 }
5222 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5223 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005224 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005225
5226 return 0;
5227}
5228
5229
5230/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005231 * wpa_supplicant_set_debug_params - Set global debug params
5232 * @global: wpa_global structure
5233 * @debug_level: debug level
5234 * @debug_timestamp: determines if show timestamp in debug data
5235 * @debug_show_keys: determines if show keys in debug data
5236 * Returns: 0 if succeed or -1 if debug_level has wrong value
5237 */
5238int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5239 int debug_timestamp, int debug_show_keys)
5240{
5241
5242 int old_level, old_timestamp, old_show_keys;
5243
5244 /* check for allowed debuglevels */
5245 if (debug_level != MSG_EXCESSIVE &&
5246 debug_level != MSG_MSGDUMP &&
5247 debug_level != MSG_DEBUG &&
5248 debug_level != MSG_INFO &&
5249 debug_level != MSG_WARNING &&
5250 debug_level != MSG_ERROR)
5251 return -1;
5252
5253 old_level = wpa_debug_level;
5254 old_timestamp = wpa_debug_timestamp;
5255 old_show_keys = wpa_debug_show_keys;
5256
5257 wpa_debug_level = debug_level;
5258 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5259 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5260
5261 if (wpa_debug_level != old_level)
5262 wpas_notify_debug_level_changed(global);
5263 if (wpa_debug_timestamp != old_timestamp)
5264 wpas_notify_debug_timestamp_changed(global);
5265 if (wpa_debug_show_keys != old_show_keys)
5266 wpas_notify_debug_show_keys_changed(global);
5267
5268 return 0;
5269}
5270
5271
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005272#ifdef CONFIG_OWE
5273static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5274 const u8 *entry_ssid, size_t entry_ssid_len)
5275{
5276 const u8 *owe, *pos, *end;
5277 u8 ssid_len;
5278 struct wpa_bss *bss;
5279
5280 /* Check network profile SSID aganst the SSID in the
5281 * OWE Transition Mode element. */
5282
5283 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5284 if (!bss)
5285 return 0;
5286
5287 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5288 if (!owe)
5289 return 0;
5290
5291 pos = owe + 6;
5292 end = owe + 2 + owe[1];
5293
5294 if (end - pos < ETH_ALEN + 1)
5295 return 0;
5296 pos += ETH_ALEN;
5297 ssid_len = *pos++;
5298 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5299 return 0;
5300
5301 return entry_ssid_len == ssid_len &&
5302 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5303}
5304#endif /* CONFIG_OWE */
5305
5306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005307/**
5308 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5309 * @wpa_s: Pointer to wpa_supplicant data
5310 * Returns: A pointer to the current network structure or %NULL on failure
5311 */
5312struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5313{
5314 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005315 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005316 int res;
5317 size_t ssid_len;
5318 u8 bssid[ETH_ALEN];
5319 int wired;
5320
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005321 res = wpa_drv_get_ssid(wpa_s, ssid);
5322 if (res < 0) {
5323 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5324 "driver");
5325 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005326 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005327 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005329 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005330 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5331 "driver");
5332 return NULL;
5333 }
5334
5335 wired = wpa_s->conf->ap_scan == 0 &&
5336 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5337
5338 entry = wpa_s->conf->ssid;
5339 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005340 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005341 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005342 (!entry->ssid ||
5343 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5344 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005345 (!entry->bssid_set ||
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005346 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005347 return entry;
5348#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005349 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005350 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5351 (entry->ssid == NULL || entry->ssid_len == 0) &&
5352 (!entry->bssid_set ||
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005353 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005354 return entry;
5355#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005356
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005357#ifdef CONFIG_OWE
5358 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005359 (entry->ssid &&
5360 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5361 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005362 (!entry->bssid_set ||
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005363 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005364 return entry;
5365#endif /* CONFIG_OWE */
5366
Dmitry Shmidt04949592012-07-19 12:16:46 -07005367 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005368 entry->ssid_len == 0 &&
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005369 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005370 return entry;
5371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005372 entry = entry->next;
5373 }
5374
5375 return NULL;
5376}
5377
5378
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005379static int select_driver(struct wpa_supplicant *wpa_s, int i)
5380{
5381 struct wpa_global *global = wpa_s->global;
5382
5383 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005384 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005385 if (global->drv_priv[i] == NULL) {
5386 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5387 "'%s'", wpa_drivers[i]->name);
5388 return -1;
5389 }
5390 }
5391
5392 wpa_s->driver = wpa_drivers[i];
5393 wpa_s->global_drv_priv = global->drv_priv[i];
5394
5395 return 0;
5396}
5397
5398
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005399static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5400 const char *name)
5401{
5402 int i;
5403 size_t len;
5404 const char *pos, *driver = name;
5405
5406 if (wpa_s == NULL)
5407 return -1;
5408
5409 if (wpa_drivers[0] == NULL) {
5410 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5411 "wpa_supplicant");
5412 return -1;
5413 }
5414
5415 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005416 /* Default to first successful driver in the list */
5417 for (i = 0; wpa_drivers[i]; i++) {
5418 if (select_driver(wpa_s, i) == 0)
5419 return 0;
5420 }
5421 /* Drivers have each reported failure, so no wpa_msg() here. */
5422 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005423 }
5424
5425 do {
5426 pos = os_strchr(driver, ',');
5427 if (pos)
5428 len = pos - driver;
5429 else
5430 len = os_strlen(driver);
5431
5432 for (i = 0; wpa_drivers[i]; i++) {
5433 if (os_strlen(wpa_drivers[i]->name) == len &&
5434 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005435 0) {
5436 /* First driver that succeeds wins */
5437 if (select_driver(wpa_s, i) == 0)
5438 return 0;
5439 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005440 }
5441
5442 driver = pos + 1;
5443 } while (pos);
5444
5445 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5446 return -1;
5447}
5448
5449
5450/**
5451 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5452 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5453 * with struct wpa_driver_ops::init()
5454 * @src_addr: Source address of the EAPOL frame
5455 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5456 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005457 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005458 *
5459 * This function is called for each received EAPOL frame. Most driver
5460 * interfaces rely on more generic OS mechanism for receiving frames through
5461 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5462 * take care of received EAPOL frames and deliver them to the core supplicant
5463 * code by calling this function.
5464 */
5465void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005466 const u8 *buf, size_t len,
5467 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005468{
5469 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005470 const u8 *connected_addr = wpa_s->valid_links ?
5471 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005472
Sunil8cd6f4d2022-06-28 18:40:46 +00005473 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5474 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5476
Hai Shalomc1a21442022-02-04 13:43:00 -08005477 if (wpa_s->own_disconnect_req) {
5478 wpa_printf(MSG_DEBUG,
5479 "Drop received EAPOL frame as we are disconnecting");
5480 return;
5481 }
5482
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005483#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005484 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5485 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005486 if (wpa_s->ignore_auth_resp) {
5487 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5488 return;
5489 }
5490#endif /* CONFIG_TESTING_OPTIONS */
5491
Jouni Malinena05074c2012-12-21 21:35:35 +02005492 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5493 (wpa_s->last_eapol_matches_bssid &&
5494#ifdef CONFIG_AP
5495 !wpa_s->ap_iface &&
5496#endif /* CONFIG_AP */
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005497 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005498 /*
5499 * There is possible race condition between receiving the
5500 * association event and the EAPOL frame since they are coming
5501 * through different paths from the driver. In order to avoid
5502 * issues in trying to process the EAPOL frame before receiving
5503 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005504 * the association event is received. This may also be needed in
5505 * driver-based roaming case, so also use src_addr != BSSID as a
5506 * trigger if we have previously confirmed that the
5507 * Authenticator uses BSSID as the src_addr (which is not the
5508 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005509 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005510 wpa_dbg(wpa_s, MSG_DEBUG,
5511 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5512 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005513 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005514 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005515 wpabuf_free(wpa_s->pending_eapol_rx);
5516 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5517 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005518 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005519 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5520 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005521 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522 }
5523 return;
5524 }
5525
Jouni Malinena05074c2012-12-21 21:35:35 +02005526 wpa_s->last_eapol_matches_bssid =
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005527 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005528
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005529#ifdef CONFIG_AP
5530 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005531 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5532 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005533 return;
5534 }
5535#endif /* CONFIG_AP */
5536
5537 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5538 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5539 "no key management is configured");
5540 return;
5541 }
5542
5543 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005544 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005545 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5546 wpa_s->wpa_state != WPA_COMPLETED) &&
5547 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005548 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005549 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005550 int timeout = 10;
5551
5552 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5553 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5554 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5555 /* Use longer timeout for IEEE 802.1X/EAP */
5556 timeout = 70;
5557 }
5558
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005559#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005560 if (wpa_s->current_ssid && wpa_s->current_bss &&
5561 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5562 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5563 /*
5564 * Use shorter timeout if going through WPS AP iteration
5565 * for PIN config method with an AP that does not
5566 * advertise Selected Registrar.
5567 */
5568 struct wpabuf *wps_ie;
5569
5570 wps_ie = wpa_bss_get_vendor_ie_multi(
5571 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5572 if (wps_ie &&
5573 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5574 timeout = 10;
5575 wpabuf_free(wps_ie);
5576 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005577#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005578
5579 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005580 }
5581 wpa_s->eapol_received++;
5582
5583 if (wpa_s->countermeasures) {
5584 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5585 "EAPOL packet");
5586 return;
5587 }
5588
5589#ifdef CONFIG_IBSS_RSN
5590 if (wpa_s->current_ssid &&
5591 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005592 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5593 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005594 return;
5595 }
5596#endif /* CONFIG_IBSS_RSN */
5597
5598 /* Source address of the incoming EAPOL frame could be compared to the
5599 * current BSSID. However, it is possible that a centralized
5600 * Authenticator could be using another MAC address than the BSSID of
5601 * an AP, so just allow any address to be used for now. The replies are
5602 * still sent to the current BSSID (if available), though. */
5603
5604 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5605 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005606 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5607 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005608 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5609 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610 return;
5611 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005612 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005613 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5615 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005616 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617 * handshake processing which would normally set portValid. We
5618 * need this to allow the EAPOL state machines to be completed
5619 * without going through EAPOL-Key handshake.
5620 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005621 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005622 }
5623}
5624
5625
Sunil8cd6f4d2022-06-28 18:40:46 +00005626static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5627 const u8 *buf, size_t len)
5628{
5629 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5630 FRAME_ENCRYPTION_UNKNOWN);
5631}
5632
5633
Hai Shalomb755a2a2020-04-23 21:49:02 -07005634static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5635{
5636 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5637 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5638}
5639
5640
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005641int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005642{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005643 u8 prev_mac_addr[ETH_ALEN];
5644
5645 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5646
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005647 if ((!wpa_s->p2p_mgmt ||
5648 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5649 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005650 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005651 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5652 wpa_drv_get_mac_addr(wpa_s),
5653 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005654 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005655 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005656 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005657 if (wpa_s->l2 == NULL)
5658 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005659
5660 if (l2_packet_set_packet_filter(wpa_s->l2,
5661 L2_PACKET_FILTER_PKTTYPE))
5662 wpa_dbg(wpa_s, MSG_DEBUG,
5663 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005664
5665 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5666 wpa_msg(wpa_s, MSG_ERROR,
5667 "Failed to get own L2 address");
5668 return -1;
5669 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005670 } else {
5671 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5672 if (addr)
5673 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5674 }
5675
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005676 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005677 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005678
Hai Shalomc3565922019-10-28 11:58:20 -07005679#ifdef CONFIG_FST
5680 if (wpa_s->fst)
5681 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5682#endif /* CONFIG_FST */
5683
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005684 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +00005685 wpas_notify_mac_address_changed(wpa_s);
5686
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005687 return 0;
5688}
5689
5690
Dmitry Shmidt04949592012-07-19 12:16:46 -07005691static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5692 const u8 *buf, size_t len)
5693{
5694 struct wpa_supplicant *wpa_s = ctx;
5695 const struct l2_ethhdr *eth;
5696
5697 if (len < sizeof(*eth))
5698 return;
5699 eth = (const struct l2_ethhdr *) buf;
5700
Sunil Ravieb83e2a2024-06-28 17:34:56 +00005701 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005702 !(eth->h_dest[0] & 0x01)) {
5703 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5704 " (bridge - not for this interface - ignore)",
5705 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5706 return;
5707 }
5708
5709 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5710 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5711 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005712 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005713}
5714
5715
Hai Shalom899fcc72020-10-19 14:38:18 -07005716int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5717 const char *bridge_ifname)
5718{
5719 if (wpa_s->wpa_state > WPA_SCANNING)
5720 return -EBUSY;
5721
5722 if (bridge_ifname &&
5723 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5724 return -EINVAL;
5725
5726 if (!bridge_ifname)
5727 bridge_ifname = "";
5728
5729 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5730 return 0;
5731
5732 if (wpa_s->l2_br) {
5733 l2_packet_deinit(wpa_s->l2_br);
5734 wpa_s->l2_br = NULL;
5735 }
5736
5737 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5738 sizeof(wpa_s->bridge_ifname));
5739
5740 if (wpa_s->bridge_ifname[0]) {
5741 wpa_dbg(wpa_s, MSG_DEBUG,
5742 "Receiving packets from bridge interface '%s'",
5743 wpa_s->bridge_ifname);
5744 wpa_s->l2_br = l2_packet_init_bridge(
5745 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5746 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5747 if (!wpa_s->l2_br) {
5748 wpa_msg(wpa_s, MSG_ERROR,
5749 "Failed to open l2_packet connection for the bridge interface '%s'",
5750 wpa_s->bridge_ifname);
5751 goto fail;
5752 }
5753 }
5754
5755#ifdef CONFIG_TDLS
5756 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5757 goto fail;
5758#endif /* CONFIG_TDLS */
5759
5760 return 0;
5761fail:
5762 wpa_s->bridge_ifname[0] = 0;
5763 if (wpa_s->l2_br) {
5764 l2_packet_deinit(wpa_s->l2_br);
5765 wpa_s->l2_br = NULL;
5766 }
5767#ifdef CONFIG_TDLS
5768 if (!wpa_s->p2p_mgmt)
5769 wpa_tdls_init(wpa_s->wpa);
5770#endif /* CONFIG_TDLS */
5771 return -EIO;
5772}
5773
5774
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005775/**
5776 * wpa_supplicant_driver_init - Initialize driver interface parameters
5777 * @wpa_s: Pointer to wpa_supplicant data
5778 * Returns: 0 on success, -1 on failure
5779 *
5780 * This function is called to initialize driver interface parameters.
5781 * wpa_drv_init() must have been called before this function to initialize the
5782 * driver interface.
5783 */
5784int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5785{
5786 static int interface_count = 0;
5787
5788 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5789 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005790
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005791 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5792 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005793 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005794 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5795
Hai Shalomb755a2a2020-04-23 21:49:02 -07005796 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005797 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5798 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005799 wpa_s->l2_br = l2_packet_init_bridge(
5800 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5801 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005802 if (wpa_s->l2_br == NULL) {
5803 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5804 "connection for the bridge interface '%s'",
5805 wpa_s->bridge_ifname);
5806 return -1;
5807 }
5808 }
5809
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005810 if (wpa_s->conf->ap_scan == 2 &&
5811 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5812 wpa_printf(MSG_INFO,
5813 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5814 }
5815
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005816 wpa_clear_keys(wpa_s, NULL);
5817
5818 /* Make sure that TKIP countermeasures are not left enabled (could
5819 * happen if wpa_supplicant is killed during countermeasures. */
5820 wpa_drv_set_countermeasures(wpa_s, 0);
5821
5822 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5823 wpa_drv_flush_pmkid(wpa_s);
5824
5825 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005826 wpa_s->prev_scan_wildcard = 0;
5827
Dmitry Shmidt04949592012-07-19 12:16:46 -07005828 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005829 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5830 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5831 interface_count = 0;
5832 }
Keith Mok4389c282022-11-23 21:36:48 +00005833#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005834 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005835 wpa_supplicant_delayed_sched_scan(wpa_s,
5836 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005837 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005838 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005839 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005840#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005841 interface_count++;
5842 } else
5843 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5844
5845 return 0;
5846}
5847
5848
5849static int wpa_supplicant_daemon(const char *pid_file)
5850{
5851 wpa_printf(MSG_DEBUG, "Daemonize..");
5852 return os_daemonize(pid_file);
5853}
5854
5855
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005856static struct wpa_supplicant *
5857wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005858{
5859 struct wpa_supplicant *wpa_s;
5860
5861 wpa_s = os_zalloc(sizeof(*wpa_s));
5862 if (wpa_s == NULL)
5863 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005864 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005865 wpa_s->scan_interval = 5;
5866 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005867 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005868 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005869 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005870 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005871
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005872 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005873 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005874#ifdef CONFIG_TESTING_OPTIONS
5875 dl_list_init(&wpa_s->drv_signal_override);
5876#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005877 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005878 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880 return wpa_s;
5881}
5882
5883
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005884#ifdef CONFIG_HT_OVERRIDES
5885
5886static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5887 struct ieee80211_ht_capabilities *htcaps,
5888 struct ieee80211_ht_capabilities *htcaps_mask,
5889 const char *ht_mcs)
5890{
5891 /* parse ht_mcs into hex array */
5892 int i;
5893 const char *tmp = ht_mcs;
5894 char *end = NULL;
5895
5896 /* If ht_mcs is null, do not set anything */
5897 if (!ht_mcs)
5898 return 0;
5899
5900 /* This is what we are setting in the kernel */
5901 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5902
5903 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5904
5905 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005906 long v;
5907
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005908 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005909 v = strtol(tmp, &end, 16);
5910
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005911 if (errno == 0) {
5912 wpa_msg(wpa_s, MSG_DEBUG,
5913 "htcap value[%i]: %ld end: %p tmp: %p",
5914 i, v, end, tmp);
5915 if (end == tmp)
5916 break;
5917
5918 htcaps->supported_mcs_set[i] = v;
5919 tmp = end;
5920 } else {
5921 wpa_msg(wpa_s, MSG_ERROR,
5922 "Failed to parse ht-mcs: %s, error: %s\n",
5923 ht_mcs, strerror(errno));
5924 return -1;
5925 }
5926 }
5927
5928 /*
5929 * If we were able to parse any values, then set mask for the MCS set.
5930 */
5931 if (i) {
5932 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5933 IEEE80211_HT_MCS_MASK_LEN - 1);
5934 /* skip the 3 reserved bits */
5935 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5936 0x1f;
5937 }
5938
5939 return 0;
5940}
5941
5942
5943static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5944 struct ieee80211_ht_capabilities *htcaps,
5945 struct ieee80211_ht_capabilities *htcaps_mask,
5946 int disabled)
5947{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005948 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005949
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005950 if (disabled == -1)
5951 return 0;
5952
Hai Shalom74f70d42019-02-11 14:42:39 -08005953 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5954
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005955 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5956 htcaps_mask->ht_capabilities_info |= msk;
5957 if (disabled)
5958 htcaps->ht_capabilities_info &= msk;
5959 else
5960 htcaps->ht_capabilities_info |= msk;
5961
5962 return 0;
5963}
5964
5965
5966static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5967 struct ieee80211_ht_capabilities *htcaps,
5968 struct ieee80211_ht_capabilities *htcaps_mask,
5969 int factor)
5970{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005971 if (factor == -1)
5972 return 0;
5973
Hai Shalom74f70d42019-02-11 14:42:39 -08005974 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5975
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005976 if (factor < 0 || factor > 3) {
5977 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5978 "Must be 0-3 or -1", factor);
5979 return -EINVAL;
5980 }
5981
5982 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5983 htcaps->a_mpdu_params &= ~0x3;
5984 htcaps->a_mpdu_params |= factor & 0x3;
5985
5986 return 0;
5987}
5988
5989
5990static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5991 struct ieee80211_ht_capabilities *htcaps,
5992 struct ieee80211_ht_capabilities *htcaps_mask,
5993 int density)
5994{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005995 if (density == -1)
5996 return 0;
5997
Hai Shalom74f70d42019-02-11 14:42:39 -08005998 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5999
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006000 if (density < 0 || density > 7) {
6001 wpa_msg(wpa_s, MSG_ERROR,
6002 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6003 density);
6004 return -EINVAL;
6005 }
6006
6007 htcaps_mask->a_mpdu_params |= 0x1C;
6008 htcaps->a_mpdu_params &= ~(0x1C);
6009 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6010
6011 return 0;
6012}
6013
6014
6015static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6016 struct ieee80211_ht_capabilities *htcaps,
6017 struct ieee80211_ht_capabilities *htcaps_mask,
6018 int disabled)
6019{
Hai Shalom74f70d42019-02-11 14:42:39 -08006020 if (disabled)
6021 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006022
Paul Stewart092955c2017-02-06 09:13:09 -08006023 set_disable_ht40(htcaps, disabled);
6024 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006025
6026 return 0;
6027}
6028
6029
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006030static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6031 struct ieee80211_ht_capabilities *htcaps,
6032 struct ieee80211_ht_capabilities *htcaps_mask,
6033 int disabled)
6034{
6035 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006036 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6037 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006038
Hai Shalom74f70d42019-02-11 14:42:39 -08006039 if (disabled)
6040 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006041
6042 if (disabled)
6043 htcaps->ht_capabilities_info &= ~msk;
6044 else
6045 htcaps->ht_capabilities_info |= msk;
6046
6047 htcaps_mask->ht_capabilities_info |= msk;
6048
6049 return 0;
6050}
6051
6052
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006053static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6054 struct ieee80211_ht_capabilities *htcaps,
6055 struct ieee80211_ht_capabilities *htcaps_mask,
6056 int disabled)
6057{
6058 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006059 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006060
Hai Shalom74f70d42019-02-11 14:42:39 -08006061 if (disabled)
6062 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006063
6064 if (disabled)
6065 htcaps->ht_capabilities_info &= ~msk;
6066 else
6067 htcaps->ht_capabilities_info |= msk;
6068
6069 htcaps_mask->ht_capabilities_info |= msk;
6070
6071 return 0;
6072}
6073
6074
Hai Shalom74f70d42019-02-11 14:42:39 -08006075static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6076 struct ieee80211_ht_capabilities *htcaps,
6077 struct ieee80211_ht_capabilities *htcaps_mask,
6078 int tx_stbc)
6079{
6080 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6081
6082 if (tx_stbc == -1)
6083 return 0;
6084
6085 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6086
6087 if (tx_stbc < 0 || tx_stbc > 1) {
6088 wpa_msg(wpa_s, MSG_ERROR,
6089 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6090 return -EINVAL;
6091 }
6092
6093 htcaps_mask->ht_capabilities_info |= msk;
6094 htcaps->ht_capabilities_info &= ~msk;
6095 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6096
6097 return 0;
6098}
6099
6100
6101static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6102 struct ieee80211_ht_capabilities *htcaps,
6103 struct ieee80211_ht_capabilities *htcaps_mask,
6104 int rx_stbc)
6105{
6106 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6107
6108 if (rx_stbc == -1)
6109 return 0;
6110
6111 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6112
6113 if (rx_stbc < 0 || rx_stbc > 3) {
6114 wpa_msg(wpa_s, MSG_ERROR,
6115 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6116 return -EINVAL;
6117 }
6118
6119 htcaps_mask->ht_capabilities_info |= msk;
6120 htcaps->ht_capabilities_info &= ~msk;
6121 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6122
6123 return 0;
6124}
6125
6126
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006127void wpa_supplicant_apply_ht_overrides(
6128 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6129 struct wpa_driver_associate_params *params)
6130{
6131 struct ieee80211_ht_capabilities *htcaps;
6132 struct ieee80211_ht_capabilities *htcaps_mask;
6133
6134 if (!ssid)
6135 return;
6136
6137 params->disable_ht = ssid->disable_ht;
6138 if (!params->htcaps || !params->htcaps_mask)
6139 return;
6140
6141 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6142 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6143 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6144 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6145 ssid->disable_max_amsdu);
6146 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6147 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6148 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006149 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006150 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006151 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6152 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006153
6154 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006155 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006156 htcaps->ht_capabilities_info |= bit;
6157 htcaps_mask->ht_capabilities_info |= bit;
6158 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006159}
6160
6161#endif /* CONFIG_HT_OVERRIDES */
6162
6163
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006164#ifdef CONFIG_VHT_OVERRIDES
6165void wpa_supplicant_apply_vht_overrides(
6166 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6167 struct wpa_driver_associate_params *params)
6168{
6169 struct ieee80211_vht_capabilities *vhtcaps;
6170 struct ieee80211_vht_capabilities *vhtcaps_mask;
6171
6172 if (!ssid)
6173 return;
6174
6175 params->disable_vht = ssid->disable_vht;
6176
6177 vhtcaps = (void *) params->vhtcaps;
6178 vhtcaps_mask = (void *) params->vhtcaps_mask;
6179
6180 if (!vhtcaps || !vhtcaps_mask)
6181 return;
6182
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006183 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6184 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006185
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006186#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006187 if (ssid->disable_sgi) {
6188 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6189 VHT_CAP_SHORT_GI_160);
6190 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6191 VHT_CAP_SHORT_GI_160);
6192 wpa_msg(wpa_s, MSG_DEBUG,
6193 "disable-sgi override specified, vht-caps: 0x%x",
6194 vhtcaps->vht_capabilities_info);
6195 }
6196
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006197 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006198 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6199 int max_ampdu;
6200
6201 max_ampdu = (ssid->vht_capa &
6202 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6203 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006204
6205 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6206 wpa_set_ampdu_factor(wpa_s,
6207 (void *) params->htcaps,
6208 (void *) params->htcaps_mask,
6209 max_ampdu);
6210 }
6211#endif /* CONFIG_HT_OVERRIDES */
6212
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006213#define OVERRIDE_MCS(i) \
6214 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6215 vhtcaps_mask->vht_supported_mcs_set.tx_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.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006218 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6219 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006220 } \
6221 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6222 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006223 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006224 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006225 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6226 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006227 }
6228
6229 OVERRIDE_MCS(1);
6230 OVERRIDE_MCS(2);
6231 OVERRIDE_MCS(3);
6232 OVERRIDE_MCS(4);
6233 OVERRIDE_MCS(5);
6234 OVERRIDE_MCS(6);
6235 OVERRIDE_MCS(7);
6236 OVERRIDE_MCS(8);
6237}
6238#endif /* CONFIG_VHT_OVERRIDES */
6239
6240
Hai Shalomfdcde762020-04-02 11:19:20 -07006241#ifdef CONFIG_HE_OVERRIDES
6242void wpa_supplicant_apply_he_overrides(
6243 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6244 struct wpa_driver_associate_params *params)
6245{
6246 if (!ssid)
6247 return;
6248
6249 params->disable_he = ssid->disable_he;
6250}
6251#endif /* CONFIG_HE_OVERRIDES */
6252
6253
Sunil Ravi77d572f2023-01-17 23:58:31 +00006254void wpa_supplicant_apply_eht_overrides(
6255 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6256 struct wpa_driver_associate_params *params)
6257{
6258 if (!ssid)
6259 return;
6260
6261 params->disable_eht = ssid->disable_eht;
6262}
6263
6264
Dmitry Shmidt04949592012-07-19 12:16:46 -07006265static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6266{
6267#ifdef PCSC_FUNCS
6268 size_t len;
6269
6270 if (!wpa_s->conf->pcsc_reader)
6271 return 0;
6272
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006273 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006274 if (!wpa_s->scard)
6275 return 1;
6276
6277 if (wpa_s->conf->pcsc_pin &&
6278 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6279 scard_deinit(wpa_s->scard);
6280 wpa_s->scard = NULL;
6281 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6282 return -1;
6283 }
6284
6285 len = sizeof(wpa_s->imsi) - 1;
6286 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6287 scard_deinit(wpa_s->scard);
6288 wpa_s->scard = NULL;
6289 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6290 return -1;
6291 }
6292 wpa_s->imsi[len] = '\0';
6293
6294 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6295
6296 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6297 wpa_s->imsi, wpa_s->mnc_len);
6298
6299 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6300 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6301#endif /* PCSC_FUNCS */
6302
6303 return 0;
6304}
6305
6306
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006307int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6308{
6309 char *val, *pos;
6310
6311 ext_password_deinit(wpa_s->ext_pw);
6312 wpa_s->ext_pw = NULL;
6313 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6314
6315 if (!wpa_s->conf->ext_password_backend)
6316 return 0;
6317
6318 val = os_strdup(wpa_s->conf->ext_password_backend);
6319 if (val == NULL)
6320 return -1;
6321 pos = os_strchr(val, ':');
6322 if (pos)
6323 *pos++ = '\0';
6324
6325 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6326
6327 wpa_s->ext_pw = ext_password_init(val, pos);
6328 os_free(val);
6329 if (wpa_s->ext_pw == NULL) {
6330 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6331 return -1;
6332 }
6333 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6334
6335 return 0;
6336}
6337
6338
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006339#ifdef CONFIG_FST
6340
6341static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6342{
6343 struct wpa_supplicant *wpa_s = ctx;
6344
6345 return (is_zero_ether_addr(wpa_s->bssid) ||
6346 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6347}
6348
6349
6350static void wpas_fst_get_channel_info_cb(void *ctx,
6351 enum hostapd_hw_mode *hw_mode,
6352 u8 *channel)
6353{
6354 struct wpa_supplicant *wpa_s = ctx;
6355
6356 if (wpa_s->current_bss) {
6357 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6358 channel);
6359 } else if (wpa_s->hw.num_modes) {
6360 *hw_mode = wpa_s->hw.modes[0].mode;
6361 } else {
6362 WPA_ASSERT(0);
6363 *hw_mode = 0;
6364 }
6365}
6366
6367
6368static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6369{
6370 struct wpa_supplicant *wpa_s = ctx;
6371
6372 *modes = wpa_s->hw.modes;
6373 return wpa_s->hw.num_modes;
6374}
6375
6376
6377static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6378{
6379 struct wpa_supplicant *wpa_s = ctx;
6380
6381 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6382 wpa_s->fst_ies = fst_ies;
6383}
6384
6385
6386static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6387{
6388 struct wpa_supplicant *wpa_s = ctx;
6389
Sunil Ravieb83e2a2024-06-28 17:34:56 +00006390 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
Paul Stewart092955c2017-02-06 09:13:09 -08006391 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6392 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6393 return -1;
6394 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006395 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006396 wpa_s->own_addr, wpa_s->bssid,
6397 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006398 0);
6399}
6400
6401
6402static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6403{
6404 struct wpa_supplicant *wpa_s = ctx;
6405
Sunil Ravieb83e2a2024-06-28 17:34:56 +00006406 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006407 return wpa_s->received_mb_ies;
6408}
6409
6410
6411static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6412 const u8 *buf, size_t size)
6413{
6414 struct wpa_supplicant *wpa_s = ctx;
6415 struct mb_ies_info info;
6416
Sunil Ravieb83e2a2024-06-28 17:34:56 +00006417 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006418
6419 if (!mb_ies_info_by_ies(&info, buf, size)) {
6420 wpabuf_free(wpa_s->received_mb_ies);
6421 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6422 }
6423}
6424
6425
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006426static const u8 * wpas_fst_get_peer_first(void *ctx,
6427 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006428 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006429{
6430 struct wpa_supplicant *wpa_s = ctx;
6431
6432 *get_ctx = NULL;
6433 if (!is_zero_ether_addr(wpa_s->bssid))
6434 return (wpa_s->received_mb_ies || !mb_only) ?
6435 wpa_s->bssid : NULL;
6436 return NULL;
6437}
6438
6439
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006440static const u8 * wpas_fst_get_peer_next(void *ctx,
6441 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006442 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006443{
6444 return NULL;
6445}
6446
6447void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6448 struct fst_wpa_obj *iface_obj)
6449{
Sunil8cd6f4d2022-06-28 18:40:46 +00006450 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006451 iface_obj->ctx = wpa_s;
6452 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6453 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6454 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6455 iface_obj->set_ies = wpas_fst_set_ies_cb;
6456 iface_obj->send_action = wpas_fst_send_action_cb;
6457 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6458 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6459 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6460 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6461}
6462#endif /* CONFIG_FST */
6463
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006464static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006465 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006466{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006467 struct wowlan_triggers *triggers;
6468 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006469
6470 if (!wpa_s->conf->wowlan_triggers)
6471 return 0;
6472
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006473 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6474 if (triggers) {
6475 ret = wpa_drv_wowlan(wpa_s, triggers);
6476 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006477 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006478 return ret;
6479}
6480
6481
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006482enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006483{
6484 if (freq < 3000)
6485 return BAND_2_4_GHZ;
6486 if (freq > 50000)
6487 return BAND_60_GHZ;
6488 return BAND_5_GHZ;
6489}
6490
6491
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006492unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006493{
6494 int i;
6495 unsigned int band = 0;
6496
6497 if (freqs) {
6498 /* freqs are specified for the radio work */
6499 for (i = 0; freqs[i]; i++)
6500 band |= wpas_freq_to_band(freqs[i]);
6501 } else {
6502 /*
6503 * freqs are not specified, implies all
6504 * the supported freqs by HW
6505 */
6506 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6507 if (wpa_s->hw.modes[i].num_channels != 0) {
6508 if (wpa_s->hw.modes[i].mode ==
6509 HOSTAPD_MODE_IEEE80211B ||
6510 wpa_s->hw.modes[i].mode ==
6511 HOSTAPD_MODE_IEEE80211G)
6512 band |= BAND_2_4_GHZ;
6513 else if (wpa_s->hw.modes[i].mode ==
6514 HOSTAPD_MODE_IEEE80211A)
6515 band |= BAND_5_GHZ;
6516 else if (wpa_s->hw.modes[i].mode ==
6517 HOSTAPD_MODE_IEEE80211AD)
6518 band |= BAND_60_GHZ;
6519 else if (wpa_s->hw.modes[i].mode ==
6520 HOSTAPD_MODE_IEEE80211ANY)
6521 band = BAND_2_4_GHZ | BAND_5_GHZ |
6522 BAND_60_GHZ;
6523 }
6524 }
6525 }
6526
6527 return band;
6528}
6529
6530
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006531static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6532 const char *rn)
6533{
6534 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6535 struct wpa_radio *radio;
6536
6537 while (rn && iface) {
6538 radio = iface->radio;
6539 if (radio && os_strcmp(rn, radio->name) == 0) {
6540 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6541 wpa_s->ifname, rn);
6542 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6543 return radio;
6544 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006545
6546 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006547 }
6548
6549 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6550 wpa_s->ifname, rn ? rn : "N/A");
6551 radio = os_zalloc(sizeof(*radio));
6552 if (radio == NULL)
6553 return NULL;
6554
6555 if (rn)
6556 os_strlcpy(radio->name, rn, sizeof(radio->name));
6557 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006558 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006559 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6560
6561 return radio;
6562}
6563
6564
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006565static void radio_work_free(struct wpa_radio_work *work)
6566{
6567 if (work->wpa_s->scan_work == work) {
6568 /* This should not really happen. */
6569 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6570 work->type, work, work->started);
6571 work->wpa_s->scan_work = NULL;
6572 }
6573
6574#ifdef CONFIG_P2P
6575 if (work->wpa_s->p2p_scan_work == work) {
6576 /* This should not really happen. */
6577 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6578 work->type, work, work->started);
6579 work->wpa_s->p2p_scan_work = NULL;
6580 }
6581#endif /* CONFIG_P2P */
6582
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006583 if (work->started) {
6584 work->wpa_s->radio->num_active_works--;
6585 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006586 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006587 work->type, work,
6588 work->wpa_s->radio->num_active_works);
6589 }
6590
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006591 dl_list_del(&work->list);
6592 os_free(work);
6593}
6594
6595
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006596static int radio_work_is_connect(struct wpa_radio_work *work)
6597{
6598 return os_strcmp(work->type, "sme-connect") == 0 ||
6599 os_strcmp(work->type, "connect") == 0;
6600}
6601
6602
6603static int radio_work_is_scan(struct wpa_radio_work *work)
6604{
6605 return os_strcmp(work->type, "scan") == 0 ||
6606 os_strcmp(work->type, "p2p-scan") == 0;
6607}
6608
6609
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006610static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6611{
6612 struct wpa_radio_work *active_work = NULL;
6613 struct wpa_radio_work *tmp;
6614
6615 /* Get the active work to know the type and band. */
6616 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6617 if (tmp->started) {
6618 active_work = tmp;
6619 break;
6620 }
6621 }
6622
6623 if (!active_work) {
6624 /* No active work, start one */
6625 radio->num_active_works = 0;
6626 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6627 list) {
6628 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006629 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006630 (((struct wpa_driver_scan_params *)
6631 tmp->ctx)->only_new_results ||
6632 tmp->wpa_s->clear_driver_scan_cache))
6633 continue;
6634 return tmp;
6635 }
6636 return NULL;
6637 }
6638
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006639 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006640 /*
6641 * If the active work is either connect or sme-connect,
6642 * do not parallelize them with other radio works.
6643 */
6644 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6645 "Do not parallelize radio work with %s",
6646 active_work->type);
6647 return NULL;
6648 }
6649
6650 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6651 if (tmp->started)
6652 continue;
6653
6654 /*
6655 * If connect or sme-connect are enqueued, parallelize only
6656 * those operations ahead of them in the queue.
6657 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006658 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006659 break;
6660
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006661 /* Serialize parallel scan and p2p_scan operations on the same
6662 * interface since the driver_nl80211 mechanism for tracking
6663 * scan cookies does not yet have support for this. */
6664 if (active_work->wpa_s == tmp->wpa_s &&
6665 radio_work_is_scan(active_work) &&
6666 radio_work_is_scan(tmp)) {
6667 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6668 "Do not start work '%s' when another work '%s' is already scheduled",
6669 tmp->type, active_work->type);
6670 continue;
6671 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006672 /*
6673 * Check that the radio works are distinct and
6674 * on different bands.
6675 */
6676 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6677 (active_work->bands != tmp->bands)) {
6678 /*
6679 * If a scan has to be scheduled through nl80211 scan
6680 * interface and if an external scan is already running,
6681 * do not schedule the scan since it is likely to get
6682 * rejected by kernel.
6683 */
6684 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006685 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006686 (((struct wpa_driver_scan_params *)
6687 tmp->ctx)->only_new_results ||
6688 tmp->wpa_s->clear_driver_scan_cache))
6689 continue;
6690
6691 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6692 "active_work:%s new_work:%s",
6693 active_work->type, tmp->type);
6694 return tmp;
6695 }
6696 }
6697
6698 /* Did not find a radio work to schedule in parallel. */
6699 return NULL;
6700}
6701
6702
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006703static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6704{
6705 struct wpa_radio *radio = eloop_ctx;
6706 struct wpa_radio_work *work;
6707 struct os_reltime now, diff;
6708 struct wpa_supplicant *wpa_s;
6709
6710 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006711 if (work == NULL) {
6712 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006713 return;
6714 }
6715
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006716 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6717 radio_list);
6718
6719 if (!(wpa_s &&
6720 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6721 if (work->started)
6722 return; /* already started and still in progress */
6723
Hai Shalom60840252021-02-19 19:02:11 -08006724 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006725 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6726 return;
6727 }
6728 } else {
6729 work = NULL;
6730 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6731 /* get the work to schedule next */
6732 work = radio_work_get_next_work(radio);
6733 }
6734 if (!work)
6735 return;
6736 }
6737
6738 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006739 os_get_reltime(&now);
6740 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006741 wpa_dbg(wpa_s, MSG_DEBUG,
6742 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006743 work->type, work, diff.sec, diff.usec);
6744 work->started = 1;
6745 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006746 radio->num_active_works++;
6747
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006748 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006749
6750 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6751 radio->num_active_works < MAX_ACTIVE_WORKS)
6752 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006753}
6754
6755
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006756/*
6757 * This function removes both started and pending radio works running on
6758 * the provided interface's radio.
6759 * Prior to the removal of the radio work, its callback (cb) is called with
6760 * deinit set to be 1. Each work's callback is responsible for clearing its
6761 * internal data and restoring to a correct state.
6762 * @wpa_s: wpa_supplicant data
6763 * @type: type of works to be removed
6764 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6765 * this interface's works.
6766 */
6767void radio_remove_works(struct wpa_supplicant *wpa_s,
6768 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006769{
6770 struct wpa_radio_work *work, *tmp;
6771 struct wpa_radio *radio = wpa_s->radio;
6772
6773 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6774 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006775 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006776 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006777
6778 /* skip other ifaces' works */
6779 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006780 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006781
6782 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6783 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006784 work->cb(work, 1);
6785 radio_work_free(work);
6786 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006787
6788 /* in case we removed the started work */
6789 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006790}
6791
6792
Roshan Pius3a1667e2018-07-03 15:17:14 -07006793void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6794{
6795 struct wpa_radio_work *work;
6796 struct wpa_radio *radio = wpa_s->radio;
6797
6798 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6799 if (work->ctx != ctx)
6800 continue;
6801 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6802 work->type, work, work->started ? " (started)" : "");
6803 radio_work_free(work);
6804 break;
6805 }
6806}
6807
6808
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006809static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6810{
6811 struct wpa_radio *radio = wpa_s->radio;
6812
6813 if (!radio)
6814 return;
6815
6816 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6817 wpa_s->ifname, radio->name);
6818 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006819 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006820 /* If the interface that triggered the external scan was removed, the
6821 * external scan is no longer running. */
6822 if (wpa_s == radio->external_scan_req_interface)
6823 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006824 wpa_s->radio = NULL;
6825 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006826 return; /* Interfaces remain for this radio */
6827
6828 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006829 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006830 os_free(radio);
6831}
6832
6833
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006834void radio_work_check_next(struct wpa_supplicant *wpa_s)
6835{
6836 struct wpa_radio *radio = wpa_s->radio;
6837
6838 if (dl_list_empty(&radio->work))
6839 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006840 if (wpa_s->ext_work_in_progress) {
6841 wpa_printf(MSG_DEBUG,
6842 "External radio work in progress - delay start of pending item");
6843 return;
6844 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006845 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6846 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6847}
6848
6849
6850/**
6851 * radio_add_work - Add a radio work item
6852 * @wpa_s: Pointer to wpa_supplicant data
6853 * @freq: Frequency of the offchannel operation in MHz or 0
6854 * @type: Unique identifier for each type of work
6855 * @next: Force as the next work to be executed
6856 * @cb: Callback function for indicating when radio is available
6857 * @ctx: Context pointer for the work (work->ctx in cb())
6858 * Returns: 0 on success, -1 on failure
6859 *
6860 * This function is used to request time for an operation that requires
6861 * exclusive radio control. Once the radio is available, the registered callback
6862 * function will be called. radio_work_done() must be called once the exclusive
6863 * radio operation has been completed, so that the radio is freed for other
6864 * operations. The special case of deinit=1 is used to free the context data
6865 * during interface removal. That does not allow the callback function to start
6866 * the radio operation, i.e., it must free any resources allocated for the radio
6867 * work and return.
6868 *
6869 * The @freq parameter can be used to indicate a single channel on which the
6870 * offchannel operation will occur. This may allow multiple radio work
6871 * operations to be performed in parallel if they apply for the same channel.
6872 * Setting this to 0 indicates that the work item may use multiple channels or
6873 * requires exclusive control of the radio.
6874 */
6875int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6876 const char *type, int next,
6877 void (*cb)(struct wpa_radio_work *work, int deinit),
6878 void *ctx)
6879{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006880 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006881 struct wpa_radio_work *work;
6882 int was_empty;
6883
6884 work = os_zalloc(sizeof(*work));
6885 if (work == NULL)
6886 return -1;
6887 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6888 os_get_reltime(&work->time);
6889 work->freq = freq;
6890 work->type = type;
6891 work->wpa_s = wpa_s;
6892 work->cb = cb;
6893 work->ctx = ctx;
6894
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006895 if (freq)
6896 work->bands = wpas_freq_to_band(freq);
6897 else if (os_strcmp(type, "scan") == 0 ||
6898 os_strcmp(type, "p2p-scan") == 0)
6899 work->bands = wpas_get_bands(wpa_s,
6900 ((struct wpa_driver_scan_params *)
6901 ctx)->freqs);
6902 else
6903 work->bands = wpas_get_bands(wpa_s, NULL);
6904
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006905 was_empty = dl_list_empty(&wpa_s->radio->work);
6906 if (next)
6907 dl_list_add(&wpa_s->radio->work, &work->list);
6908 else
6909 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6910 if (was_empty) {
6911 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6912 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006913 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6914 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6915 wpa_dbg(wpa_s, MSG_DEBUG,
6916 "Try to schedule a radio work (num_active_works=%u)",
6917 radio->num_active_works);
6918 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006919 }
6920
6921 return 0;
6922}
6923
6924
6925/**
6926 * radio_work_done - Indicate that a radio work item has been completed
6927 * @work: Completed work
6928 *
6929 * This function is called once the callback function registered with
6930 * radio_add_work() has completed its work.
6931 */
6932void radio_work_done(struct wpa_radio_work *work)
6933{
6934 struct wpa_supplicant *wpa_s = work->wpa_s;
6935 struct os_reltime now, diff;
6936 unsigned int started = work->started;
6937
6938 os_get_reltime(&now);
6939 os_reltime_sub(&now, &work->time, &diff);
6940 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6941 work->type, work, started ? "done" : "canceled",
6942 diff.sec, diff.usec);
6943 radio_work_free(work);
6944 if (started)
6945 radio_work_check_next(wpa_s);
6946}
6947
6948
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006949struct wpa_radio_work *
6950radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006951{
6952 struct wpa_radio_work *work;
6953 struct wpa_radio *radio = wpa_s->radio;
6954
6955 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6956 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006957 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006958 }
6959
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006960 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006961}
6962
6963
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006964static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006965 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006966{
6967 const char *ifname, *driver, *rn;
6968
6969 driver = iface->driver;
6970next_driver:
6971 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6972 return -1;
6973
6974 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6975 if (wpa_s->drv_priv == NULL) {
6976 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006977 int level = MSG_ERROR;
6978
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006979 pos = driver ? os_strchr(driver, ',') : NULL;
6980 if (pos) {
6981 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6982 "driver interface - try next driver wrapper");
6983 driver = pos + 1;
6984 goto next_driver;
6985 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006986
6987#ifdef CONFIG_MATCH_IFACE
6988 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6989 level = MSG_DEBUG;
6990#endif /* CONFIG_MATCH_IFACE */
6991 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006992 return -1;
6993 }
6994 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6995 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6996 "driver_param '%s'", wpa_s->conf->driver_param);
6997 return -1;
6998 }
6999
7000 ifname = wpa_drv_get_ifname(wpa_s);
7001 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7002 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7003 "interface name with '%s'", ifname);
7004 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7005 }
7006
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007007 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007008 if (rn && rn[0] == '\0')
7009 rn = NULL;
7010
7011 wpa_s->radio = radio_add_interface(wpa_s, rn);
7012 if (wpa_s->radio == NULL)
7013 return -1;
7014
7015 return 0;
7016}
7017
7018
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007019#ifdef CONFIG_GAS_SERVER
7020
7021static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7022 unsigned int freq, const u8 *dst,
7023 const u8 *src, const u8 *bssid,
7024 const u8 *data, size_t data_len,
7025 enum offchannel_send_action_result result)
7026{
7027 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7028 " result=%s",
7029 freq, MAC2STR(dst),
7030 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7031 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7032 "FAILED"));
7033 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7034 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7035}
7036
7037
7038static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7039 struct wpabuf *buf, unsigned int wait_time)
7040{
7041 struct wpa_supplicant *wpa_s = ctx;
7042 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7043
7044 if (wait_time > wpa_s->max_remain_on_chan)
7045 wait_time = wpa_s->max_remain_on_chan;
7046
7047 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7048 wpabuf_head(buf), wpabuf_len(buf),
7049 wait_time, wpas_gas_server_tx_status, 0);
7050}
7051
7052#endif /* CONFIG_GAS_SERVER */
7053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007054static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007055 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007056{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007057 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007058 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007059 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007060
7061 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7062 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7063 iface->confname ? iface->confname : "N/A",
7064 iface->driver ? iface->driver : "default",
7065 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7066 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7067
7068 if (iface->confname) {
7069#ifdef CONFIG_BACKEND_FILE
7070 wpa_s->confname = os_rel2abs_path(iface->confname);
7071 if (wpa_s->confname == NULL) {
7072 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7073 "for configuration file '%s'.",
7074 iface->confname);
7075 return -1;
7076 }
7077 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7078 iface->confname, wpa_s->confname);
7079#else /* CONFIG_BACKEND_FILE */
7080 wpa_s->confname = os_strdup(iface->confname);
7081#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007082 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007083 if (wpa_s->conf == NULL) {
7084 wpa_printf(MSG_ERROR, "Failed to read or parse "
7085 "configuration '%s'.", wpa_s->confname);
7086 return -1;
7087 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007088 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007089 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007090 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007091 wpa_printf(MSG_ERROR,
7092 "Failed to read or parse configuration '%s'.",
7093 wpa_s->confanother);
7094 return -1;
7095 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007096
7097 /*
7098 * Override ctrl_interface and driver_param if set on command
7099 * line.
7100 */
7101 if (iface->ctrl_interface) {
7102 os_free(wpa_s->conf->ctrl_interface);
7103 wpa_s->conf->ctrl_interface =
7104 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007105 if (!wpa_s->conf->ctrl_interface) {
7106 wpa_printf(MSG_ERROR,
7107 "Failed to duplicate control interface '%s'.",
7108 iface->ctrl_interface);
7109 return -1;
7110 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007111 }
7112
7113 if (iface->driver_param) {
7114 os_free(wpa_s->conf->driver_param);
7115 wpa_s->conf->driver_param =
7116 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007117 if (!wpa_s->conf->driver_param) {
7118 wpa_printf(MSG_ERROR,
7119 "Failed to duplicate driver param '%s'.",
7120 iface->driver_param);
7121 return -1;
7122 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007123 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007124
7125 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7126 os_free(wpa_s->conf->ctrl_interface);
7127 wpa_s->conf->ctrl_interface = NULL;
7128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129 } else
7130 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7131 iface->driver_param);
7132
7133 if (wpa_s->conf == NULL) {
7134 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7135 return -1;
7136 }
7137
7138 if (iface->ifname == NULL) {
7139 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7140 return -1;
7141 }
7142 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7143 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7144 iface->ifname);
7145 return -1;
7146 }
7147 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007148#ifdef CONFIG_MATCH_IFACE
7149 wpa_s->matched = iface->matched;
7150#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007151
7152 if (iface->bridge_ifname) {
7153 if (os_strlen(iface->bridge_ifname) >=
7154 sizeof(wpa_s->bridge_ifname)) {
7155 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7156 "name '%s'.", iface->bridge_ifname);
7157 return -1;
7158 }
7159 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7160 sizeof(wpa_s->bridge_ifname));
7161 }
7162
7163 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007164 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7165 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007166
7167 /* Initialize driver interface and register driver event handler before
7168 * L2 receive handler so that association events are processed before
7169 * EAPOL-Key packets if both become available for the same select()
7170 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007171 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007172 return -1;
7173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007174 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7175 return -1;
7176
7177 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7178 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7179 NULL);
7180 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7181
7182 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7183 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7184 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7185 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7186 "dot11RSNAConfigPMKLifetime");
7187 return -1;
7188 }
7189
7190 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7191 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7192 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7193 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7194 "dot11RSNAConfigPMKReauthThreshold");
7195 return -1;
7196 }
7197
7198 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7199 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7200 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7201 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7202 "dot11RSNAConfigSATimeout");
7203 return -1;
7204 }
7205
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007206 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7207 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007208 &wpa_s->hw.flags,
7209 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007210 if (wpa_s->hw.modes) {
7211 u16 i;
7212
7213 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7214 if (wpa_s->hw.modes[i].vht_capab) {
7215 wpa_s->hw_capab = CAPAB_VHT;
7216 break;
7217 }
7218
7219 if (wpa_s->hw.modes[i].ht_capab &
7220 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7221 wpa_s->hw_capab = CAPAB_HT40;
7222 else if (wpa_s->hw.modes[i].ht_capab &&
7223 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7224 wpa_s->hw_capab = CAPAB_HT;
7225 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007226 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007227 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007228
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007229 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7230 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007231 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007232 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007233 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007234 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007235 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007236 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007237 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007238 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007239 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007240 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7241 wpa_s->max_sched_scan_plan_interval =
7242 capa.max_sched_scan_plan_interval;
7243 wpa_s->max_sched_scan_plan_iterations =
7244 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007245 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7246 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007247 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7248 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007249 wpa_s->extended_capa = capa.extended_capa;
7250 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7251 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007252 wpa_s->num_multichan_concurrent =
7253 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007254 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007255 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007256
7257 if (capa.mac_addr_rand_scan_supported)
7258 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7259 if (wpa_s->sched_scan_supported &&
7260 capa.mac_addr_rand_sched_scan_supported)
7261 wpa_s->mac_addr_rand_supported |=
7262 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007263
7264 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7265 if (wpa_s->extended_capa &&
7266 wpa_s->extended_capa_len >= 3 &&
7267 wpa_s->extended_capa[2] & 0x40)
7268 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007269 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007270#ifdef CONFIG_PASN
7271 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7272#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007273 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7274 !!(wpa_s->drv_flags &
7275 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007276 if (wpa_s->max_remain_on_chan == 0)
7277 wpa_s->max_remain_on_chan = 1000;
7278
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007279 /*
7280 * Only take p2p_mgmt parameters when P2P Device is supported.
7281 * Doing it here as it determines whether l2_packet_init() will be done
7282 * during wpa_supplicant_driver_init().
7283 */
7284 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7285 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007286
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007287 if (wpa_s->num_multichan_concurrent == 0)
7288 wpa_s->num_multichan_concurrent = 1;
7289
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007290 if (wpa_supplicant_driver_init(wpa_s) < 0)
7291 return -1;
7292
7293#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007294 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295 return -1;
7296#endif /* CONFIG_TDLS */
7297
7298 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7299 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7300 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7301 return -1;
7302 }
7303
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007304#ifdef CONFIG_FST
7305 if (wpa_s->conf->fst_group_id) {
7306 struct fst_iface_cfg cfg;
7307 struct fst_wpa_obj iface_obj;
7308
7309 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7310 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7311 sizeof(cfg.group_id));
7312 cfg.priority = wpa_s->conf->fst_priority;
7313 cfg.llt = wpa_s->conf->fst_llt;
7314
7315 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7316 &iface_obj, &cfg);
7317 if (!wpa_s->fst) {
7318 wpa_msg(wpa_s, MSG_ERROR,
7319 "FST: Cannot attach iface %s to group %s",
7320 wpa_s->ifname, cfg.group_id);
7321 return -1;
7322 }
7323 }
7324#endif /* CONFIG_FST */
7325
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007326 if (wpas_wps_init(wpa_s))
7327 return -1;
7328
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007329#ifdef CONFIG_GAS_SERVER
7330 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7331 if (!wpa_s->gas_server) {
7332 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7333 return -1;
7334 }
7335#endif /* CONFIG_GAS_SERVER */
7336
7337#ifdef CONFIG_DPP
7338 if (wpas_dpp_init(wpa_s) < 0)
7339 return -1;
7340#endif /* CONFIG_DPP */
7341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007342 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7343 return -1;
7344 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7345
7346 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7347 if (wpa_s->ctrl_iface == NULL) {
7348 wpa_printf(MSG_ERROR,
7349 "Failed to initialize control interface '%s'.\n"
7350 "You may have another wpa_supplicant process "
7351 "already running or the file was\n"
7352 "left by an unclean termination of wpa_supplicant "
7353 "in which case you will need\n"
7354 "to manually remove this file before starting "
7355 "wpa_supplicant again.\n",
7356 wpa_s->conf->ctrl_interface);
7357 return -1;
7358 }
7359
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007360 wpa_s->gas = gas_query_init(wpa_s);
7361 if (wpa_s->gas == NULL) {
7362 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7363 return -1;
7364 }
7365
Roshan Pius3a1667e2018-07-03 15:17:14 -07007366 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7367 wpa_s->p2p_mgmt) &&
7368 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007369 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7370 return -1;
7371 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007372
7373 if (wpa_bss_init(wpa_s) < 0)
7374 return -1;
7375
Paul Stewart092955c2017-02-06 09:13:09 -08007376#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7377#ifdef CONFIG_MESH
7378 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7379#endif /* CONFIG_MESH */
7380#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7381
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007382 /*
7383 * Set Wake-on-WLAN triggers, if configured.
7384 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7385 * have effect anyway when the interface is down).
7386 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007387 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007388 return -1;
7389
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007390#ifdef CONFIG_EAP_PROXY
7391{
7392 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007393 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7394 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007395 if (wpa_s->mnc_len > 0) {
7396 wpa_s->imsi[len] = '\0';
7397 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7398 wpa_s->imsi, wpa_s->mnc_len);
7399 } else {
7400 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7401 }
7402}
7403#endif /* CONFIG_EAP_PROXY */
7404
Dmitry Shmidt04949592012-07-19 12:16:46 -07007405 if (pcsc_reader_init(wpa_s) < 0)
7406 return -1;
7407
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007408 if (wpas_init_ext_pw(wpa_s) < 0)
7409 return -1;
7410
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007411 wpas_rrm_reset(wpa_s);
7412
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007413 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7414
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007415#ifdef CONFIG_HS20
7416 hs20_init(wpa_s);
7417#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007418#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007419 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007420 if ((wpa_s->conf->oce & OCE_STA) &&
7421 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7422 wpa_s->enable_oce = OCE_STA;
7423 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7424 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7425 /* TODO: Need to add STA-CFON support */
7426 wpa_printf(MSG_ERROR,
7427 "OCE STA-CFON feature is not yet supported");
7428 }
7429 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007430 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7431#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007432
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007433 wpa_supplicant_set_default_scan_ies(wpa_s);
7434
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007435 return 0;
7436}
7437
7438
7439static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007440 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007441{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007442 struct wpa_global *global = wpa_s->global;
7443 struct wpa_supplicant *iface, *prev;
7444
Jimmy Chen0e73c002021-08-18 13:21:30 +08007445 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007446 wpas_p2p_group_remove(wpa_s, "*");
7447
7448 iface = global->ifaces;
7449 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007450 if (iface->p2pdev == wpa_s)
7451 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007452 if (iface == wpa_s || iface->parent != wpa_s) {
7453 iface = iface->next;
7454 continue;
7455 }
7456 wpa_printf(MSG_DEBUG,
7457 "Remove remaining child interface %s from parent %s",
7458 iface->ifname, wpa_s->ifname);
7459 prev = iface;
7460 iface = iface->next;
7461 wpa_supplicant_remove_iface(global, prev, terminate);
7462 }
7463
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007464 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007465 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007466 /*
7467 * Don't deauthenticate if WoWLAN is enable and not explicitly
7468 * been configured to disconnect.
7469 */
7470 if (!wpa_drv_get_wowlan(wpa_s) ||
7471 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007472 wpa_supplicant_deauthenticate(
7473 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007474
Hai Shalomfdcde762020-04-02 11:19:20 -07007475 wpa_drv_set_countermeasures(wpa_s, 0);
7476 wpa_clear_keys(wpa_s, NULL);
7477 } else {
7478 wpa_msg(wpa_s, MSG_INFO,
7479 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7480 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481 }
7482
7483 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007484 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007485
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007486 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007487 radio_remove_interface(wpa_s);
7488
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007489#ifdef CONFIG_FST
7490 if (wpa_s->fst) {
7491 fst_detach(wpa_s->fst);
7492 wpa_s->fst = NULL;
7493 }
7494 if (wpa_s->received_mb_ies) {
7495 wpabuf_free(wpa_s->received_mb_ies);
7496 wpa_s->received_mb_ies = NULL;
7497 }
7498#endif /* CONFIG_FST */
7499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007500 if (wpa_s->drv_priv)
7501 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007502
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007503 if (notify)
7504 wpas_notify_iface_removed(wpa_s);
7505
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007506 if (terminate)
7507 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007508
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007509 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7510 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007511
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007512#ifdef CONFIG_MESH
7513 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007514 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007515 wpa_s->ifmsh = NULL;
7516 }
7517#endif /* CONFIG_MESH */
7518
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007519 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007520 wpa_config_free(wpa_s->conf);
7521 wpa_s->conf = NULL;
7522 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007523
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007524 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007525 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007526
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007527 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007528}
7529
7530
Dmitry Shmidte4663042016-04-04 10:07:49 -07007531#ifdef CONFIG_MATCH_IFACE
7532
7533/**
7534 * wpa_supplicant_match_iface - Match an interface description to a name
7535 * @global: Pointer to global data from wpa_supplicant_init()
7536 * @ifname: Name of the interface to match
7537 * Returns: Pointer to the created interface description or %NULL on failure
7538 */
7539struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7540 const char *ifname)
7541{
7542 int i;
7543 struct wpa_interface *iface, *miface;
7544
7545 for (i = 0; i < global->params.match_iface_count; i++) {
7546 miface = &global->params.match_ifaces[i];
7547 if (!miface->ifname ||
7548 fnmatch(miface->ifname, ifname, 0) == 0) {
7549 iface = os_zalloc(sizeof(*iface));
7550 if (!iface)
7551 return NULL;
7552 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007553 if (!miface->ifname)
7554 iface->matched = WPA_IFACE_MATCHED_NULL;
7555 else
7556 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007557 iface->ifname = ifname;
7558 return iface;
7559 }
7560 }
7561
7562 return NULL;
7563}
7564
7565
7566/**
7567 * wpa_supplicant_match_existing - Match existing interfaces
7568 * @global: Pointer to global data from wpa_supplicant_init()
7569 * Returns: 0 on success, -1 on failure
7570 */
7571static int wpa_supplicant_match_existing(struct wpa_global *global)
7572{
7573 struct if_nameindex *ifi, *ifp;
7574 struct wpa_supplicant *wpa_s;
7575 struct wpa_interface *iface;
7576
7577 ifp = if_nameindex();
7578 if (!ifp) {
7579 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7580 return -1;
7581 }
7582
7583 for (ifi = ifp; ifi->if_name; ifi++) {
7584 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7585 if (wpa_s)
7586 continue;
7587 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7588 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007589 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007590 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007591 }
7592 }
7593
7594 if_freenameindex(ifp);
7595 return 0;
7596}
7597
7598#endif /* CONFIG_MATCH_IFACE */
7599
7600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007601/**
7602 * wpa_supplicant_add_iface - Add a new network interface
7603 * @global: Pointer to global data from wpa_supplicant_init()
7604 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007605 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007606 * Returns: Pointer to the created interface or %NULL on failure
7607 *
7608 * This function is used to add new network interfaces for %wpa_supplicant.
7609 * This can be called before wpa_supplicant_run() to add interfaces before the
7610 * main event loop has been started. In addition, new interfaces can be added
7611 * dynamically while %wpa_supplicant is already running. This could happen,
7612 * e.g., when a hotplug network adapter is inserted.
7613 */
7614struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007615 struct wpa_interface *iface,
7616 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007617{
7618 struct wpa_supplicant *wpa_s;
7619 struct wpa_interface t_iface;
7620 struct wpa_ssid *ssid;
7621
7622 if (global == NULL || iface == NULL)
7623 return NULL;
7624
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007625 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007626 if (wpa_s == NULL)
7627 return NULL;
7628
7629 wpa_s->global = global;
7630
7631 t_iface = *iface;
7632 if (global->params.override_driver) {
7633 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7634 "('%s' -> '%s')",
7635 iface->driver, global->params.override_driver);
7636 t_iface.driver = global->params.override_driver;
7637 }
7638 if (global->params.override_ctrl_interface) {
7639 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7640 "ctrl_interface ('%s' -> '%s')",
7641 iface->ctrl_interface,
7642 global->params.override_ctrl_interface);
7643 t_iface.ctrl_interface =
7644 global->params.override_ctrl_interface;
7645 }
7646 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7647 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7648 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007649 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007650 return NULL;
7651 }
7652
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007653 /* Notify the control interfaces about new iface */
7654 if (wpas_notify_iface_added(wpa_s)) {
7655 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7656 return NULL;
7657 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007658
Jimmy Chene2206be2022-07-10 10:25:21 +08007659 /* Notify the control interfaces about new networks */
7660 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7661 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007662 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007663 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7664 && os_strncmp((const char *) ssid->ssid,
7665 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7666 wpas_notify_persistent_group_added(wpa_s, ssid);
7667 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007668 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007669
7670 wpa_s->next = global->ifaces;
7671 global->ifaces = wpa_s;
7672
7673 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007674 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007675
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007676#ifdef CONFIG_P2P
7677 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007678 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007679 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007680 wpas_p2p_add_p2pdev_interface(
7681 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007682 wpa_printf(MSG_INFO,
7683 "P2P: Failed to enable P2P Device interface");
7684 /* Try to continue without. P2P will be disabled. */
7685 }
7686#endif /* CONFIG_P2P */
7687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007688 return wpa_s;
7689}
7690
7691
7692/**
7693 * wpa_supplicant_remove_iface - Remove a network interface
7694 * @global: Pointer to global data from wpa_supplicant_init()
7695 * @wpa_s: Pointer to the network interface to be removed
7696 * Returns: 0 if interface was removed, -1 if interface was not found
7697 *
7698 * This function can be used to dynamically remove network interfaces from
7699 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7700 * addition, this function is used to remove all remaining interfaces when
7701 * %wpa_supplicant is terminated.
7702 */
7703int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007704 struct wpa_supplicant *wpa_s,
7705 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007706{
7707 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007708#ifdef CONFIG_MESH
7709 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7710 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007711 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007712#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007713
7714 /* Remove interface from the global list of interfaces */
7715 prev = global->ifaces;
7716 if (prev == wpa_s) {
7717 global->ifaces = wpa_s->next;
7718 } else {
7719 while (prev && prev->next != wpa_s)
7720 prev = prev->next;
7721 if (prev == NULL)
7722 return -1;
7723 prev->next = wpa_s->next;
7724 }
7725
7726 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7727
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007728#ifdef CONFIG_MESH
7729 if (mesh_if_created) {
7730 ifname = os_strdup(wpa_s->ifname);
7731 if (ifname == NULL) {
7732 wpa_dbg(wpa_s, MSG_ERROR,
7733 "mesh: Failed to malloc ifname");
7734 return -1;
7735 }
7736 }
7737#endif /* CONFIG_MESH */
7738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007739 if (global->p2p_group_formation == wpa_s)
7740 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007741 if (global->p2p_invite_group == wpa_s)
7742 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007743 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007744
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007745#ifdef CONFIG_MESH
7746 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007747 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007748 os_free(ifname);
7749 }
7750#endif /* CONFIG_MESH */
7751
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007752 return 0;
7753}
7754
7755
7756/**
7757 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7758 * @wpa_s: Pointer to the network interface
7759 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7760 */
7761const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7762{
7763 const char *eapol_method;
7764
7765 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7766 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7767 return "NO-EAP";
7768 }
7769
7770 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7771 if (eapol_method == NULL)
7772 return "UNKNOWN-EAP";
7773
7774 return eapol_method;
7775}
7776
7777
7778/**
7779 * wpa_supplicant_get_iface - Get a new network interface
7780 * @global: Pointer to global data from wpa_supplicant_init()
7781 * @ifname: Interface name
7782 * Returns: Pointer to the interface or %NULL if not found
7783 */
7784struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7785 const char *ifname)
7786{
7787 struct wpa_supplicant *wpa_s;
7788
7789 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7790 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7791 return wpa_s;
7792 }
7793 return NULL;
7794}
7795
7796
7797#ifndef CONFIG_NO_WPA_MSG
7798static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7799{
7800 struct wpa_supplicant *wpa_s = ctx;
7801 if (wpa_s == NULL)
7802 return NULL;
7803 return wpa_s->ifname;
7804}
7805#endif /* CONFIG_NO_WPA_MSG */
7806
7807
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007808#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7809#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7810#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7811
7812/* Periodic cleanup tasks */
7813static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7814{
7815 struct wpa_global *global = eloop_ctx;
7816 struct wpa_supplicant *wpa_s;
7817
7818 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7819 wpas_periodic, global, NULL);
7820
7821#ifdef CONFIG_P2P
7822 if (global->p2p)
7823 p2p_expire_peers(global->p2p);
7824#endif /* CONFIG_P2P */
7825
7826 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7827 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7828#ifdef CONFIG_AP
7829 ap_periodic(wpa_s);
7830#endif /* CONFIG_AP */
7831 }
7832}
7833
7834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007835/**
7836 * wpa_supplicant_init - Initialize %wpa_supplicant
7837 * @params: Parameters for %wpa_supplicant
7838 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7839 *
7840 * This function is used to initialize %wpa_supplicant. After successful
7841 * initialization, the returned data pointer can be used to add and remove
7842 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7843 */
7844struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7845{
7846 struct wpa_global *global;
7847 int ret, i;
7848
7849 if (params == NULL)
7850 return NULL;
7851
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007852#ifdef CONFIG_DRIVER_NDIS
7853 {
7854 void driver_ndis_init_ops(void);
7855 driver_ndis_init_ops();
7856 }
7857#endif /* CONFIG_DRIVER_NDIS */
7858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007859#ifndef CONFIG_NO_WPA_MSG
7860 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7861#endif /* CONFIG_NO_WPA_MSG */
7862
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007863 if (params->wpa_debug_file_path)
7864 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007865 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007866 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007867 if (params->wpa_debug_syslog)
7868 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007869 if (params->wpa_debug_tracing) {
7870 ret = wpa_debug_open_linux_tracing();
7871 if (ret) {
7872 wpa_printf(MSG_ERROR,
7873 "Failed to enable trace logging");
7874 return NULL;
7875 }
7876 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007877
7878 ret = eap_register_methods();
7879 if (ret) {
7880 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7881 if (ret == -2)
7882 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7883 "the same EAP type.");
7884 return NULL;
7885 }
7886
7887 global = os_zalloc(sizeof(*global));
7888 if (global == NULL)
7889 return NULL;
7890 dl_list_init(&global->p2p_srv_bonjour);
7891 dl_list_init(&global->p2p_srv_upnp);
7892 global->params.daemonize = params->daemonize;
7893 global->params.wait_for_monitor = params->wait_for_monitor;
7894 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007895
7896 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007897 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007898 if (!global->params.pid_file) {
7899 wpa_supplicant_deinit(global);
7900 return NULL;
7901 }
7902 }
7903
7904 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007905 global->params.ctrl_interface =
7906 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007907 if (!global->params.ctrl_interface) {
7908 wpa_supplicant_deinit(global);
7909 return NULL;
7910 }
7911 }
7912
7913 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007914 global->params.ctrl_interface_group =
7915 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007916 if (!global->params.ctrl_interface_group) {
7917 wpa_supplicant_deinit(global);
7918 return NULL;
7919 }
7920 }
7921
7922 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007923 global->params.override_driver =
7924 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007925 if (!global->params.override_driver) {
7926 wpa_supplicant_deinit(global);
7927 return NULL;
7928 }
7929 }
7930
7931 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007932 global->params.override_ctrl_interface =
7933 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007934 if (!global->params.override_ctrl_interface) {
7935 wpa_supplicant_deinit(global);
7936 return NULL;
7937 }
7938 }
7939
Dmitry Shmidte4663042016-04-04 10:07:49 -07007940#ifdef CONFIG_MATCH_IFACE
7941 global->params.match_iface_count = params->match_iface_count;
7942 if (params->match_iface_count) {
7943 global->params.match_ifaces =
7944 os_calloc(params->match_iface_count,
7945 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007946 if (!global->params.match_ifaces) {
7947 wpa_printf(MSG_ERROR,
7948 "Failed to allocate match interfaces");
7949 wpa_supplicant_deinit(global);
7950 return NULL;
7951 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007952 os_memcpy(global->params.match_ifaces,
7953 params->match_ifaces,
7954 params->match_iface_count *
7955 sizeof(struct wpa_interface));
7956 }
7957#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007958#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007959 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007960 global->params.conf_p2p_dev =
7961 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007962 if (!global->params.conf_p2p_dev) {
7963 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7964 wpa_supplicant_deinit(global);
7965 return NULL;
7966 }
7967 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007968#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007969 wpa_debug_level = global->params.wpa_debug_level =
7970 params->wpa_debug_level;
7971 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7972 params->wpa_debug_show_keys;
7973 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7974 params->wpa_debug_timestamp;
7975
Hai Shalomfdcde762020-04-02 11:19:20 -07007976 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007977
7978 if (eloop_init()) {
7979 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7980 wpa_supplicant_deinit(global);
7981 return NULL;
7982 }
7983
Jouni Malinen75ecf522011-06-27 15:19:46 -07007984 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007985
7986 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7987 if (global->ctrl_iface == NULL) {
7988 wpa_supplicant_deinit(global);
7989 return NULL;
7990 }
7991
7992 if (wpas_notify_supplicant_initialized(global)) {
7993 wpa_supplicant_deinit(global);
7994 return NULL;
7995 }
7996
7997 for (i = 0; wpa_drivers[i]; i++)
7998 global->drv_count++;
7999 if (global->drv_count == 0) {
8000 wpa_printf(MSG_ERROR, "No drivers enabled");
8001 wpa_supplicant_deinit(global);
8002 return NULL;
8003 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008004 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008005 if (global->drv_priv == NULL) {
8006 wpa_supplicant_deinit(global);
8007 return NULL;
8008 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008009
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008010#ifdef CONFIG_WIFI_DISPLAY
8011 if (wifi_display_init(global) < 0) {
8012 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8013 wpa_supplicant_deinit(global);
8014 return NULL;
8015 }
8016#endif /* CONFIG_WIFI_DISPLAY */
8017
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008018 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8019 wpas_periodic, global, NULL);
8020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008021 return global;
8022}
8023
8024
8025/**
8026 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8027 * @global: Pointer to global data from wpa_supplicant_init()
8028 * Returns: 0 after successful event loop run, -1 on failure
8029 *
8030 * This function starts the main event loop and continues running as long as
8031 * there are any remaining events. In most cases, this function is running as
8032 * long as the %wpa_supplicant process in still in use.
8033 */
8034int wpa_supplicant_run(struct wpa_global *global)
8035{
8036 struct wpa_supplicant *wpa_s;
8037
8038 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008039 (wpa_supplicant_daemon(global->params.pid_file) ||
8040 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008041 return -1;
8042
Dmitry Shmidte4663042016-04-04 10:07:49 -07008043#ifdef CONFIG_MATCH_IFACE
8044 if (wpa_supplicant_match_existing(global))
8045 return -1;
8046#endif
8047
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008048 if (global->params.wait_for_monitor) {
8049 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008050 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008051 wpa_supplicant_ctrl_iface_wait(
8052 wpa_s->ctrl_iface);
8053 }
8054
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008055#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008056 // If daemonize is enabled, initialize AIDL here.
8057 if (global->params.daemonize) {
8058 global->aidl = wpas_aidl_init(global);
8059 if (!global->aidl)
8060 return -1;
8061 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008062#endif /* CONFIG_AIDL */
8063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008064 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8065 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8066
8067 eloop_run();
8068
8069 return 0;
8070}
8071
8072
8073/**
8074 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8075 * @global: Pointer to global data from wpa_supplicant_init()
8076 *
8077 * This function is called to deinitialize %wpa_supplicant and to free all
8078 * allocated resources. Remaining network interfaces will also be removed.
8079 */
8080void wpa_supplicant_deinit(struct wpa_global *global)
8081{
8082 int i;
8083
8084 if (global == NULL)
8085 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008086
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008087 eloop_cancel_timeout(wpas_periodic, global, NULL);
8088
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008089#ifdef CONFIG_WIFI_DISPLAY
8090 wifi_display_deinit(global);
8091#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008092
8093 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008094 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008095
8096 if (global->ctrl_iface)
8097 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8098
8099 wpas_notify_supplicant_deinitialized(global);
8100
8101 eap_peer_unregister_methods();
8102#ifdef CONFIG_AP
8103 eap_server_unregister_methods();
8104#endif /* CONFIG_AP */
8105
8106 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8107 if (!global->drv_priv[i])
8108 continue;
8109 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8110 }
8111 os_free(global->drv_priv);
8112
8113 random_deinit();
8114
8115 eloop_destroy();
8116
8117 if (global->params.pid_file) {
8118 os_daemonize_terminate(global->params.pid_file);
8119 os_free(global->params.pid_file);
8120 }
8121 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008122 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008123 os_free(global->params.override_driver);
8124 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008125#ifdef CONFIG_MATCH_IFACE
8126 os_free(global->params.match_ifaces);
8127#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008128#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008129 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008130#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008131
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008132 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008133 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008134 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008136 os_free(global);
8137 wpa_debug_close_syslog();
8138 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008139 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008140}
8141
8142
8143void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8144{
8145 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8146 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8147 char country[3];
8148 country[0] = wpa_s->conf->country[0];
8149 country[1] = wpa_s->conf->country[1];
8150 country[2] = '\0';
8151 if (wpa_drv_set_country(wpa_s, country) < 0) {
8152 wpa_printf(MSG_ERROR, "Failed to set country code "
8153 "'%s'", country);
8154 }
8155 }
8156
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008157 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8158 wpas_init_ext_pw(wpa_s);
8159
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008160 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8161 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8162
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008163 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8164 struct wpa_driver_capa capa;
8165 int res = wpa_drv_get_capa(wpa_s, &capa);
8166
8167 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8168 wpa_printf(MSG_ERROR,
8169 "Failed to update wowlan_triggers to '%s'",
8170 wpa_s->conf->wowlan_triggers);
8171 }
8172
Hai Shalom81f62d82019-07-22 12:10:00 -07008173 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8174 wpa_supplicant_set_default_scan_ies(wpa_s);
8175
Hai Shalom899fcc72020-10-19 14:38:18 -07008176#ifdef CONFIG_BGSCAN
8177 /*
8178 * We default to global bgscan parameters only when per-network bgscan
8179 * parameters aren't set. Only bother resetting bgscan parameters if
8180 * this is the case.
8181 */
8182 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8183 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8184 wpa_s->wpa_state == WPA_COMPLETED)
8185 wpa_supplicant_reset_bgscan(wpa_s);
8186#endif /* CONFIG_BGSCAN */
8187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008188#ifdef CONFIG_WPS
8189 wpas_wps_update_config(wpa_s);
8190#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008191 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008192 wpa_s->conf->changed_parameters = 0;
8193}
8194
8195
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008196void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008197{
8198 int i;
8199
8200 for (i = 0; i < *num_freqs; i++) {
8201 if (freqs[i] == freq)
8202 return;
8203 }
8204
8205 freqs[*num_freqs] = freq;
8206 (*num_freqs)++;
8207}
8208
8209
8210static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8211{
8212 struct wpa_bss *bss, *cbss;
8213 const int max_freqs = 10;
8214 int *freqs;
8215 int num_freqs = 0;
8216
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008217 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008218 if (freqs == NULL)
8219 return NULL;
8220
8221 cbss = wpa_s->current_bss;
8222
8223 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8224 if (bss == cbss)
8225 continue;
8226 if (bss->ssid_len == cbss->ssid_len &&
8227 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008228 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008229 add_freq(freqs, &num_freqs, bss->freq);
8230 if (num_freqs == max_freqs)
8231 break;
8232 }
8233 }
8234
8235 if (num_freqs == 0) {
8236 os_free(freqs);
8237 freqs = NULL;
8238 }
8239
8240 return freqs;
8241}
8242
8243
Sunil Ravieb83e2a2024-06-28 17:34:56 +00008244void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008245{
8246 int timeout;
8247 int count;
8248 int *freqs = NULL;
8249
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008250 wpas_connect_work_done(wpa_s);
8251
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008252 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008253 * Remove possible authentication timeout since the connection failed.
8254 */
8255 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8256
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008257 /*
Hai Shalom60840252021-02-19 19:02:11 -08008258 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008259 * generated based on local request to disconnect.
8260 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008261 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008262 wpa_s->own_disconnect_req = 0;
8263 wpa_dbg(wpa_s, MSG_DEBUG,
8264 "Ignore connection failure due to local request to disconnect");
8265 return;
8266 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008267 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008268 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8269 "indication since interface has been put into "
8270 "disconnected state");
8271 return;
8272 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008273 if (wpa_s->auto_reconnect_disabled) {
8274 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8275 "indication since auto connect is disabled");
8276 return;
8277 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008278
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008279 /*
Hai Shalom60840252021-02-19 19:02:11 -08008280 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008281 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008282 */
Hai Shalom60840252021-02-19 19:02:11 -08008283 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008284 if (count == 1 && wpa_s->current_bss) {
8285 /*
Hai Shalom60840252021-02-19 19:02:11 -08008286 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008287 * another BSS available for the same ESS, we should try that
8288 * next. Otherwise, we may as well try this one once more
8289 * before allowing other, likely worse, ESSes to be considered.
8290 */
8291 freqs = get_bss_freqs_in_ess(wpa_s);
8292 if (freqs) {
8293 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8294 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008295 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008296 /*
8297 * On the next scan, go through only the known channels
8298 * used in this ESS based on previous scans to speed up
8299 * common load balancing use case.
8300 */
8301 os_free(wpa_s->next_scan_freqs);
8302 wpa_s->next_scan_freqs = freqs;
8303 }
8304 }
8305
Hai Shalom899fcc72020-10-19 14:38:18 -07008306 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008307
Hai Shalom899fcc72020-10-19 14:38:18 -07008308 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008309 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8310 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008311 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008312 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008313 /*
8314 * Multiple consecutive connection failures mean that other APs are
8315 * either not available or have already been tried, so we can start
8316 * increasing the delay here to avoid constant scanning.
8317 */
8318 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008319 case 1:
8320 timeout = 100;
8321 break;
8322 case 2:
8323 timeout = 500;
8324 break;
8325 case 3:
8326 timeout = 1000;
8327 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008328 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008329 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008330 break;
8331 default:
8332 timeout = 10000;
8333 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008334 }
8335
Hai Shalom899fcc72020-10-19 14:38:18 -07008336 wpa_dbg(wpa_s, MSG_DEBUG,
8337 "Consecutive connection failures: %d --> request scan in %d ms",
8338 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008340 /*
8341 * TODO: if more than one possible AP is available in scan results,
8342 * could try the other ones before requesting a new scan.
8343 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008344
8345 /* speed up the connection attempt with normal scan */
8346 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008347 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8348 1000 * (timeout % 1000));
8349}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008350
8351
Hai Shalomce48b4a2018-09-05 11:41:35 -07008352#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008353
8354void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8355{
8356 struct wpa_ssid *ssid = wpa_s->current_ssid;
8357 const u8 *realm, *username, *rrk;
8358 size_t realm_len, username_len, rrk_len;
8359 u16 next_seq_num;
8360
8361 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8362 * Check for ERP keys existing to limit when this can be done since
8363 * the rejection response is not protected and such triggers should
8364 * really not allow internal state to be modified unless required to
8365 * avoid significant issues in functionality. In addition, drop
8366 * externally configure PMKSA entries even without ERP keys since it
8367 * is possible for an external component to add PMKSA entries for FILS
8368 * authentication without restoring previously generated ERP keys.
8369 *
8370 * In this case, this is needed to allow recovery from cases where the
8371 * AP or authentication server has dropped PMKSAs and ERP keys. */
8372 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8373 return;
8374
8375 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8376 &username, &username_len,
8377 &realm, &realm_len, &next_seq_num,
8378 &rrk, &rrk_len) != 0 ||
8379 !realm) {
8380 wpa_dbg(wpa_s, MSG_DEBUG,
8381 "FILS: Drop external PMKSA cache entry");
8382 wpa_sm_aborted_external_cached(wpa_s->wpa);
8383 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8384 return;
8385 }
8386
8387 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8388 wpa_sm_aborted_cached(wpa_s->wpa);
8389 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8390}
8391
8392
Hai Shalomce48b4a2018-09-05 11:41:35 -07008393void fils_connection_failure(struct wpa_supplicant *wpa_s)
8394{
8395 struct wpa_ssid *ssid = wpa_s->current_ssid;
8396 const u8 *realm, *username, *rrk;
8397 size_t realm_len, username_len, rrk_len;
8398 u16 next_seq_num;
8399
8400 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8401 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8402 &username, &username_len,
8403 &realm, &realm_len, &next_seq_num,
8404 &rrk, &rrk_len) != 0 ||
8405 !realm)
8406 return;
8407
8408 wpa_hexdump_ascii(MSG_DEBUG,
8409 "FILS: Store last connection failure realm",
8410 realm, realm_len);
8411 os_free(wpa_s->last_con_fail_realm);
8412 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8413 if (wpa_s->last_con_fail_realm) {
8414 wpa_s->last_con_fail_realm_len = realm_len;
8415 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8416 }
8417}
8418#endif /* CONFIG_FILS */
8419
8420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008421int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8422{
8423 return wpa_s->conf->ap_scan == 2 ||
8424 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8425}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008426
Dmitry Shmidt04949592012-07-19 12:16:46 -07008427
Gabriel Biren57ededa2021-09-03 16:08:50 +00008428#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008429int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8430 struct wpa_ssid *ssid,
8431 const char *field,
8432 const char *value)
8433{
8434#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008435 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008436
8437 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8438 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8439 (const u8 *) value, os_strlen(value));
8440
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008441 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008442 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008443#else /* IEEE8021X_EAPOL */
8444 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8445 return -1;
8446#endif /* IEEE8021X_EAPOL */
8447}
8448
8449int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8450 struct wpa_ssid *ssid,
8451 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008452 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008453{
8454#ifdef IEEE8021X_EAPOL
8455 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008456 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008457
8458 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008459 case WPA_CTRL_REQ_EAP_IDENTITY:
8460 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008461 os_free(eap->imsi_identity);
8462 if (value == NULL)
8463 return -1;
8464 identity = os_strchr(value, ':');
8465 if (identity == NULL) {
8466 /* plain identity */
8467 eap->identity = (u8 *)os_strdup(value);
8468 eap->identity_len = os_strlen(value);
8469 } else {
8470 /* have both plain identity and encrypted identity */
8471 imsi_identity = value;
8472 *identity++ = '\0';
8473 /* plain identity */
8474 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8475 eap->imsi_identity_len = strlen(imsi_identity);
8476 /* encrypted identity */
8477 eap->identity = (u8 *)dup_binstr(identity,
8478 value_len - strlen(imsi_identity) - 1);
8479 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8480 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008481 eap->pending_req_identity = 0;
8482 if (ssid == wpa_s->current_ssid)
8483 wpa_s->reassociate = 1;
8484 break;
8485 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008486 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008487 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008488 if (!eap->password)
8489 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008490 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008491 eap->pending_req_password = 0;
8492 if (ssid == wpa_s->current_ssid)
8493 wpa_s->reassociate = 1;
8494 break;
8495 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008496 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008497 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008498 if (!eap->new_password)
8499 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008500 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008501 eap->pending_req_new_password = 0;
8502 if (ssid == wpa_s->current_ssid)
8503 wpa_s->reassociate = 1;
8504 break;
8505 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008506 str_clear_free(eap->cert.pin);
8507 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008508 if (!eap->cert.pin)
8509 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008510 eap->pending_req_pin = 0;
8511 if (ssid == wpa_s->current_ssid)
8512 wpa_s->reassociate = 1;
8513 break;
8514 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008515 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008516 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008517 if (!eap->otp)
8518 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008519 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008520 os_free(eap->pending_req_otp);
8521 eap->pending_req_otp = NULL;
8522 eap->pending_req_otp_len = 0;
8523 break;
8524 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008525 str_clear_free(eap->cert.private_key_passwd);
8526 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008527 if (!eap->cert.private_key_passwd)
8528 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008529 eap->pending_req_passphrase = 0;
8530 if (ssid == wpa_s->current_ssid)
8531 wpa_s->reassociate = 1;
8532 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008533 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008534 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008535 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008536 if (!eap->external_sim_resp)
8537 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008538 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008539 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008540 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8541 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8542 return -1;
8543 ssid->mem_only_psk = 1;
8544 if (ssid->passphrase)
8545 wpa_config_update_psk(ssid);
8546 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8547 wpa_supplicant_req_scan(wpa_s, 0, 0);
8548 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008549 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8550 if (eap->pending_ext_cert_check != PENDING_CHECK)
8551 return -1;
8552 if (os_strcmp(value, "good") == 0)
8553 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8554 else if (os_strcmp(value, "bad") == 0)
8555 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8556 else
8557 return -1;
8558 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008559 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008560 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008561 return -1;
8562 }
8563
8564 return 0;
8565#else /* IEEE8021X_EAPOL */
8566 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8567 return -1;
8568#endif /* IEEE8021X_EAPOL */
8569}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008570#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008571
8572
8573int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8574{
Hai Shalomfdcde762020-04-02 11:19:20 -07008575#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008576 int i;
8577 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008578#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008579
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008580 if (wpa_s->p2p_mgmt)
8581 return 1; /* no normal network profiles on p2p_mgmt interface */
8582
Dmitry Shmidt04949592012-07-19 12:16:46 -07008583 if (ssid == NULL)
8584 return 1;
8585
8586 if (ssid->disabled)
8587 return 1;
8588
Hai Shalomfdcde762020-04-02 11:19:20 -07008589#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008590 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008591 drv_enc = wpa_s->drv_enc;
8592 else
8593 drv_enc = (unsigned int) -1;
8594
8595 for (i = 0; i < NUM_WEP_KEYS; i++) {
8596 size_t len = ssid->wep_key_len[i];
8597 if (len == 0)
8598 continue;
8599 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8600 continue;
8601 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8602 continue;
8603 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8604 continue;
8605 return 1; /* invalid WEP key */
8606 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008607#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008609 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008610 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008611 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008612 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008613 return 1;
8614
Sunil Ravi89eba102022-09-13 21:04:37 -07008615#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008616#ifdef CRYPTO_RSA_OAEP_SHA256
8617 if (ssid->eap.imsi_privacy_cert) {
8618 struct crypto_rsa_key *key;
8619 bool failed = false;
8620
8621 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8622 if (!key)
8623 failed = true;
8624 crypto_rsa_key_free(key);
8625 if (failed) {
8626 wpa_printf(MSG_DEBUG,
8627 "Invalid imsi_privacy_cert (%s) - disable network",
8628 ssid->eap.imsi_privacy_cert);
8629 return 1;
8630 }
8631 }
8632#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008633#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008634
Dmitry Shmidt04949592012-07-19 12:16:46 -07008635 return 0;
8636}
8637
8638
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008639int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8640{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008641 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8642 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8643 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8644 /*
8645 * Driver does not support BIP -- ignore pmf=1 default
8646 * since the connection with PMF would fail and the
8647 * configuration does not require PMF to be enabled.
8648 */
8649 return NO_MGMT_FRAME_PROTECTION;
8650 }
8651
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008652 if (ssid &&
8653 (ssid->key_mgmt &
8654 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8655 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8656 /*
8657 * Do not use the default PMF value for non-RSN networks
8658 * since PMF is available only with RSN and pmf=2
8659 * configuration would otherwise prevent connections to
8660 * all open networks.
8661 */
8662 return NO_MGMT_FRAME_PROTECTION;
8663 }
8664
Sunil Ravi77d572f2023-01-17 23:58:31 +00008665#ifdef CONFIG_OCV
8666 /* Enable PMF if OCV is being enabled */
8667 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8668 ssid && ssid->ocv)
8669 return MGMT_FRAME_PROTECTION_OPTIONAL;
8670#endif /* CONFIG_OCV */
8671
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008672 return wpa_s->conf->pmf;
8673 }
8674
8675 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008676}
8677
8678
Sunil Ravi77d572f2023-01-17 23:58:31 +00008679#ifdef CONFIG_SAE
8680bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8681 struct wpa_ssid *ssid,
8682 const struct wpa_ie_data *ie)
8683{
8684 return wpa_s->conf->sae_check_mfp &&
8685 (!(ie->capabilities &
8686 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8687 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8688}
8689#endif /* CONFIG_SAE */
8690
8691
Hai Shalomc1a21442022-02-04 13:43:00 -08008692int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8693{
8694 if (wpa_s->current_ssid == NULL ||
Sunil Ravieb83e2a2024-06-28 17:34:56 +00008695 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8696 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
Hai Shalomc1a21442022-02-04 13:43:00 -08008697 return 0;
8698 return wpa_sm_pmf_enabled(wpa_s->wpa);
8699}
8700
8701
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008702int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008703{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008704 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008705 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008706 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008707 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008708 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008709}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008710
8711
Sunil Ravi77d572f2023-01-17 23:58:31 +00008712void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8713 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008714{
8715 struct wpa_ssid *ssid = wpa_s->current_ssid;
8716 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008717 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008718
8719 if (ssid == NULL) {
8720 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8721 "SSID block");
8722 return;
8723 }
8724
8725 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8726 return;
8727
8728 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008729
8730#ifdef CONFIG_P2P
8731 if (ssid->p2p_group &&
8732 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8733 /*
8734 * Skip the wait time since there is a short timeout on the
8735 * connection to a P2P group.
8736 */
8737 return;
8738 }
8739#endif /* CONFIG_P2P */
8740
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008741 if (ssid->auth_failures > 50)
8742 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008743 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008744 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008745 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008746 dur = 90;
8747 else if (ssid->auth_failures > 3)
8748 dur = 60;
8749 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008750 dur = 30;
8751 else if (ssid->auth_failures > 1)
8752 dur = 20;
8753 else
8754 dur = 10;
8755
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008756 if (ssid->auth_failures > 1 &&
8757 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8758 dur += os_random() % (ssid->auth_failures * 10);
8759
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008760 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008761 if (now.sec + dur <= ssid->disabled_until.sec)
8762 return;
8763
8764 ssid->disabled_until.sec = now.sec + dur;
8765
8766 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008767 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008768 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008769 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008770
8771 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8772 int msg_len = snprintf(NULL, 0, format_str,
8773 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8774 ssid->auth_failures, dur, reason) + 1;
8775 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308776 if (!msg)
8777 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008778 snprintf(msg, msg_len, format_str,
8779 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8780 ssid->auth_failures, dur, reason);
8781 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8782 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008783
8784 if (bssid)
8785 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008786}
8787
8788
8789void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8790 struct wpa_ssid *ssid, int clear_failures)
8791{
8792 if (ssid == NULL)
8793 return;
8794
8795 if (ssid->disabled_until.sec) {
8796 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8797 "id=%d ssid=\"%s\"",
8798 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8799 }
8800 ssid->disabled_until.sec = 0;
8801 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008802 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008803 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008804 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8805 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8806 " ignored to allow a lower priority BSS, if any, to be tried next",
8807 MAC2STR(ssid->disabled_due_to));
8808 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8809 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8810 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008811}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008812
8813
8814int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8815{
8816 size_t i;
8817
8818 if (wpa_s->disallow_aps_bssid == NULL)
8819 return 0;
8820
8821 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravieb83e2a2024-06-28 17:34:56 +00008822 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8823 bssid, ETH_ALEN) == 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008824 return 1;
8825 }
8826
8827 return 0;
8828}
8829
8830
8831int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8832 size_t ssid_len)
8833{
8834 size_t i;
8835
8836 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8837 return 0;
8838
8839 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8840 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8841 if (ssid_len == s->ssid_len &&
8842 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8843 return 1;
8844 }
8845
8846 return 0;
8847}
8848
8849
8850/**
8851 * wpas_request_connection - Request a new connection
8852 * @wpa_s: Pointer to the network interface
8853 *
8854 * This function is used to request a new connection to be found. It will mark
8855 * the interface to allow reassociation and request a new scan to find a
8856 * suitable network to connect to.
8857 */
8858void wpas_request_connection(struct wpa_supplicant *wpa_s)
8859{
8860 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008861 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008862 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008863 wpa_s->disconnected = 0;
8864 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008865 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008866
8867 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8868 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008869 else
8870 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008871}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008872
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008873
Roshan Pius02242d72016-08-09 15:31:48 -07008874/**
8875 * wpas_request_disconnection - Request disconnection
8876 * @wpa_s: Pointer to the network interface
8877 *
8878 * This function is used to request disconnection from the currently connected
8879 * network. This will stop any ongoing scans and initiate deauthentication.
8880 */
8881void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8882{
8883#ifdef CONFIG_SME
8884 wpa_s->sme.prev_bssid_set = 0;
8885#endif /* CONFIG_SME */
8886 wpa_s->reassociate = 0;
8887 wpa_s->disconnected = 1;
8888 wpa_supplicant_cancel_sched_scan(wpa_s);
8889 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008890 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008891 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8892 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008893 radio_remove_works(wpa_s, "connect", 0);
8894 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008895 wpa_s->roam_in_progress = false;
8896#ifdef CONFIG_WNM
8897 wpa_s->bss_trans_mgmt_in_progress = false;
8898#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008899}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008900
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008901
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008902void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8903 struct wpa_used_freq_data *freqs_data,
8904 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008905{
8906 unsigned int i;
8907
8908 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8909 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008910 for (i = 0; i < len; i++) {
8911 struct wpa_used_freq_data *cur = &freqs_data[i];
8912 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8913 i, cur->freq, cur->flags);
8914 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008915}
8916
8917
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008918/*
8919 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008920 * are using the same radio as the current interface, and in addition, get
8921 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008922 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008923int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8924 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008925 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008926{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008927 struct wpa_supplicant *ifs;
8928 u8 bssid[ETH_ALEN];
8929 int freq;
8930 unsigned int idx = 0, i;
8931
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008932 wpa_dbg(wpa_s, MSG_DEBUG,
8933 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008934 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008935
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008936 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8937 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008938 if (idx == len)
8939 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008940
Sunil Ravi77d572f2023-01-17 23:58:31 +00008941 if (exclude_current && ifs == wpa_s)
8942 continue;
8943
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008944 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8945 continue;
8946
8947 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008948 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8949 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008950 freq = ifs->current_ssid->frequency;
8951 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8952 freq = ifs->assoc_freq;
8953 else
8954 continue;
8955
8956 /* Hold only distinct freqs */
8957 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008958 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008959 break;
8960
8961 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008962 freqs_data[idx++].freq = freq;
8963
8964 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008965 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008966 WPA_FREQ_USED_BY_P2P_CLIENT :
8967 WPA_FREQ_USED_BY_INFRA_STATION;
8968 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008969 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008970
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008971 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008972 return idx;
8973}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008974
8975
8976/*
8977 * Find the operating frequencies of any of the virtual interfaces that
8978 * are using the same radio as the current interface.
8979 */
8980int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008981 int *freq_array, unsigned int len,
8982 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008983{
8984 struct wpa_used_freq_data *freqs_data;
8985 int num, i;
8986
8987 os_memset(freq_array, 0, sizeof(int) * len);
8988
8989 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8990 if (!freqs_data)
8991 return -1;
8992
Sunil Ravi77d572f2023-01-17 23:58:31 +00008993 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8994 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008995 for (i = 0; i < num; i++)
8996 freq_array[i] = freqs_data[i].freq;
8997
8998 os_free(freqs_data);
8999
9000 return num;
9001}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009002
9003
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009004struct wpa_supplicant *
9005wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9006{
9007 switch (frame) {
9008#ifdef CONFIG_P2P
9009 case VENDOR_ELEM_PROBE_REQ_P2P:
9010 case VENDOR_ELEM_PROBE_RESP_P2P:
9011 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9012 case VENDOR_ELEM_BEACON_P2P_GO:
9013 case VENDOR_ELEM_P2P_PD_REQ:
9014 case VENDOR_ELEM_P2P_PD_RESP:
9015 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9016 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9017 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9018 case VENDOR_ELEM_P2P_INV_REQ:
9019 case VENDOR_ELEM_P2P_INV_RESP:
9020 case VENDOR_ELEM_P2P_ASSOC_REQ:
9021 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009022 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009023#endif /* CONFIG_P2P */
9024 default:
9025 return wpa_s;
9026 }
9027}
9028
9029
9030void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9031{
9032 unsigned int i;
9033 char buf[30];
9034
9035 wpa_printf(MSG_DEBUG, "Update vendor elements");
9036
9037 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9038 if (wpa_s->vendor_elem[i]) {
9039 int res;
9040
9041 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9042 if (!os_snprintf_error(sizeof(buf), res)) {
9043 wpa_hexdump_buf(MSG_DEBUG, buf,
9044 wpa_s->vendor_elem[i]);
9045 }
9046 }
9047 }
9048
9049#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009050 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009051 wpa_s->global->p2p &&
9052 !wpa_s->global->p2p_disabled)
9053 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9054#endif /* CONFIG_P2P */
9055}
9056
9057
9058int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9059 const u8 *elem, size_t len)
9060{
9061 u8 *ie, *end;
9062
9063 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9064 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9065
9066 for (; ie + 1 < end; ie += 2 + ie[1]) {
9067 if (ie + len > end)
9068 break;
9069 if (os_memcmp(ie, elem, len) != 0)
9070 continue;
9071
9072 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9073 wpabuf_free(wpa_s->vendor_elem[frame]);
9074 wpa_s->vendor_elem[frame] = NULL;
9075 } else {
9076 os_memmove(ie, ie + len, end - (ie + len));
9077 wpa_s->vendor_elem[frame]->used -= len;
9078 }
9079 wpas_vendor_elem_update(wpa_s);
9080 return 0;
9081 }
9082
9083 return -1;
9084}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009085
9086
9087struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009088 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009089 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009090{
9091 u16 i;
9092
Hai Shalomc1a21442022-02-04 13:43:00 -08009093 if (!modes)
9094 return NULL;
9095
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009096 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009097 if (modes[i].mode != mode ||
9098 !modes[i].num_channels || !modes[i].channels)
9099 continue;
Sunil Ravi88611412024-06-28 17:34:56 +00009100 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
9101 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009102 return &modes[i];
9103 }
9104
9105 return NULL;
9106}
9107
9108
Hai Shalomc1a21442022-02-04 13:43:00 -08009109struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9110 u16 num_modes, int freq)
9111{
9112 int i, j;
9113
9114 for (i = 0; i < num_modes; i++) {
9115 for (j = 0; j < modes[i].num_channels; j++) {
9116 if (freq == modes[i].channels[j].freq)
9117 return &modes[i];
9118 }
9119 }
9120
9121 return NULL;
9122}
9123
9124
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009125static struct
9126wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9127 const u8 *bssid)
9128{
9129 struct wpa_bss_tmp_disallowed *bss;
9130
9131 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9132 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009133 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009134 return bss;
9135 }
9136
9137 return NULL;
9138}
9139
9140
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009141static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9142{
9143 struct wpa_bss_tmp_disallowed *tmp;
9144 unsigned int num_bssid = 0;
9145 u8 *bssids;
9146 int ret;
9147
9148 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9149 if (!bssids)
9150 return -1;
9151 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9152 struct wpa_bss_tmp_disallowed, list) {
9153 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9154 ETH_ALEN);
9155 num_bssid++;
9156 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009157 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009158 os_free(bssids);
9159 return ret;
9160}
9161
9162
9163static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9164{
9165 struct wpa_supplicant *wpa_s = eloop_ctx;
9166 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9167
9168 /* Make sure the bss is not already freed */
9169 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9170 struct wpa_bss_tmp_disallowed, list) {
9171 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009172 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009173 wpa_set_driver_tmp_disallow_list(wpa_s);
9174 break;
9175 }
9176 }
9177}
9178
9179
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009180void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009181 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009182{
9183 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009184
9185 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9186 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009187 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009188 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009189 }
9190
9191 bss = os_malloc(sizeof(*bss));
9192 if (!bss) {
9193 wpa_printf(MSG_DEBUG,
9194 "Failed to allocate memory for temp disallow BSS");
9195 return;
9196 }
9197
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009198 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9199 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009200 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009201
9202finish:
9203 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009204 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9205 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009206}
9207
9208
Hai Shalom74f70d42019-02-11 14:42:39 -08009209int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9210 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009211{
Hai Shalom74f70d42019-02-11 14:42:39 -08009212 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009213
9214 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9215 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009216 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009217 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009218 break;
9219 }
9220 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009221 if (!disallowed)
9222 return 0;
9223
9224 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009225 bss->level > disallowed->rssi_threshold) {
9226 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9227 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009228 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009229 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009230
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009231 return 1;
9232}
Hai Shalom81f62d82019-07-22 12:10:00 -07009233
9234
9235int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9236 unsigned int type, const u8 *addr,
9237 const u8 *mask)
9238{
9239 if ((addr && !mask) || (!addr && mask)) {
9240 wpa_printf(MSG_INFO,
9241 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9242 return -1;
9243 }
9244
9245 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9246 wpa_printf(MSG_INFO,
9247 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9248 return -1;
9249 }
9250
9251 if (type & MAC_ADDR_RAND_SCAN) {
9252 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9253 addr, mask))
9254 return -1;
9255 }
9256
9257 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9258 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9259 addr, mask))
9260 return -1;
9261
9262 if (wpa_s->sched_scanning && !wpa_s->pno)
9263 wpas_scan_restart_sched_scan(wpa_s);
9264 }
9265
9266 if (type & MAC_ADDR_RAND_PNO) {
9267 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9268 addr, mask))
9269 return -1;
9270
9271 if (wpa_s->pno) {
9272 wpas_stop_pno(wpa_s);
9273 wpas_start_pno(wpa_s);
9274 }
9275 }
9276
9277 return 0;
9278}
9279
9280
9281int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9282 unsigned int type)
9283{
9284 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9285 if (wpa_s->pno) {
9286 if (type & MAC_ADDR_RAND_PNO) {
9287 wpas_stop_pno(wpa_s);
9288 wpas_start_pno(wpa_s);
9289 }
9290 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9291 wpas_scan_restart_sched_scan(wpa_s);
9292 }
9293
9294 return 0;
9295}
Hai Shalomfdcde762020-04-02 11:19:20 -07009296
9297
9298int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9299 struct wpa_signal_info *si)
9300{
9301 int res;
9302
9303 if (!wpa_s->driver->signal_poll)
9304 return -1;
9305
9306 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9307
9308#ifdef CONFIG_TESTING_OPTIONS
9309 if (res == 0) {
9310 struct driver_signal_override *dso;
9311
9312 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9313 struct driver_signal_override, list) {
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009314 if (os_memcmp(wpa_s->bssid, dso->bssid,
9315 ETH_ALEN) != 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07009316 continue;
9317 wpa_printf(MSG_DEBUG,
9318 "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 +00009319 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009320 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009321 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009322 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009323 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009324 dso->si_avg_beacon_signal,
9325 si->current_noise,
9326 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009327 si->data.signal = dso->si_current_signal;
9328 si->data.avg_signal = dso->si_avg_signal;
9329 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009330 si->current_noise = dso->si_current_noise;
9331 break;
9332 }
9333 }
9334#endif /* CONFIG_TESTING_OPTIONS */
9335
9336 return res;
9337}
9338
9339
9340struct wpa_scan_results *
Sunil Ravi88611412024-06-28 17:34:56 +00009341wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
Hai Shalomfdcde762020-04-02 11:19:20 -07009342{
9343 struct wpa_scan_results *scan_res;
9344#ifdef CONFIG_TESTING_OPTIONS
9345 size_t idx;
9346#endif /* CONFIG_TESTING_OPTIONS */
9347
Sunil Ravi88611412024-06-28 17:34:56 +00009348 if (!wpa_s->driver->get_scan_results2)
Hai Shalomfdcde762020-04-02 11:19:20 -07009349 return NULL;
9350
Sunil Ravi88611412024-06-28 17:34:56 +00009351 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
Hai Shalomfdcde762020-04-02 11:19:20 -07009352
9353#ifdef CONFIG_TESTING_OPTIONS
9354 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9355 struct driver_signal_override *dso;
9356 struct wpa_scan_res *res = scan_res->res[idx];
9357
9358 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9359 struct driver_signal_override, list) {
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009360 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07009361 continue;
9362 wpa_printf(MSG_DEBUG,
9363 "Override driver scan signal level %d->%d for "
9364 MACSTR,
9365 res->level, dso->scan_level,
9366 MAC2STR(res->bssid));
9367 res->flags |= WPA_SCAN_QUAL_INVALID;
9368 if (dso->scan_level < 0)
9369 res->flags |= WPA_SCAN_LEVEL_DBM;
9370 else
9371 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9372 res->level = dso->scan_level;
9373 break;
9374 }
9375 }
9376#endif /* CONFIG_TESTING_OPTIONS */
9377
9378 return scan_res;
9379}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009380
9381
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009382static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009383{
9384 int i;
9385
9386 if (!wpa_s->valid_links)
9387 return false;
9388
Sunil Ravi88611412024-06-28 17:34:56 +00009389 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9390 if (!(wpa_s->valid_links & BIT(i)))
9391 continue;
9392
Sunil Ravieb83e2a2024-06-28 17:34:56 +00009393 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009394 return true;
9395 }
9396
9397 return false;
9398}
9399
9400
9401int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9402 unsigned int wait, const u8 *dst, const u8 *src,
9403 const u8 *bssid, const u8 *data, size_t data_len,
9404 int no_cck)
9405{
9406 if (!wpa_s->driver->send_action)
9407 return -1;
9408
9409 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9410 if (wpas_ap_link_address(wpa_s, dst))
9411 dst = wpa_s->ap_mld_addr;
9412
9413 if (wpas_ap_link_address(wpa_s, bssid))
9414 bssid = wpa_s->ap_mld_addr;
9415 }
9416
9417 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9418 bssid, data, data_len, no_cck);
9419}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009420
9421
9422bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9423{
9424 struct hostapd_channel_data *chnl;
9425 int i, j;
9426
9427 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9428 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9429 chnl = wpa_s->hw.modes[i].channels;
9430 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9431 if (only_enabled &&
9432 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9433 continue;
9434 if (is_6ghz_freq(chnl[j].freq))
9435 return true;
9436 }
9437 }
9438 }
9439
9440 return false;
9441}