blob: 982ff6caf791c1ee3e78f57210c598dbae02ec95 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003 * Copyright (c) 2003-2024, 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"
Sunil Ravib0ac25f2024-07-12 01:42:03 +000068#include "nan_usd.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070069#ifdef CONFIG_MESH
70#include "ap/ap_config.h"
71#include "ap/hostapd.h"
72#endif /* CONFIG_MESH */
Gabriel Biren3c401c52024-10-10 20:11:18 +000073#include "aidl/vendor/aidl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070075const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076"wpa_supplicant v" VERSION_STR "\n"
Sunil Ravi7f769292024-07-23 22:21:32 +000077"Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070079const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080080"This software may be distributed under the terms of the BSD license.\n"
81"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082#ifdef EAP_TLS_OPENSSL
83"\nThis product includes software developed by the OpenSSL Project\n"
84"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
85#endif /* EAP_TLS_OPENSSL */
86;
87
88#ifndef CONFIG_NO_STDOUT_DEBUG
89/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080091"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070092const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080093"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070094"\n"
95"Redistribution and use in source and binary forms, with or without\n"
96"modification, are permitted provided that the following conditions are\n"
97"met:\n"
98"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070099const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700100"1. Redistributions of source code must retain the above copyright\n"
101" notice, this list of conditions and the following disclaimer.\n"
102"\n"
103"2. Redistributions in binary form must reproduce the above copyright\n"
104" notice, this list of conditions and the following disclaimer in the\n"
105" documentation and/or other materials provided with the distribution.\n"
106"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700107const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700108"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
109" names of its contributors may be used to endorse or promote products\n"
110" derived from this software without specific prior written permission.\n"
111"\n"
112"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
113"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
114"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
115"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700116const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
118"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
119"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
120"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
121"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
122"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
123"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
124"\n";
125#endif /* CONFIG_NO_STDOUT_DEBUG */
126
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700127
128static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
Sunil Ravi7f769292024-07-23 22:21:32 +0000129static void wpas_verify_ssid_beacon(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700130#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
131static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
132#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700133#ifdef CONFIG_OWE
134static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
135#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700136
137
Hai Shalomfdcde762020-04-02 11:19:20 -0700138#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700139/* Configure default/group WEP keys for static WEP */
140int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
141{
142 int i, set = 0;
143
144 for (i = 0; i < NUM_WEP_KEYS; i++) {
145 if (ssid->wep_key_len[i] == 0)
146 continue;
147
148 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000149 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700151 ssid->wep_key[i], ssid->wep_key_len[i],
152 i == ssid->wep_tx_keyidx ?
153 KEY_FLAG_GROUP_RX_TX_DEFAULT :
154 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155 }
156
157 return set;
158}
Hai Shalomfdcde762020-04-02 11:19:20 -0700159#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160
161
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700162int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
163 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164{
165 u8 key[32];
166 size_t keylen;
167 enum wpa_alg alg;
168 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800169 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700170
171 /* IBSS/WPA-None uses only one key (Group) for both receiving and
172 * sending unicast and multicast packets. */
173
174 if (ssid->mode != WPAS_MODE_IBSS) {
175 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
176 "IBSS/ad-hoc) for WPA-None", ssid->mode);
177 return -1;
178 }
179
180 if (!ssid->psk_set) {
181 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
182 "WPA-None");
183 return -1;
184 }
185
186 switch (wpa_s->group_cipher) {
187 case WPA_CIPHER_CCMP:
188 os_memcpy(key, ssid->psk, 16);
189 keylen = 16;
190 alg = WPA_ALG_CCMP;
191 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700192 case WPA_CIPHER_GCMP:
193 os_memcpy(key, ssid->psk, 16);
194 keylen = 16;
195 alg = WPA_ALG_GCMP;
196 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197 case WPA_CIPHER_TKIP:
198 /* WPA-None uses the same Michael MIC key for both TX and RX */
199 os_memcpy(key, ssid->psk, 16 + 8);
200 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
201 keylen = 32;
202 alg = WPA_ALG_TKIP;
203 break;
204 default:
205 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
206 "WPA-None", wpa_s->group_cipher);
207 return -1;
208 }
209
210 /* TODO: should actually remember the previously used seq#, both for TX
211 * and RX from each STA.. */
212
Sunil Ravi77d572f2023-01-17 23:58:31 +0000213 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700214 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800215 os_memset(key, 0, sizeof(key));
216 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217}
218
219
220static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
221{
222 struct wpa_supplicant *wpa_s = eloop_ctx;
223 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700224 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
225 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
226 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 bssid = wpa_s->pending_bssid;
228 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
229 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800230 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700231 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800233 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700234 wpa_s->reassociate = 1;
235
236 /*
237 * If we timed out, the AP or the local radio may be busy.
238 * So, wait a second until scanning again.
239 */
240 wpa_supplicant_req_scan(wpa_s, 1, 0);
241}
242
243
244/**
245 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
246 * @wpa_s: Pointer to wpa_supplicant data
247 * @sec: Number of seconds after which to time out authentication
248 * @usec: Number of microseconds after which to time out authentication
249 *
250 * This function is used to schedule a timeout for the current authentication
251 * attempt.
252 */
253void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
254 int sec, int usec)
255{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700256 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
258 return;
259
260 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
261 "%d usec", sec, usec);
262 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700263 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700264 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
265}
266
267
Roshan Pius3a1667e2018-07-03 15:17:14 -0700268/*
269 * wpas_auth_timeout_restart - Restart and change timeout for authentication
270 * @wpa_s: Pointer to wpa_supplicant data
271 * @sec_diff: difference in seconds applied to original timeout value
272 */
273void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
274{
275 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
276
277 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
278 wpa_dbg(wpa_s, MSG_DEBUG,
279 "Authentication timeout restart: %d sec", new_sec);
280 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
281 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
282 wpa_s, NULL);
283 }
284}
285
286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287/**
288 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
289 * @wpa_s: Pointer to wpa_supplicant data
290 *
291 * This function is used to cancel authentication timeout scheduled with
292 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
293 * been completed.
294 */
295void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
296{
297 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
298 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800299 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700300 os_free(wpa_s->last_con_fail_realm);
301 wpa_s->last_con_fail_realm = NULL;
302 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303}
304
305
306/**
307 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
308 * @wpa_s: Pointer to wpa_supplicant data
309 *
310 * This function is used to configure EAPOL state machine based on the selected
311 * authentication mode.
312 */
313void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
314{
315#ifdef IEEE8021X_EAPOL
316 struct eapol_config eapol_conf;
317 struct wpa_ssid *ssid = wpa_s->current_ssid;
318
319#ifdef CONFIG_IBSS_RSN
320 if (ssid->mode == WPAS_MODE_IBSS &&
321 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
322 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
323 /*
324 * RSN IBSS authentication is per-STA and we can disable the
325 * per-BSSID EAPOL authentication.
326 */
327 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700328 eapol_sm_notify_eap_success(wpa_s->eapol, true);
329 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330 return;
331 }
332#endif /* CONFIG_IBSS_RSN */
333
Hai Shalome21d4e82020-04-29 16:34:06 -0700334 eapol_sm_notify_eap_success(wpa_s->eapol, false);
335 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336
337 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
338 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
339 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
340 else
341 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
342
343 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
344 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
345 eapol_conf.accept_802_1x_keys = 1;
346 eapol_conf.required_keys = 0;
347 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
348 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
349 }
350 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
351 eapol_conf.required_keys |=
352 EAPOL_REQUIRE_KEY_BROADCAST;
353 }
354
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700355 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356 eapol_conf.required_keys = 0;
357 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700358 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359 eapol_conf.workaround = ssid->eap_workaround;
360 eapol_conf.eap_disabled =
361 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
362 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
363 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700364 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800365
366#ifdef CONFIG_WPS
367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
368 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
369 if (wpa_s->current_bss) {
370 struct wpabuf *ie;
371 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
372 WPS_IE_VENDOR_TYPE);
373 if (ie) {
374 if (wps_is_20(ie))
375 eapol_conf.wps |=
376 EAPOL_PEER_IS_WPS20_AP;
377 wpabuf_free(ie);
378 }
379 }
380 }
381#endif /* CONFIG_WPS */
382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700384
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800385#ifdef CONFIG_MACSEC
386 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
387 ieee802_1x_create_preshared_mka(wpa_s, ssid);
388 else
389 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
390#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800391#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392}
393
394
395/**
396 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
397 * @wpa_s: Pointer to wpa_supplicant data
398 * @ssid: Configuration data for the network
399 *
400 * This function is used to configure WPA state machine and related parameters
401 * to a mode where WPA is not enabled. This is called as part of the
402 * authentication configuration when the selected network does not use WPA.
403 */
404void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
405 struct wpa_ssid *ssid)
406{
Hai Shalomfdcde762020-04-02 11:19:20 -0700407#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700409#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000410 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700411
412 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
413 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
414 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
415 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
416 else
417 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
418 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
419 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700420 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Sunil Ravic0f5d412024-09-11 22:12:49 +0000421 wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
422 wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
423 wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700425 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
426 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
428 wpa_s->group_cipher = WPA_CIPHER_NONE;
429 wpa_s->mgmt_group_cipher = 0;
430
Hai Shalomfdcde762020-04-02 11:19:20 -0700431#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 for (i = 0; i < NUM_WEP_KEYS; i++) {
433 if (ssid->wep_key_len[i] > 5) {
434 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
435 wpa_s->group_cipher = WPA_CIPHER_WEP104;
436 break;
437 } else if (ssid->wep_key_len[i] > 0) {
438 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
439 wpa_s->group_cipher = WPA_CIPHER_WEP40;
440 break;
441 }
442 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700443#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
445 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
446 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
447 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
448 wpa_s->pairwise_cipher);
449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
451 wpa_s->mgmt_group_cipher);
Sunil Ravi7f769292024-07-23 22:21:32 +0000452 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700453
454 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000455 os_memset(&mlo, 0, sizeof(mlo));
456 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457}
458
459
Dmitry Shmidt04949592012-07-19 12:16:46 -0700460void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800461{
462 int i;
463 if (wpa_s->hw.modes == NULL)
464 return;
465
466 for (i = 0; i < wpa_s->hw.num_modes; i++) {
467 os_free(wpa_s->hw.modes[i].channels);
468 os_free(wpa_s->hw.modes[i].rates);
469 }
470
471 os_free(wpa_s->hw.modes);
472 wpa_s->hw.modes = NULL;
473}
474
475
Hai Shalomc1a21442022-02-04 13:43:00 -0800476static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
477 struct wpa_bss_tmp_disallowed *bss)
478{
479 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
480 dl_list_del(&bss->list);
481 os_free(bss);
482}
483
484
Hai Shalom74f70d42019-02-11 14:42:39 -0800485void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800486{
487 struct wpa_bss_tmp_disallowed *bss, *prev;
488
489 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800490 struct wpa_bss_tmp_disallowed, list)
491 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800492}
493
494
Paul Stewart092955c2017-02-06 09:13:09 -0800495void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
496{
497 struct fils_hlp_req *req;
498
499 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
500 list)) != NULL) {
501 dl_list_del(&req->list);
502 wpabuf_free(req->pkt);
503 os_free(req);
504 }
505}
506
507
Hai Shalomfdcde762020-04-02 11:19:20 -0700508void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
509{
510 struct wpa_supplicant *wpa_s = eloop_ctx;
511
512 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
513 return;
514 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
515 wpa_bss_flush(wpa_s);
516}
517
518
519#ifdef CONFIG_TESTING_OPTIONS
520void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
521{
522 struct driver_signal_override *dso;
523
524 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
525 struct driver_signal_override, list))) {
526 dl_list_del(&dso->list);
527 os_free(dso);
528 }
529}
530#endif /* CONFIG_TESTING_OPTIONS */
531
532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
534{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700535 int i;
536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700538 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539 scard_deinit(wpa_s->scard);
540 wpa_s->scard = NULL;
541 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
542 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
543 l2_packet_deinit(wpa_s->l2);
544 wpa_s->l2 = NULL;
545 if (wpa_s->l2_br) {
546 l2_packet_deinit(wpa_s->l2_br);
547 wpa_s->l2_br = NULL;
548 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800549#ifdef CONFIG_TESTING_OPTIONS
550 l2_packet_deinit(wpa_s->l2_test);
551 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800552 os_free(wpa_s->get_pref_freq_list_override);
553 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700554 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
555 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800556 os_free(wpa_s->extra_sae_rejected_groups);
557 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700558 wpabuf_free(wpa_s->rsne_override_eapol);
559 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800560 wpabuf_free(wpa_s->rsnxe_override_assoc);
561 wpa_s->rsnxe_override_assoc = NULL;
562 wpabuf_free(wpa_s->rsnxe_override_eapol);
563 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700564 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800565#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567 if (wpa_s->conf != NULL) {
568 struct wpa_ssid *ssid;
569 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
570 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571 }
572
573 os_free(wpa_s->confname);
574 wpa_s->confname = NULL;
575
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700576 os_free(wpa_s->confanother);
577 wpa_s->confanother = NULL;
578
Hai Shalomce48b4a2018-09-05 11:41:35 -0700579 os_free(wpa_s->last_con_fail_realm);
580 wpa_s->last_con_fail_realm = NULL;
581 wpa_s->last_con_fail_realm_len = 0;
582
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 wpa_sm_set_eapol(wpa_s->wpa, NULL);
584 eapol_sm_deinit(wpa_s->eapol);
585 wpa_s->eapol = NULL;
586
587 rsn_preauth_deinit(wpa_s->wpa);
588
589#ifdef CONFIG_TDLS
590 wpa_tdls_deinit(wpa_s->wpa);
591#endif /* CONFIG_TDLS */
592
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000593#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800594 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000595#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800597 ptksa_cache_deinit(wpa_s->ptksa);
598 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 wpa_sm_deinit(wpa_s->wpa);
600 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800601 wpa_bssid_ignore_clear(wpa_s);
602
603#ifdef CONFIG_PASN
604 wpas_pasn_auth_stop(wpa_s);
605#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700606
607 wpa_bss_deinit(wpa_s);
608
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700609 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700610 wpa_supplicant_cancel_scan(wpa_s);
611 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800612 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
613#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
614 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
615 wpa_s, NULL);
616#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700617
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700618 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700619 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Sunil Ravi7f769292024-07-23 22:21:32 +0000620 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700622 wpas_wps_deinit(wpa_s);
623
624 wpabuf_free(wpa_s->pending_eapol_rx);
625 wpa_s->pending_eapol_rx = NULL;
626
627#ifdef CONFIG_IBSS_RSN
628 ibss_rsn_deinit(wpa_s->ibss_rsn);
629 wpa_s->ibss_rsn = NULL;
630#endif /* CONFIG_IBSS_RSN */
631
632 sme_deinit(wpa_s);
633
634#ifdef CONFIG_AP
635 wpa_supplicant_ap_deinit(wpa_s);
636#endif /* CONFIG_AP */
637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700639
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800640#ifdef CONFIG_OFFCHANNEL
641 offchannel_deinit(wpa_s);
642#endif /* CONFIG_OFFCHANNEL */
643
644 wpa_supplicant_cancel_sched_scan(wpa_s);
645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646 os_free(wpa_s->next_scan_freqs);
647 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800648
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800649 os_free(wpa_s->manual_scan_freqs);
650 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 os_free(wpa_s->select_network_scan_freqs);
652 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800653
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700654 os_free(wpa_s->manual_sched_scan_freqs);
655 wpa_s->manual_sched_scan_freqs = NULL;
656
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800657 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
658
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700659 /*
660 * Need to remove any pending gas-query radio work before the
661 * gas_query_deinit() call because gas_query::work has not yet been set
662 * for works that have not been started. gas_query_free() will be unable
663 * to cancel such pending radio works and once the pending gas-query
664 * radio work eventually gets removed, the deinit notification call to
665 * gas_query_start_cb() would result in dereferencing freed memory.
666 */
667 if (wpa_s->radio)
668 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800669 gas_query_deinit(wpa_s->gas);
670 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700671 gas_server_deinit(wpa_s->gas_server);
672 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800673
674 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700675
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700676 ieee802_1x_dealloc_kay_sm(wpa_s);
677
Dmitry Shmidt04949592012-07-19 12:16:46 -0700678 os_free(wpa_s->bssid_filter);
679 wpa_s->bssid_filter = NULL;
680
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800681 os_free(wpa_s->disallow_aps_bssid);
682 wpa_s->disallow_aps_bssid = NULL;
683 os_free(wpa_s->disallow_aps_ssid);
684 wpa_s->disallow_aps_ssid = NULL;
685
Dmitry Shmidt04949592012-07-19 12:16:46 -0700686 wnm_bss_keep_alive_deinit(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000687 wnm_btm_reset(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688
689 ext_password_deinit(wpa_s->ext_pw);
690 wpa_s->ext_pw = NULL;
691
692 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800693 wpa_s->last_gas_resp = NULL;
694 wpabuf_free(wpa_s->prev_gas_resp);
695 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700696
697 os_free(wpa_s->last_scan_res);
698 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800699
700#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700701 if (wpa_s->drv_priv)
702 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700703 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800704#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700705
706 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
707 wpabuf_free(wpa_s->vendor_elem[i]);
708 wpa_s->vendor_elem[i] = NULL;
709 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800710
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000711#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800712 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000713#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800714
715 wpa_s->sched_scan_plans_num = 0;
716 os_free(wpa_s->sched_scan_plans);
717 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800718
719#ifdef CONFIG_MBO
720 wpa_s->non_pref_chan_num = 0;
721 os_free(wpa_s->non_pref_chan);
722 wpa_s->non_pref_chan = NULL;
723#endif /* CONFIG_MBO */
724
725 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700726
727 wpabuf_free(wpa_s->lci);
728 wpa_s->lci = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000729#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800730 wpas_clear_beacon_rep_data(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000731#endif /* CONFIG_NO_RRM */
Paul Stewart092955c2017-02-06 09:13:09 -0800732
733#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
734#ifdef CONFIG_MESH
735 {
736 struct external_pmksa_cache *entry;
737
738 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
739 struct external_pmksa_cache,
740 list)) != NULL) {
741 dl_list_del(&entry->list);
742 os_free(entry->pmksa_cache);
743 os_free(entry);
744 }
745 }
746#endif /* CONFIG_MESH */
747#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
748
749 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800750
751 wpabuf_free(wpa_s->ric_ies);
752 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700753
754#ifdef CONFIG_DPP
755 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700756 dpp_global_deinit(wpa_s->dpp);
757 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700758#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800759
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000760#ifdef CONFIG_NAN_USD
761 wpas_nan_usd_deinit(wpa_s);
762#endif /* CONFIG_NAN_USD */
763
Hai Shalom60840252021-02-19 19:02:11 -0800764#ifdef CONFIG_PASN
765 wpas_pasn_auth_stop(wpa_s);
766#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000767#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -0800768 wpas_scs_deinit(wpa_s);
769 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000770#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000771
772#ifdef CONFIG_OWE
773 os_free(wpa_s->owe_trans_scan_freq);
774 wpa_s->owe_trans_scan_freq = NULL;
775#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776}
777
778
779/**
780 * wpa_clear_keys - Clear keys configured for the driver
781 * @wpa_s: Pointer to wpa_supplicant data
782 * @addr: Previously used BSSID or %NULL if not available
783 *
784 * This function clears the encryption keys that has been previously configured
785 * for the driver.
786 */
787void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
788{
Hai Shalomc3565922019-10-28 11:58:20 -0700789 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790
791 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800792 for (i = 0; i < max; i++) {
793 if (wpa_s->keys_cleared & BIT(i))
794 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000795 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700796 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800797 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700798 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
799 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800800 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700801 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000802 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
803 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700804 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000805 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
806 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 /* MLME-SETPROTECTION.request(None) */
808 wpa_drv_mlme_setprotection(
809 wpa_s, addr,
810 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
811 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
812 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800813 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814}
815
816
817/**
818 * wpa_supplicant_state_txt - Get the connection state name as a text string
819 * @state: State (wpa_state; WPA_*)
820 * Returns: The state name as a printable text string
821 */
822const char * wpa_supplicant_state_txt(enum wpa_states state)
823{
824 switch (state) {
825 case WPA_DISCONNECTED:
826 return "DISCONNECTED";
827 case WPA_INACTIVE:
828 return "INACTIVE";
829 case WPA_INTERFACE_DISABLED:
830 return "INTERFACE_DISABLED";
831 case WPA_SCANNING:
832 return "SCANNING";
833 case WPA_AUTHENTICATING:
834 return "AUTHENTICATING";
835 case WPA_ASSOCIATING:
836 return "ASSOCIATING";
837 case WPA_ASSOCIATED:
838 return "ASSOCIATED";
839 case WPA_4WAY_HANDSHAKE:
840 return "4WAY_HANDSHAKE";
841 case WPA_GROUP_HANDSHAKE:
842 return "GROUP_HANDSHAKE";
843 case WPA_COMPLETED:
844 return "COMPLETED";
845 default:
846 return "UNKNOWN";
847 }
848}
849
850
851#ifdef CONFIG_BGSCAN
852
Hai Shalom899fcc72020-10-19 14:38:18 -0700853static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
854{
855 if (wpa_s->bgscan_ssid) {
856 bgscan_deinit(wpa_s);
857 wpa_s->bgscan_ssid = NULL;
858 }
859}
860
861
862/**
863 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
864 * @wpa_s: Pointer to the wpa_supplicant data
865 *
866 * Stop, start, or reconfigure the scan parameters depending on the method.
867 */
868void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800870 const char *name;
871
872 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
873 name = wpa_s->current_ssid->bgscan;
874 else
875 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700876 if (!name || name[0] == '\0') {
877 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800878 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700879 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800880 if (wpas_driver_bss_selection(wpa_s))
881 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800882#ifdef CONFIG_P2P
883 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
884 return;
885#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700886
887 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800888 if (wpa_s->current_ssid) {
889 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
891 "bgscan");
892 /*
893 * Live without bgscan; it is only used as a roaming
894 * optimization, so the initial connection is not
895 * affected.
896 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700897 } else {
898 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700900 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
Sunil Ravi99c035e2024-07-12 01:42:03 +0000901 0, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700902 if (scan_res) {
903 bgscan_notify_scan(wpa_s, scan_res);
904 wpa_scan_results_free(scan_res);
905 }
906 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700907 } else
908 wpa_s->bgscan_ssid = NULL;
909}
910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911#endif /* CONFIG_BGSCAN */
912
913
Dmitry Shmidt04949592012-07-19 12:16:46 -0700914static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
915{
916 if (autoscan_init(wpa_s, 0))
917 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
918}
919
920
921static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
922{
923 autoscan_deinit(wpa_s);
924}
925
926
927void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
928{
929 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
930 wpa_s->wpa_state == WPA_SCANNING) {
931 autoscan_deinit(wpa_s);
932 wpa_supplicant_start_autoscan(wpa_s);
933 }
934}
935
936
Sunil Ravi7f769292024-07-23 22:21:32 +0000937static void wpas_verify_ssid_beacon(void *eloop_ctx, void *timeout_ctx)
938{
939 struct wpa_supplicant *wpa_s = eloop_ctx;
940 struct wpa_bss *bss;
941 const u8 *ssid;
942 size_t ssid_len;
943
944 if (!wpa_s->current_ssid || !wpa_s->current_bss)
945 return;
946
947 ssid = wpa_s->current_bss->ssid;
948 ssid_len = wpa_s->current_bss->ssid_len;
949
950 if (wpa_s->current_ssid->ssid_len &&
951 (wpa_s->current_ssid->ssid_len != ssid_len ||
952 os_memcmp(wpa_s->current_ssid->ssid, ssid, ssid_len) != 0))
953 return;
954
955 if (wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
956 !wpa_s->bigtk_set || wpa_s->ssid_verified)
957 return;
958
959 wpa_printf(MSG_DEBUG,
960 "SSID not yet verified; check if the driver has received a verified Beacon frame");
961 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
962 return;
963
964 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
965 if (!bss)
966 return;
967 wpa_printf(MSG_DEBUG, "The current beacon time stamp: 0x%llx",
968 (long long unsigned int) bss->tsf);
969 if (bss->tsf > wpa_s->first_beacon_tsf) {
970 const u8 *ie;
971
972 wpa_printf(MSG_DEBUG,
973 "Verified Beacon frame has been received");
974 wpa_s->beacons_checked++;
975
976 ie = wpa_bss_get_ie_beacon(bss, WLAN_EID_SSID);
977 if (ie && ie[1] == ssid_len &&
978 os_memcmp(&ie[2], ssid, ssid_len) == 0) {
979 wpa_printf(MSG_DEBUG,
980 "SSID verified based on a Beacon frame and beacon protection");
981 wpa_s->ssid_verified = true;
982 return;
983 }
984
985 /* TODO: Multiple BSSID element */
986 }
987
988 if (wpa_s->beacons_checked < 16) {
989 eloop_register_timeout(wpa_s->next_beacon_check, 0,
990 wpas_verify_ssid_beacon, wpa_s, NULL);
991 wpa_s->next_beacon_check++;
992 }
993}
994
995
996static void wpas_verify_ssid_beacon_prot(struct wpa_supplicant *wpa_s)
997{
998 struct wpa_bss *bss;
999
1000 wpa_printf(MSG_DEBUG,
1001 "SSID not yet verified; try to verify using beacon protection");
1002 /* Fetch the current scan result which is likely based on not yet
1003 * verified payload since the current BIGTK was just received. Any
1004 * newer update in the future with a larger timestamp value is an
1005 * indication that a verified Beacon frame has been received. */
1006 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
1007 return;
1008
1009 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
1010 if (!bss)
1011 return;
1012 wpa_printf(MSG_DEBUG, "The initial beacon time stamp: 0x%llx",
1013 (long long unsigned int) bss->tsf);
1014 wpa_s->first_beacon_tsf = bss->tsf;
1015 wpa_s->beacons_checked = 0;
1016 wpa_s->next_beacon_check = 1;
1017 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
1018 eloop_register_timeout(1, 0, wpas_verify_ssid_beacon, wpa_s, NULL);
1019}
1020
1021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022/**
1023 * wpa_supplicant_set_state - Set current connection state
1024 * @wpa_s: Pointer to wpa_supplicant data
1025 * @state: The new connection state
1026 *
1027 * This function is called whenever the connection state changes, e.g.,
1028 * association is completed for WPA/WPA2 4-Way Handshake is started.
1029 */
1030void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
1031 enum wpa_states state)
1032{
1033 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -07001034#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -07001035 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001036#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037
1038 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
1039 wpa_supplicant_state_txt(wpa_s->wpa_state),
1040 wpa_supplicant_state_txt(state));
1041
Hai Shalom74f70d42019-02-11 14:42:39 -08001042 if (state == WPA_COMPLETED &&
1043 os_reltime_initialized(&wpa_s->roam_start)) {
1044 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
1045 wpa_s->roam_start.sec = 0;
1046 wpa_s->roam_start.usec = 0;
1047 wpas_notify_auth_changed(wpa_s);
1048 wpas_notify_roam_time(wpa_s);
1049 wpas_notify_roam_complete(wpa_s);
1050 } else if (state == WPA_DISCONNECTED &&
1051 os_reltime_initialized(&wpa_s->roam_start)) {
1052 wpa_s->roam_start.sec = 0;
1053 wpa_s->roam_start.usec = 0;
1054 wpa_s->roam_time.sec = 0;
1055 wpa_s->roam_time.usec = 0;
1056 wpas_notify_roam_complete(wpa_s);
1057 }
1058
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08001059 if (state == WPA_INTERFACE_DISABLED) {
1060 /* Assure normal scan when interface is restored */
1061 wpa_s->normal_scans = 0;
1062 }
1063
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001064 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001065 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001066 /* Reinitialize normal_scan counter */
1067 wpa_s->normal_scans = 0;
1068 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001069
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001070#ifdef CONFIG_P2P
1071 /*
1072 * P2PS client has to reply to Probe Request frames received on the
1073 * group operating channel. Enable Probe Request frame reporting for
1074 * P2P connected client in case p2p_cli_probe configuration property is
1075 * set to 1.
1076 */
1077 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
1078 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
1079 wpa_s->current_ssid->p2p_group) {
1080 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
1081 wpa_dbg(wpa_s, MSG_DEBUG,
1082 "P2P: Enable CLI Probe Request RX reporting");
1083 wpa_s->p2p_cli_probe =
1084 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
1085 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
1086 wpa_dbg(wpa_s, MSG_DEBUG,
1087 "P2P: Disable CLI Probe Request RX reporting");
1088 wpa_s->p2p_cli_probe = 0;
1089 wpa_drv_probe_req_report(wpa_s, 0);
1090 }
1091 }
1092#endif /* CONFIG_P2P */
1093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094 if (state != WPA_SCANNING)
1095 wpa_supplicant_notify_scanning(wpa_s, 0);
1096
1097 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001099 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001100 char mld_addr[50];
1101
1102 mld_addr[0] = '\0';
1103 if (wpa_s->valid_links)
1104 os_snprintf(mld_addr, sizeof(mld_addr),
1105 " ap_mld_addr=" MACSTR,
1106 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107
1108#ifdef CONFIG_SME
1109 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1110 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1111 fils_hlp_sent = 1;
1112#endif /* CONFIG_SME */
1113 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1114 wpa_auth_alg_fils(wpa_s->auth_alg))
1115 fils_hlp_sent = 1;
1116
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001117#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001119 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001120 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001122 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001123 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001124#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001125 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001126 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128 wpa_drv_set_operstate(wpa_s, 1);
1129#ifndef IEEE8021X_EAPOL
1130 wpa_drv_set_supp_port(wpa_s, 1);
1131#endif /* IEEE8021X_EAPOL */
1132 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001133 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001135
1136 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001137
1138#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1139 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001140 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001141#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001142#ifdef CONFIG_OWE
1143 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1144 wpas_update_owe_connect_params(wpa_s);
1145#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001146#ifdef CONFIG_HS20
1147 hs20_configure_frame_filters(wpa_s);
1148#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1150 state == WPA_ASSOCIATED) {
1151 wpa_s->new_connection = 1;
1152 wpa_drv_set_operstate(wpa_s, 0);
1153#ifndef IEEE8021X_EAPOL
1154 wpa_drv_set_supp_port(wpa_s, 0);
1155#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001156 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001157 }
1158 wpa_s->wpa_state = state;
1159
1160#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001161 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1162 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001163 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001164 wpa_supplicant_stop_bgscan(wpa_s);
1165#endif /* CONFIG_BGSCAN */
1166
Hai Shalom5f92bc92019-04-18 11:54:11 -07001167 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001168 wpa_supplicant_stop_autoscan(wpa_s);
1169
1170 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1171 wpa_supplicant_start_autoscan(wpa_s);
1172
Sunil Ravi99c035e2024-07-12 01:42:03 +00001173 if (state == WPA_COMPLETED || state == WPA_INTERFACE_DISABLED ||
1174 state == WPA_INACTIVE)
1175 wnm_btm_reset(wpa_s);
1176
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001177#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001178 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1179 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001180#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001182 if (wpa_s->wpa_state != old_state) {
1183 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1184
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001185 /*
1186 * Notify the P2P Device interface about a state change in one
1187 * of the interfaces.
1188 */
1189 wpas_p2p_indicate_state_change(wpa_s);
1190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191 if (wpa_s->wpa_state == WPA_COMPLETED ||
1192 old_state == WPA_COMPLETED)
1193 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001194#ifdef CONFIG_DPP2
1195 if (wpa_s->wpa_state == WPA_COMPLETED)
1196 wpas_dpp_connected(wpa_s);
1197#endif /* CONFIG_DPP2 */
Sunil Ravi7f769292024-07-23 22:21:32 +00001198
1199 if (wpa_s->wpa_state == WPA_COMPLETED &&
1200 wpa_s->bigtk_set && !wpa_s->ssid_verified)
1201 wpas_verify_ssid_beacon_prot(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 }
Hai Shalomc3565922019-10-28 11:58:20 -07001203#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1204 if (update_fils_connect_params)
1205 wpas_update_fils_connect_params(wpa_s);
1206#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207}
1208
1209
1210void wpa_supplicant_terminate_proc(struct wpa_global *global)
1211{
1212 int pending = 0;
1213#ifdef CONFIG_WPS
1214 struct wpa_supplicant *wpa_s = global->ifaces;
1215 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001216 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001217 if (wpas_wps_terminate_pending(wpa_s) == 1)
1218 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001219#ifdef CONFIG_P2P
1220 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1221 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1222 wpas_p2p_disconnect(wpa_s);
1223#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001224 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001225 }
1226#endif /* CONFIG_WPS */
1227 if (pending)
1228 return;
1229 eloop_terminate();
1230}
1231
1232
1233static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1234{
1235 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 wpa_supplicant_terminate_proc(global);
1237}
1238
1239
1240void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1241{
1242 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001243 enum wpa_states new_state;
1244
1245 if (old_state == WPA_SCANNING)
1246 new_state = WPA_SCANNING;
1247 else
1248 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001249
1250 wpa_s->pairwise_cipher = 0;
1251 wpa_s->group_cipher = 0;
1252 wpa_s->mgmt_group_cipher = 0;
1253 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001254 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001256 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001257
1258 if (wpa_s->wpa_state != old_state)
1259 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1260}
1261
1262
1263/**
1264 * wpa_supplicant_reload_configuration - Reload configuration data
1265 * @wpa_s: Pointer to wpa_supplicant data
1266 * Returns: 0 on success or -1 if configuration parsing failed
1267 *
1268 * This function can be used to request that the configuration data is reloaded
1269 * (e.g., after configuration file change). This function is reloading
1270 * configuration only for one interface, so this may need to be called multiple
1271 * times if %wpa_supplicant is controlling multiple interfaces and all
1272 * interfaces need reconfiguration.
1273 */
1274int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1275{
1276 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001277 int reconf_ctrl;
1278 int old_ap_scan;
1279
1280 if (wpa_s->confname == NULL)
1281 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001282 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283 if (conf == NULL) {
1284 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1285 "file '%s' - exiting", wpa_s->confname);
1286 return -1;
1287 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001288 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001289 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001290 wpa_msg(wpa_s, MSG_ERROR,
1291 "Failed to parse the configuration file '%s' - exiting",
1292 wpa_s->confanother);
1293 return -1;
1294 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296 conf->changed_parameters = (unsigned int) -1;
1297
1298 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1299 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1300 os_strcmp(conf->ctrl_interface,
1301 wpa_s->conf->ctrl_interface) != 0);
1302
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001303 if (reconf_ctrl) {
1304 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305 wpa_s->ctrl_iface = NULL;
1306 }
1307
1308 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001309 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001310 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1311 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001312 wpa_supplicant_deauthenticate(wpa_s,
1313 WLAN_REASON_DEAUTH_LEAVING);
1314 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315
1316 /*
1317 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001318 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001319 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001320 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1321 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1322 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323 /*
1324 * Clear forced success to clear EAP state for next
1325 * authentication.
1326 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001327 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001328 }
1329 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1330 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001331 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1333 rsn_preauth_deinit(wpa_s->wpa);
1334
1335 old_ap_scan = wpa_s->conf->ap_scan;
1336 wpa_config_free(wpa_s->conf);
1337 wpa_s->conf = conf;
1338 if (old_ap_scan != wpa_s->conf->ap_scan)
1339 wpas_notify_ap_scan_changed(wpa_s);
1340
1341 if (reconf_ctrl)
1342 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1343
1344 wpa_supplicant_update_config(wpa_s);
1345
1346 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001347 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348 wpa_s->reassociate = 1;
1349 wpa_supplicant_req_scan(wpa_s, 0, 0);
1350 }
Hai Shalom60840252021-02-19 19:02:11 -08001351 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001352 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1353 return 0;
1354}
1355
1356
1357static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1358{
1359 struct wpa_global *global = signal_ctx;
1360 struct wpa_supplicant *wpa_s;
1361 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1362 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1363 sig);
1364 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1365 wpa_supplicant_terminate_proc(global);
1366 }
1367 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001368
1369 if (wpa_debug_reopen_file() < 0) {
1370 /* Ignore errors since we cannot really do much to fix this */
1371 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1372 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373}
1374
1375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1377 struct wpa_ssid *ssid,
1378 struct wpa_ie_data *ie)
1379{
1380 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1381 if (ret) {
1382 if (ret == -2) {
1383 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1384 "from association info");
1385 }
1386 return -1;
1387 }
1388
1389 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1390 "cipher suites");
1391 if (!(ie->group_cipher & ssid->group_cipher)) {
1392 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1393 "cipher 0x%x (mask 0x%x) - reject",
1394 ie->group_cipher, ssid->group_cipher);
1395 return -1;
1396 }
1397 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1398 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1399 "cipher 0x%x (mask 0x%x) - reject",
1400 ie->pairwise_cipher, ssid->pairwise_cipher);
1401 return -1;
1402 }
1403 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1404 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1405 "management 0x%x (mask 0x%x) - reject",
1406 ie->key_mgmt, ssid->key_mgmt);
1407 return -1;
1408 }
1409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001410 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001411 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1413 "that does not support management frame protection - "
1414 "reject");
1415 return -1;
1416 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417
1418 return 0;
1419}
1420
1421
Hai Shalom021b0b52019-04-10 11:17:58 -07001422static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1423 int freq)
1424{
1425 if (!ie->has_group)
1426 ie->group_cipher = wpa_default_rsn_cipher(freq);
1427 if (!ie->has_pairwise)
1428 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1429 return (ie->group_cipher & ssid->group_cipher) &&
1430 (ie->pairwise_cipher & ssid->pairwise_cipher);
1431}
1432
1433
Hai Shalomc1a21442022-02-04 13:43:00 -08001434void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1435 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1436{
1437 int sel;
1438
1439 sel = ie->mgmt_group_cipher;
1440 if (ssid->group_mgmt_cipher)
1441 sel &= ssid->group_mgmt_cipher;
1442 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1443 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1444 sel = 0;
1445 wpa_dbg(wpa_s, MSG_DEBUG,
1446 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1447 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1448 if (sel & WPA_CIPHER_AES_128_CMAC) {
1449 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1450 wpa_dbg(wpa_s, MSG_DEBUG,
1451 "WPA: using MGMT group cipher AES-128-CMAC");
1452 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1453 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1454 wpa_dbg(wpa_s, MSG_DEBUG,
1455 "WPA: using MGMT group cipher BIP-GMAC-128");
1456 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1457 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1458 wpa_dbg(wpa_s, MSG_DEBUG,
1459 "WPA: using MGMT group cipher BIP-GMAC-256");
1460 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1461 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1462 wpa_dbg(wpa_s, MSG_DEBUG,
1463 "WPA: using MGMT group cipher BIP-CMAC-256");
1464 } else {
1465 wpa_s->mgmt_group_cipher = 0;
1466 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1467 }
1468 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1469 wpa_s->mgmt_group_cipher);
1470 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1471 wpas_get_ssid_pmf(wpa_s, ssid));
1472}
1473
Sunil Ravi77d572f2023-01-17 23:58:31 +00001474/**
1475 * wpa_supplicant_get_psk - Get PSK from config or external database
1476 * @wpa_s: Pointer to wpa_supplicant data
1477 * @bss: Scan results for the selected BSS, or %NULL if not available
1478 * @ssid: Configuration data for the selected network
1479 * @psk: Buffer for the PSK
1480 * Returns: 0 on success or -1 if configuration parsing failed
1481 *
1482 * This function obtains the PSK for a network, either included inline in the
1483 * config or retrieved from an external database.
1484 */
1485static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1486 struct wpa_bss *bss, struct wpa_ssid *ssid,
1487 u8 *psk)
1488{
1489 if (ssid->psk_set) {
1490 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1491 ssid->psk, PMK_LEN);
1492 os_memcpy(psk, ssid->psk, PMK_LEN);
1493 return 0;
1494 }
1495
1496#ifndef CONFIG_NO_PBKDF2
1497 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1498 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1499 4096, psk, PMK_LEN) != 0) {
1500 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1501 return -1;
1502 }
1503 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1504 psk, PMK_LEN);
1505 return 0;
1506 }
1507#endif /* CONFIG_NO_PBKDF2 */
1508
1509#ifdef CONFIG_EXT_PASSWORD
1510 if (ssid->ext_psk) {
1511 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1512 ssid->ext_psk);
1513 char pw_str[64 + 1];
1514
1515 if (!pw) {
1516 wpa_msg(wpa_s, MSG_INFO,
1517 "EXT PW: No PSK found from external storage");
1518 return -1;
1519 }
1520
1521 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1522 wpa_msg(wpa_s, MSG_INFO,
1523 "EXT PW: Unexpected PSK length %d in external storage",
1524 (int) wpabuf_len(pw));
1525 ext_password_free(pw);
1526 return -1;
1527 }
1528
1529 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1530 pw_str[wpabuf_len(pw)] = '\0';
1531
1532#ifndef CONFIG_NO_PBKDF2
1533 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1534 {
1535 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1536 4096, psk, PMK_LEN) != 0) {
1537 wpa_msg(wpa_s, MSG_WARNING,
1538 "Error in pbkdf2_sha1()");
1539 forced_memzero(pw_str, sizeof(pw_str));
1540 ext_password_free(pw);
1541 return -1;
1542 }
1543 wpa_hexdump_key(MSG_MSGDUMP,
1544 "PSK (from external passphrase)",
1545 psk, PMK_LEN);
1546 } else
1547#endif /* CONFIG_NO_PBKDF2 */
1548 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1549 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1550 wpa_msg(wpa_s, MSG_INFO,
1551 "EXT PW: Invalid PSK hex string");
1552 forced_memzero(pw_str, sizeof(pw_str));
1553 ext_password_free(pw);
1554 return -1;
1555 }
1556 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1557 psk, PMK_LEN);
1558 } else {
1559 wpa_msg(wpa_s, MSG_INFO,
1560 "EXT PW: No suitable PSK available");
1561 forced_memzero(pw_str, sizeof(pw_str));
1562 ext_password_free(pw);
1563 return -1;
1564 }
1565
1566 forced_memzero(pw_str, sizeof(pw_str));
1567 ext_password_free(pw);
1568
1569 return 0;
1570 }
1571#endif /* CONFIG_EXT_PASSWORD */
1572
1573 return -1;
1574}
1575
Hai Shalomc1a21442022-02-04 13:43:00 -08001576
Sunil Ravi89eba102022-09-13 21:04:37 -07001577static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1578 struct wpa_ssid *ssid)
1579{
1580 int akm_count = wpa_s->max_num_akms;
1581 u8 capab = 0;
1582
1583 if (akm_count < 2)
1584 return;
1585
1586 akm_count--;
1587 wpa_s->allowed_key_mgmts = 0;
1588 switch (wpa_s->key_mgmt) {
1589 case WPA_KEY_MGMT_PSK:
1590 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1591 akm_count--;
1592 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1593 }
1594 if (!akm_count)
1595 break;
1596 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1597 akm_count--;
1598 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1599 }
1600 if (!akm_count)
1601 break;
1602 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1603 wpa_s->allowed_key_mgmts |=
1604 WPA_KEY_MGMT_PSK_SHA256;
1605 break;
1606 case WPA_KEY_MGMT_PSK_SHA256:
1607 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1608 akm_count--;
1609 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1610 }
1611 if (!akm_count)
1612 break;
1613 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1614 akm_count--;
1615 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1616 }
1617 if (!akm_count)
1618 break;
1619 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1620 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1621 break;
1622 case WPA_KEY_MGMT_SAE:
1623 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1624 akm_count--;
1625 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1626 }
1627 if (!akm_count)
1628 break;
1629 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1630 akm_count--;
1631 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1632 }
1633 if (!akm_count)
1634 break;
1635 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1636 wpa_s->allowed_key_mgmts |=
1637 WPA_KEY_MGMT_PSK_SHA256;
1638 break;
1639 case WPA_KEY_MGMT_SAE_EXT_KEY:
1640 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1641 akm_count--;
1642 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1643 }
1644 if (!akm_count)
1645 break;
1646 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1647 akm_count--;
1648 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1649 }
1650 if (!akm_count)
1651 break;
1652 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1653 wpa_s->allowed_key_mgmts |=
1654 WPA_KEY_MGMT_PSK_SHA256;
1655 break;
1656 default:
1657 return;
1658 }
1659
Sunil Ravi77d572f2023-01-17 23:58:31 +00001660 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1661 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001662 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1663#ifdef CONFIG_SAE_PK
1664 if (ssid->sae_pk)
1665 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1666#endif /* CONFIG_SAE_PK */
1667
1668 if (!((wpa_s->allowed_key_mgmts &
1669 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1670 return;
1671
1672 if (!wpa_s->rsnxe_len) {
1673 wpa_s->rsnxe_len = 3;
1674 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1675 wpa_s->rsnxe[1] = 1;
1676 wpa_s->rsnxe[2] = 0;
1677 }
1678
1679 wpa_s->rsnxe[2] |= capab;
1680}
1681
1682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001683/**
1684 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1685 * @wpa_s: Pointer to wpa_supplicant data
1686 * @bss: Scan results for the selected BSS, or %NULL if not available
1687 * @ssid: Configuration data for the selected network
1688 * @wpa_ie: Buffer for the WPA/RSN IE
1689 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1690 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001691 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 * Returns: 0 on success or -1 on failure
1693 *
1694 * This function is used to configure authentication and encryption parameters
1695 * based on the network configuration and scan result for the selected BSS (if
1696 * available).
1697 */
1698int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1699 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001700 u8 *wpa_ie, size_t *wpa_ie_len,
1701 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702{
1703 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001704 int sel, proto;
1705 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001706 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001707 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708
1709 if (bss) {
1710 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
Sunil Ravi7f769292024-07-23 22:21:32 +00001711 bss_rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
1712 bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001713 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001714 } else {
1715 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1716 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717
1718 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1719 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001720 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 (ie.key_mgmt & ssid->key_mgmt)) {
1722 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1723 proto = WPA_PROTO_RSN;
1724 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001725 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726 (ie.group_cipher & ssid->group_cipher) &&
1727 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1728 (ie.key_mgmt & ssid->key_mgmt)) {
1729 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1730 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001731#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001732 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1733 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1734 (ie.group_cipher & ssid->group_cipher) &&
1735 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1736 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001737 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001738 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001739 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1740 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1741 (ie.group_cipher & ssid->group_cipher) &&
1742 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1743 (ie.key_mgmt & ssid->key_mgmt)) {
1744 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1745 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001746#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747 } else if (bss) {
1748 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001749 wpa_dbg(wpa_s, MSG_DEBUG,
1750 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1751 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1752 ssid->key_mgmt);
1753 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1754 MAC2STR(bss->bssid),
1755 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1756 bss_wpa ? " WPA" : "",
1757 bss_rsn ? " RSN" : "",
1758 bss_osen ? " OSEN" : "");
1759 if (bss_rsn) {
1760 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1761 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1762 wpa_dbg(wpa_s, MSG_DEBUG,
1763 "Could not parse RSN element");
1764 } else {
1765 wpa_dbg(wpa_s, MSG_DEBUG,
1766 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1767 ie.pairwise_cipher, ie.group_cipher,
1768 ie.key_mgmt);
1769 }
1770 }
1771 if (bss_wpa) {
1772 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1773 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1774 wpa_dbg(wpa_s, MSG_DEBUG,
1775 "Could not parse WPA element");
1776 } else {
1777 wpa_dbg(wpa_s, MSG_DEBUG,
1778 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1779 ie.pairwise_cipher, ie.group_cipher,
1780 ie.key_mgmt);
1781 }
1782 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783 return -1;
1784 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001785 if (ssid->proto & WPA_PROTO_OSEN)
1786 proto = WPA_PROTO_OSEN;
1787 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788 proto = WPA_PROTO_RSN;
1789 else
1790 proto = WPA_PROTO_WPA;
1791 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1792 os_memset(&ie, 0, sizeof(ie));
1793 ie.group_cipher = ssid->group_cipher;
1794 ie.pairwise_cipher = ssid->pairwise_cipher;
1795 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001796 ie.mgmt_group_cipher = 0;
1797 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1798 if (ssid->group_mgmt_cipher &
1799 WPA_CIPHER_BIP_GMAC_256)
1800 ie.mgmt_group_cipher =
1801 WPA_CIPHER_BIP_GMAC_256;
1802 else if (ssid->group_mgmt_cipher &
1803 WPA_CIPHER_BIP_CMAC_256)
1804 ie.mgmt_group_cipher =
1805 WPA_CIPHER_BIP_CMAC_256;
1806 else if (ssid->group_mgmt_cipher &
1807 WPA_CIPHER_BIP_GMAC_128)
1808 ie.mgmt_group_cipher =
1809 WPA_CIPHER_BIP_GMAC_128;
1810 else
1811 ie.mgmt_group_cipher =
1812 WPA_CIPHER_AES_128_CMAC;
1813 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001814#ifdef CONFIG_OWE
1815 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1816 !ssid->owe_only &&
1817 !bss_wpa && !bss_rsn && !bss_osen) {
1818 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1819 wpa_s->wpa_proto = 0;
1820 *wpa_ie_len = 0;
1821 return 0;
1822 }
1823#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1825 "based on configuration");
1826 } else
1827 proto = ie.proto;
1828 }
1829
1830 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1831 "pairwise %d key_mgmt %d proto %d",
1832 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001833 if (ssid->ieee80211w) {
1834 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1835 ie.mgmt_group_cipher);
1836 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001838 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1840 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001841 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842
1843 if (bss || !wpa_s->ap_ies_from_associnfo) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00001844 const u8 *rsnoe = NULL, *rsno2e = NULL, *rsnxoe = NULL;
1845
1846 if (bss) {
1847 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1848 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
1849 rsnoe = wpa_bss_get_vendor_ie(
1850 bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
1851 rsno2e = wpa_bss_get_vendor_ie(
1852 bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
1853 rsnxoe = wpa_bss_get_vendor_ie(
1854 bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
1855 }
1856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001857 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1858 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1859 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001860 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1861 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
Sunil Ravic0f5d412024-09-11 22:12:49 +00001862 bss_rsnx ? 2 + bss_rsnx[1] : 0) ||
1863 wpa_sm_set_ap_rsne_override(wpa_s->wpa, rsnoe,
1864 rsnoe ? 2 + rsnoe[1] : 0) ||
1865 wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
1866 rsno2e ? 2 + rsno2e[1] : 0) ||
1867 wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
1868 rsnxoe ? 2 + rsnxoe[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 return -1;
1870 }
1871
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001872#ifdef CONFIG_NO_WPA
1873 wpa_s->group_cipher = WPA_CIPHER_NONE;
1874 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1875#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001877 wpa_dbg(wpa_s, MSG_DEBUG,
1878 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1879 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001880 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1881 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001882 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1883 "cipher");
1884 return -1;
1885 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001886 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1887 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001888
1889 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001890 wpa_dbg(wpa_s, MSG_DEBUG,
1891 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1892 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001893 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1894 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001895 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1896 "cipher");
1897 return -1;
1898 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001899 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1900 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001901#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902
1903 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001904#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001905 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1906 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001907 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001908 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1909 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001910#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001911#ifdef CONFIG_IEEE80211R
1912 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1913 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1914 sel &= ~WPA_KEY_MGMT_FT;
1915#endif /* CONFIG_IEEE80211R */
1916 wpa_dbg(wpa_s, MSG_DEBUG,
1917 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1918 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001919 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001920#ifdef CONFIG_IEEE80211R
1921#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001922 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1923 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001924 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1925 wpa_dbg(wpa_s, MSG_DEBUG,
1926 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001927 if (!ssid->ft_eap_pmksa_caching &&
1928 pmksa_cache_get_current(wpa_s->wpa)) {
1929 /* PMKSA caching with FT may have interoperability
1930 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001931 wpa_dbg(wpa_s, MSG_DEBUG,
1932 "WPA: Disable PMKSA caching for FT/802.1X connection");
1933 pmksa_cache_clear_current(wpa_s->wpa);
1934 }
1935#endif /* CONFIG_SHA384 */
1936#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001937#ifdef CONFIG_SUITEB192
1938 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1939 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1940 wpa_dbg(wpa_s, MSG_DEBUG,
1941 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1942#endif /* CONFIG_SUITEB192 */
1943#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001944 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1945 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1946 wpa_dbg(wpa_s, MSG_DEBUG,
1947 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001948#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001949#ifdef CONFIG_SHA384
1950 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1951 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1952 wpa_dbg(wpa_s, MSG_DEBUG,
1953 "WPA: using KEY_MGMT 802.1X with SHA384");
1954#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001955#ifdef CONFIG_FILS
1956#ifdef CONFIG_IEEE80211R
1957 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1958 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1959 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001960#endif /* CONFIG_IEEE80211R */
1961 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1962 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1963 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001964#ifdef CONFIG_IEEE80211R
1965 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1966 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1967 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1968#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001969 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1970 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1971 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1972#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001974 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1975 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1977 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001978 if (!ssid->ft_eap_pmksa_caching &&
1979 pmksa_cache_get_current(wpa_s->wpa)) {
1980 /* PMKSA caching with FT may have interoperability
1981 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001982 wpa_dbg(wpa_s, MSG_DEBUG,
1983 "WPA: Disable PMKSA caching for FT/802.1X connection");
1984 pmksa_cache_clear_current(wpa_s->wpa);
1985 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001986#endif /* CONFIG_IEEE80211R */
1987#ifdef CONFIG_DPP
1988 } else if (sel & WPA_KEY_MGMT_DPP) {
1989 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1990 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1991#endif /* CONFIG_DPP */
1992#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001993 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1994 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1995 wpa_dbg(wpa_s, MSG_DEBUG,
1996 "RSN: using KEY_MGMT FT/SAE (ext key)");
1997 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1998 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1999 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07002000 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
2001 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
2002 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
2003 } else if (sel & WPA_KEY_MGMT_SAE) {
2004 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
2005 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
2006#endif /* CONFIG_SAE */
2007#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
2009 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
2010 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
2011#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2013 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
2014 wpa_dbg(wpa_s, MSG_DEBUG,
2015 "WPA: using KEY_MGMT 802.1X with SHA256");
2016 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
2017 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
2018 wpa_dbg(wpa_s, MSG_DEBUG,
2019 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
2021 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
2022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
2023 } else if (sel & WPA_KEY_MGMT_PSK) {
2024 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
2025 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
2026 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
2027 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
2028 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002029#ifdef CONFIG_HS20
2030 } else if (sel & WPA_KEY_MGMT_OSEN) {
2031 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
2032 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
2033#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002034#ifdef CONFIG_OWE
2035 } else if (sel & WPA_KEY_MGMT_OWE) {
2036 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
2037 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
2038#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039 } else {
2040 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
2041 "authenticated key management type");
2042 return -1;
2043 }
2044
2045 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
2046 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
2047 wpa_s->pairwise_cipher);
2048 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
2049
Hai Shalomc3565922019-10-28 11:58:20 -07002050 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002051 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
2052 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07002053 wpa_msg(wpa_s, MSG_INFO,
2054 "RSN: Management frame protection required but the selected AP does not enable it");
2055 return -1;
2056 }
2057
Hai Shalomc1a21442022-02-04 13:43:00 -08002058 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08002059#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08002060 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
2061 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
2062 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08002063#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07002064 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07002065 if ((ssid->sae_password_id ||
2066 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002067 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
2068 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
2069 if (bss && is_6ghz_freq(bss->freq) &&
2070 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
2071 wpa_dbg(wpa_s, MSG_DEBUG,
2072 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
2073 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08002074 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002075 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07002076#ifdef CONFIG_SAE_PK
2077 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
2078 wpa_key_mgmt_sae(ssid->key_mgmt) &&
2079 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
2080 ((ssid->sae_password &&
2081 sae_pk_valid_password(ssid->sae_password)) ||
2082 (!ssid->sae_password && ssid->passphrase &&
2083 sae_pk_valid_password(ssid->passphrase))));
2084#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002085 if (bss && is_6ghz_freq(bss->freq) &&
2086 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
2087 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
2088 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
2089 MGMT_FRAME_PROTECTION_REQUIRED);
2090 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07002091#ifdef CONFIG_TESTING_OPTIONS
2092 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
2093 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07002094 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
2095 wpa_s->oci_freq_override_eapol);
2096 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
2097 wpa_s->oci_freq_override_eapol_g2);
2098 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
2099 wpa_s->oci_freq_override_ft_assoc);
2100 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
2101 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07002102 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
2103 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07002104#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07002105
2106 /* Extended Key ID is only supported in infrastructure BSS so far */
2107 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
2108 (ssid->proto & WPA_PROTO_RSN) &&
2109 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
2110 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
2111 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
2112 int use_ext_key_id = 0;
2113
2114 wpa_msg(wpa_s, MSG_DEBUG,
2115 "WPA: Enable Extended Key ID support");
2116 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
2117 wpa_s->conf->extended_key_id);
2118 if (bss_rsn &&
2119 wpa_s->conf->extended_key_id &&
2120 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
2121 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
2122 use_ext_key_id = 1;
2123 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
2124 use_ext_key_id);
2125 } else {
2126 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
2127 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
2128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002129
Sunil Ravi640215c2023-06-28 23:08:09 +00002130 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2131 * appropriate advertisement of the supported number of PTKSA receive
2132 * counters. In theory, this could be based on a driver capability, but
2133 * in practice all cases using WMM support at least eight replay
2134 * counters, so use a hardcoded value for now since there is no explicit
2135 * driver capability indication for this.
2136 *
2137 * In addition, claim WMM to be enabled if the AP supports it since it
2138 * is far more likely for any current device to support WMM. */
2139 wmm = wpa_s->connection_set &&
2140 (wpa_s->connection_ht || wpa_s->connection_vht ||
2141 wpa_s->connection_he || wpa_s->connection_eht);
2142 if (!wmm && bss)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002143 wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002144 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2145
Sunil Ravi7f769292024-07-23 22:21:32 +00002146 if (ssid->ssid_protection && proto == WPA_PROTO_RSN) {
2147 bool ssid_prot;
2148
2149 /* Enable SSID protection based on the AP advertising support
2150 * for it to avoid potential interoperability issues with
2151 * incorrect AP behavior if we were to send an "unexpected"
2152 * RSNXE with multiple octets of payload. */
2153 ssid_prot = ieee802_11_rsnx_capab(
2154 bss_rsnx, WLAN_RSNX_CAPAB_SSID_PROTECTION);
2155 if (!skip_default_rsne)
2156 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION,
2157 proto == WPA_PROTO_RSN && ssid_prot);
2158 } else {
2159 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, false);
2160 }
2161
Sunil Ravi77d572f2023-01-17 23:58:31 +00002162 if (!skip_default_rsne) {
2163 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2164 wpa_ie_len)) {
2165 wpa_msg(wpa_s, MSG_WARNING,
2166 "RSN: Failed to generate RSNE/WPA IE");
2167 return -1;
2168 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169
Sunil Ravi77d572f2023-01-17 23:58:31 +00002170 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2171 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2172 &wpa_s->rsnxe_len)) {
2173 wpa_msg(wpa_s, MSG_WARNING,
2174 "RSN: Failed to generate RSNXE");
2175 return -1;
2176 }
Hai Shalomc3565922019-10-28 11:58:20 -07002177 }
2178
Hai Shalom021b0b52019-04-10 11:17:58 -07002179 if (0) {
2180#ifdef CONFIG_DPP
2181 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2182 /* Use PMK from DPP network introduction (PMKSA entry) */
2183 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002184#ifdef CONFIG_DPP2
2185 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2186#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002187#endif /* CONFIG_DPP */
2188 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002189 int psk_set = 0;
2190
Sunil Ravi77d572f2023-01-17 23:58:31 +00002191 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2192 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002193
Sunil Ravi77d572f2023-01-17 23:58:31 +00002194 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2195 psk) == 0) {
2196 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2197 NULL);
2198 psk_set = 1;
2199 }
2200 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002201 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002202
Roshan Pius3a1667e2018-07-03 15:17:14 -07002203 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002204 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002205 psk_set = 1;
2206
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002207 if (!psk_set) {
2208 wpa_msg(wpa_s, MSG_INFO,
2209 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002210 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002211 return -1;
2212 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002213#ifdef CONFIG_OWE
2214 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2215 /* OWE Diffie-Hellman exchange in (Re)Association
2216 * Request/Response frames set the PMK, so do not override it
2217 * here. */
2218#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002219 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2221
Hai Shalomfdcde762020-04-02 11:19:20 -07002222 if (ssid->mode != WPAS_MODE_IBSS &&
2223 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2224 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2225 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2226 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2227 wpa_msg(wpa_s, MSG_INFO,
2228 "Disable PTK0 rekey support - replaced with reconnect");
2229 wpa_s->deny_ptk0_rekey = 1;
2230 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2231 } else {
2232 wpa_s->deny_ptk0_rekey = 0;
2233 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2234 }
2235
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002236#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2237 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302238 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002239 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2240 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002241 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2242 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302243 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2244 wpa_dbg(wpa_s, MSG_INFO,
2245 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2246 }
Sunil Ravif42be322022-11-04 03:31:21 +00002247#else
2248 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2249 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2250 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002251#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2252 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002254 return 0;
2255}
2256
2257
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002258static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2259 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002260{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002261#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002262 bool scs = true, mscs = true;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002263#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08002264
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002265 *pos = 0x00;
2266
2267 switch (idx) {
2268 case 0: /* Bits 0-7 */
2269 break;
2270 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002271 if (wpa_s->conf->coloc_intf_reporting) {
2272 /* Bit 13 - Collocated Interference Reporting */
2273 *pos |= 0x20;
2274 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002275 break;
2276 case 2: /* Bits 16-23 */
2277#ifdef CONFIG_WNM
2278 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002279 if ((wpas_driver_bss_selection(wpa_s) ||
2280 !wpa_s->disable_mbo_oce) &&
2281 !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002282 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002283#endif /* CONFIG_WNM */
2284 break;
2285 case 3: /* Bits 24-31 */
2286#ifdef CONFIG_WNM
2287 *pos |= 0x02; /* Bit 25 - SSID List */
2288#endif /* CONFIG_WNM */
2289#ifdef CONFIG_INTERWORKING
2290 if (wpa_s->conf->interworking)
2291 *pos |= 0x80; /* Bit 31 - Interworking */
2292#endif /* CONFIG_INTERWORKING */
2293 break;
2294 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002295#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002296 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002297 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002298#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002299 break;
2300 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002301#ifdef CONFIG_HS20
2302 if (wpa_s->conf->hs20)
2303 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2304#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002305#ifdef CONFIG_MBO
2306 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2307#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002308 break;
2309 case 6: /* Bits 48-55 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002310#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002311#ifdef CONFIG_TESTING_OPTIONS
2312 if (wpa_s->disable_scs_support)
2313 scs = false;
2314#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002315 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2316 /* Drop own SCS capability indication since the AP does
2317 * not support it. This is needed to avoid
2318 * interoperability issues with APs that get confused
2319 * with Extended Capabilities element. */
2320 scs = false;
2321 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002322 if (scs)
2323 *pos |= 0x40; /* Bit 54 - SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002324#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002325 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002326 case 7: /* Bits 56-63 */
2327 break;
2328 case 8: /* Bits 64-71 */
2329 if (wpa_s->conf->ftm_responder)
2330 *pos |= 0x40; /* Bit 70 - FTM responder */
2331 if (wpa_s->conf->ftm_initiator)
2332 *pos |= 0x80; /* Bit 71 - FTM initiator */
2333 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002334 case 9: /* Bits 72-79 */
2335#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002336 if (!wpa_s->disable_fils)
2337 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002338#endif /* CONFIG_FILS */
2339 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002340 case 10: /* Bits 80-87 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002341#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002342#ifdef CONFIG_TESTING_OPTIONS
2343 if (wpa_s->disable_mscs_support)
2344 mscs = false;
2345#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002346 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2347 /* Drop own MSCS capability indication since the AP does
2348 * not support it. This is needed to avoid
2349 * interoperability issues with APs that get confused
2350 * with Extended Capabilities element. */
2351 mscs = false;
2352 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002353 if (mscs)
2354 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002355#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002356 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002357 }
2358}
2359
2360
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002361int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2362 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002363{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002364 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002365 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002366
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002367 if (len < wpa_s->extended_capa_len)
2368 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002369 if (buflen < (size_t) len + 2) {
2370 wpa_printf(MSG_INFO,
2371 "Not enough room for building extended capabilities element");
2372 return -1;
2373 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002374
2375 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002376 *pos++ = len;
2377 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002378 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002379
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002380 if (i < wpa_s->extended_capa_len) {
2381 *pos &= ~wpa_s->extended_capa_mask[i];
2382 *pos |= wpa_s->extended_capa[i];
2383 }
2384 }
2385
2386 while (len > 0 && buf[1 + len] == 0) {
2387 len--;
2388 buf[1] = len;
2389 }
2390 if (len == 0)
2391 return 0;
2392
2393 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002394}
2395
2396
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002397static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2398 struct wpa_bss *test_bss)
2399{
2400 struct wpa_bss *bss;
2401
2402 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2403 if (bss == test_bss)
2404 return 1;
2405 }
2406
2407 return 0;
2408}
2409
2410
2411static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2412 struct wpa_ssid *test_ssid)
2413{
2414 struct wpa_ssid *ssid;
2415
2416 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2417 if (ssid == test_ssid)
2418 return 1;
2419 }
2420
2421 return 0;
2422}
2423
2424
2425int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2426 struct wpa_ssid *test_ssid)
2427{
2428 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2429 return 0;
2430
2431 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2432}
2433
2434
2435void wpas_connect_work_free(struct wpa_connect_work *cwork)
2436{
2437 if (cwork == NULL)
2438 return;
2439 os_free(cwork);
2440}
2441
2442
2443void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2444{
2445 struct wpa_connect_work *cwork;
2446 struct wpa_radio_work *work = wpa_s->connect_work;
2447
2448 if (!work)
2449 return;
2450
2451 wpa_s->connect_work = NULL;
2452 cwork = work->ctx;
2453 work->ctx = NULL;
2454 wpas_connect_work_free(cwork);
2455 radio_work_done(work);
2456}
2457
2458
Sunil Ravi77d572f2023-01-17 23:58:31 +00002459int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2460 enum wpas_mac_addr_style style,
2461 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002462{
2463 struct os_reltime now;
2464 u8 addr[ETH_ALEN];
2465
2466 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002467 /* Random addresses are valid within a given ESS so check
2468 * expiration/value only when continuing to use the same ESS. */
2469 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2470 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2471 /* Pregenerated addresses do not expire but their value
2472 * might have changed, so let's check that. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002473 if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
Sunil Ravi77d572f2023-01-17 23:58:31 +00002474 return 0;
2475 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2476 wpa_s->last_mac_addr_change.usec != 0) &&
2477 !os_reltime_expired(
2478 &now,
2479 &wpa_s->last_mac_addr_change,
2480 wpa_s->conf->rand_addr_lifetime)) {
2481 wpa_msg(wpa_s, MSG_DEBUG,
2482 "Previously selected random MAC address has not yet expired");
2483 return 0;
2484 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002485 }
2486
2487 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002488 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002489 if (random_mac_addr(addr) < 0)
2490 return -1;
2491 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002492 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002493 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2494 if (random_mac_addr_keep_oui(addr) < 0)
2495 return -1;
2496 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002497 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2498 if (!ssid) {
2499 wpa_msg(wpa_s, MSG_INFO,
2500 "Invalid 'ssid' for address policy 3");
2501 return -1;
2502 }
2503 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2504 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002505 default:
2506 return -1;
2507 }
2508
2509 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2510 wpa_msg(wpa_s, MSG_INFO,
2511 "Failed to set random MAC address");
2512 return -1;
2513 }
2514
2515 os_get_reltime(&wpa_s->last_mac_addr_change);
2516 wpa_s->mac_addr_changed = 1;
2517 wpa_s->last_mac_addr_style = style;
2518
2519 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2520 wpa_msg(wpa_s, MSG_INFO,
2521 "Could not update MAC address information");
2522 return -1;
2523 }
2524
2525 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2526 MAC2STR(addr));
2527
Sunil Ravi77d572f2023-01-17 23:58:31 +00002528 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002529}
2530
2531
2532int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2533{
2534 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2535 !wpa_s->conf->preassoc_mac_addr)
2536 return 0;
2537
Sunil Ravi77d572f2023-01-17 23:58:31 +00002538 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2539 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002540}
2541
2542
Sunil Ravi036cec52023-03-29 11:35:17 -07002543void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2544 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002545{
2546#ifdef CONFIG_SAE
2547 int *groups = conf->sae_groups;
2548 int default_groups[] = { 19, 20, 21, 0 };
2549 const char *password;
2550
2551 if (!groups || groups[0] <= 0)
2552 groups = default_groups;
2553
2554 password = ssid->sae_password;
2555 if (!password)
2556 password = ssid->passphrase;
2557
Hai Shalom899fcc72020-10-19 14:38:18 -07002558 if (!password ||
Sunil Ravi7f769292024-07-23 22:21:32 +00002559 !wpa_key_mgmt_sae(ssid->key_mgmt) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002560 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002561 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002562 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002563 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002564 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002565 /* PT derivation not needed */
2566 sae_deinit_pt(ssid->pt);
2567 ssid->pt = NULL;
2568 return;
2569 }
2570
2571 if (ssid->pt)
2572 return; /* PT already derived */
2573 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2574 (const u8 *) password, os_strlen(password),
2575 ssid->sae_password_id);
2576#endif /* CONFIG_SAE */
2577}
2578
2579
Sunil Ravi7f769292024-07-23 22:21:32 +00002580void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002581{
2582#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2583 os_free(wpa_s->sme.sae_rejected_groups);
2584 wpa_s->sme.sae_rejected_groups = NULL;
2585#ifdef CONFIG_TESTING_OPTIONS
2586 if (wpa_s->extra_sae_rejected_groups) {
2587 int i, *groups = wpa_s->extra_sae_rejected_groups;
2588
2589 for (i = 0; groups[i]; i++) {
2590 wpa_printf(MSG_DEBUG,
2591 "TESTING: Indicate rejection of an extra SAE group %d",
2592 groups[i]);
2593 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2594 groups[i]);
2595 }
2596 }
2597#endif /* CONFIG_TESTING_OPTIONS */
2598#endif /* CONFIG_SAE && CONFIG_SME */
2599}
2600
2601
Hai Shalom60840252021-02-19 19:02:11 -08002602int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2603{
2604 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2605 wpa_msg(wpa_s, MSG_INFO,
2606 "Could not restore permanent MAC address");
2607 return -1;
2608 }
2609 wpa_s->mac_addr_changed = 0;
2610 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2611 wpa_msg(wpa_s, MSG_INFO,
2612 "Could not update MAC address information");
2613 return -1;
2614 }
2615 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2616 return 0;
2617}
2618
2619
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002620static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622/**
2623 * wpa_supplicant_associate - Request association
2624 * @wpa_s: Pointer to wpa_supplicant data
2625 * @bss: Scan results for the selected BSS, or %NULL if not available
2626 * @ssid: Configuration data for the selected network
2627 *
2628 * This function is used to request %wpa_supplicant to associate with a BSS.
2629 */
2630void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2631 struct wpa_bss *bss, struct wpa_ssid *ssid)
2632{
Sunil Ravi7f769292024-07-23 22:21:32 +00002633 bool clear_rejected = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002634 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002635 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002636
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002637 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002638 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002639
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002640 /*
2641 * If we are starting a new connection, any previously pending EAPOL
2642 * RX cannot be valid anymore.
2643 */
2644 wpabuf_free(wpa_s->pending_eapol_rx);
2645 wpa_s->pending_eapol_rx = NULL;
2646
Sunil Ravi77d572f2023-01-17 23:58:31 +00002647 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002648 rand_style = wpa_s->conf->mac_addr;
2649 else
2650 rand_style = ssid->mac_addr;
2651
Sunil Ravia04bd252022-05-02 22:54:18 -07002652 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002653 wpa_s->multi_ap_ie = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002654#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002655 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002656#endif /* CONFIG_NO_WMM_AC */
2657#ifdef CONFIG_WNM
2658 wpa_s->wnm_mode = 0;
Sunil Ravi99c035e2024-07-12 01:42:03 +00002659 wpa_s->wnm_target_bss = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002660#endif /* CONFIG_WNM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002661 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002662 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002663#ifdef CONFIG_TESTING_OPTIONS
2664 wpa_s->testing_resend_assoc = 0;
2665#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002666
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002667 if (wpa_s->last_ssid == ssid) {
2668 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002669 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002670 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002671#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002672 wmm_ac_save_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002673#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002674 wpa_s->reassoc_same_bss = 1;
Sunil Ravi7f769292024-07-23 22:21:32 +00002675 clear_rejected = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08002676 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2677 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002678 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002679 }
Sunil Ravi7f769292024-07-23 22:21:32 +00002680
2681 if (clear_rejected)
2682 wpa_s_clear_sae_rejected(wpa_s);
2683
Hai Shalomc1a21442022-02-04 13:43:00 -08002684#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002685 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002686#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002687
Sunil Ravi77d572f2023-01-17 23:58:31 +00002688 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2689 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2690
2691 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002692 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002693 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2694 status > 0) /* MAC changed */
2695 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2696 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2697 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002698 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002699 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002700 }
2701 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702
2703#ifdef CONFIG_IBSS_RSN
2704 ibss_rsn_deinit(wpa_s->ibss_rsn);
2705 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002706#else /* CONFIG_IBSS_RSN */
2707 if (ssid->mode == WPAS_MODE_IBSS &&
2708 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2709 wpa_msg(wpa_s, MSG_INFO,
2710 "IBSS RSN not supported in the build");
2711 return;
2712 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713#endif /* CONFIG_IBSS_RSN */
2714
2715 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2716 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2717#ifdef CONFIG_AP
2718 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2719 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2720 "mode");
2721 return;
2722 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002723 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2724 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302725 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2726 ssid->mode == WPAS_MODE_P2P_GO) {
2727 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002728 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302729 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002730 return;
2731 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 wpa_s->current_bss = bss;
2733#else /* CONFIG_AP */
2734 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2735 "the build");
2736#endif /* CONFIG_AP */
2737 return;
2738 }
2739
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002740 if (ssid->mode == WPAS_MODE_MESH) {
2741#ifdef CONFIG_MESH
2742 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2743 wpa_msg(wpa_s, MSG_INFO,
2744 "Driver does not support mesh mode");
2745 return;
2746 }
2747 if (bss)
2748 ssid->frequency = bss->freq;
2749 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002750 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002751 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2752 return;
2753 }
2754 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002755#else /* CONFIG_MESH */
2756 wpa_msg(wpa_s, MSG_ERROR,
2757 "mesh mode support not included in the build");
2758#endif /* CONFIG_MESH */
2759 return;
2760 }
2761
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002762 /*
2763 * Set WPA state machine configuration to match the selected network now
2764 * so that the information is available before wpas_start_assoc_cb()
2765 * gets called. This is needed at least for RSN pre-authentication where
2766 * candidate APs are added to a list based on scan result processing
2767 * before completion of the first association.
2768 */
2769 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2770
2771#ifdef CONFIG_DPP
2772 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2773 return;
2774#endif /* CONFIG_DPP */
2775
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776#ifdef CONFIG_TDLS
2777 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002778 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779#endif /* CONFIG_TDLS */
2780
Hai Shalomc3565922019-10-28 11:58:20 -07002781#ifdef CONFIG_MBO
2782 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2783#endif /* CONFIG_MBO */
2784
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002785 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002786 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787 sme_authenticate(wpa_s, bss, ssid);
2788 return;
2789 }
2790
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002791 if (wpa_s->connect_work) {
2792 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2793 return;
2794 }
2795
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002796 if (radio_work_pending(wpa_s, "connect")) {
2797 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2798 return;
2799 }
2800
Dmitry Shmidt29333592017-01-09 12:27:11 -08002801#ifdef CONFIG_SME
2802 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2803 /* Clear possibly set auth_alg, if any, from last attempt. */
2804 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2805 }
2806#endif /* CONFIG_SME */
2807
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002808 wpas_abort_ongoing_scan(wpa_s);
2809
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002810 cwork = os_zalloc(sizeof(*cwork));
2811 if (cwork == NULL)
2812 return;
2813
2814 cwork->bss = bss;
2815 cwork->ssid = ssid;
2816
2817 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2818 wpas_start_assoc_cb, cwork) < 0) {
2819 os_free(cwork);
2820 }
2821}
2822
2823
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002824static int bss_is_ibss(struct wpa_bss *bss)
2825{
2826 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2827 IEEE80211_CAP_IBSS;
2828}
2829
2830
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002831static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2832 const struct wpa_ssid *ssid)
2833{
2834 enum hostapd_hw_mode hw_mode;
2835 struct hostapd_hw_modes *mode = NULL;
2836 u8 channel;
2837 int i;
2838
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002839 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2840 if (hw_mode == NUM_HOSTAPD_MODES)
2841 return 0;
2842 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2843 if (wpa_s->hw.modes[i].mode == hw_mode) {
2844 mode = &wpa_s->hw.modes[i];
2845 break;
2846 }
2847 }
2848
2849 if (!mode)
2850 return 0;
2851
2852 return mode->vht_capab != 0;
2853}
2854
2855
Hai Shalomc1a21442022-02-04 13:43:00 -08002856static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2857{
2858 int i;
2859
2860 for (i = channel; i < channel + 16; i += 4) {
2861 struct hostapd_channel_data *chan;
2862
2863 chan = hw_get_channel_chan(mode, i, NULL);
2864 if (!chan ||
2865 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2866 return false;
2867 }
2868
2869 return true;
2870}
2871
2872
Sunil Ravi036cec52023-03-29 11:35:17 -07002873static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2874 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002875{
Sunil Ravi036cec52023-03-29 11:35:17 -07002876 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002877
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002878 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2879 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2880
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002881 if (!bss_is_ibss(bss))
2882 continue;
2883
2884 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002885 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2886 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002887 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002888 return NULL;
2889}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002890
Sunil Ravi036cec52023-03-29 11:35:17 -07002891
2892static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2893 const struct wpa_ssid *ssid,
2894 struct hostapd_hw_modes *mode)
2895{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002896 /* For IBSS check HT_IBSS flag */
2897 if (ssid->mode == WPAS_MODE_IBSS &&
2898 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002899 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002900
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002901 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2902 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2903 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2904 wpa_printf(MSG_DEBUG,
2905 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002906 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002907 }
2908
Sunil Ravi036cec52023-03-29 11:35:17 -07002909 if (!ht_supported(mode))
2910 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002911
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002912#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002913 if (ssid->disable_ht)
2914 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002915#endif /* CONFIG_HT_OVERRIDES */
2916
Sunil Ravi036cec52023-03-29 11:35:17 -07002917 return true;
2918}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002919
Sunil Ravi036cec52023-03-29 11:35:17 -07002920
2921static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2922 const struct wpa_ssid *ssid,
2923 struct hostapd_hw_modes *mode)
2924{
2925 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2926 return false;
2927
2928 if (!drv_supports_vht(wpa_s, ssid))
2929 return false;
2930
2931 /* For IBSS check VHT_IBSS flag */
2932 if (ssid->mode == WPAS_MODE_IBSS &&
2933 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2934 return false;
2935
2936 if (!vht_supported(mode))
2937 return false;
2938
2939#ifdef CONFIG_VHT_OVERRIDES
2940 if (ssid->disable_vht)
2941 return false;
2942#endif /* CONFIG_VHT_OVERRIDES */
2943
2944 return true;
2945}
2946
2947
2948static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2949 const struct wpa_ssid *ssid,
2950 const struct hostapd_hw_modes *mode,
2951 int ieee80211_mode)
2952{
Hai Shalomfdcde762020-04-02 11:19:20 -07002953#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002954 if (ssid->disable_he)
2955 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002956#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002957
Sunil Ravi036cec52023-03-29 11:35:17 -07002958 switch (mode->mode) {
2959 case HOSTAPD_MODE_IEEE80211G:
2960 case HOSTAPD_MODE_IEEE80211B:
2961 case HOSTAPD_MODE_IEEE80211A:
2962 return mode->he_capab[ieee80211_mode].he_supported;
2963 default:
2964 return false;
2965 }
2966}
2967
2968
2969static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2970 const struct wpa_ssid *ssid,
2971 const struct hostapd_hw_modes *mode,
2972 int ieee80211_mode)
2973{
2974 if (ssid->disable_eht)
2975 return false;
2976
2977 switch(mode->mode) {
2978 case HOSTAPD_MODE_IEEE80211G:
2979 case HOSTAPD_MODE_IEEE80211B:
2980 case HOSTAPD_MODE_IEEE80211A:
2981 return mode->eht_capab[ieee80211_mode].eht_supported;
2982 default:
2983 return false;
2984 }
2985}
2986
2987
2988static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2989 const struct wpa_ssid *ssid,
2990 struct hostapd_hw_modes *mode,
2991 struct hostapd_freq_params *freq,
2992 int obss_scan) {
2993 int chan_idx;
2994 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2995 int i, res;
2996 unsigned int j;
2997 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002998 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2999 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07003000 };
3001 int ht40 = -1;
3002
3003 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003004 return;
3005
3006 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
3007 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07003008 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003009 break;
3010 pri_chan = NULL;
3011 }
3012 if (!pri_chan)
3013 return;
3014
3015 /* Check primary channel flags */
3016 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
3017 return;
3018
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003019#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07003020 if (ssid->disable_ht40)
3021 return;
3022#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003023
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003024 /* Check/setup HT40+/HT40- */
3025 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07003026 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003027 ht40 = 1;
3028 break;
3029 }
3030 }
3031
3032 /* Find secondary channel */
3033 for (i = 0; i < mode->num_channels; i++) {
3034 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07003035 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003036 break;
3037 sec_chan = NULL;
3038 }
3039 if (!sec_chan)
3040 return;
3041
3042 /* Check secondary channel flags */
3043 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
3044 return;
3045
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003046 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003047 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
3048 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003049 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003050 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
3051 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003052 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003053 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003054
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003055 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003056 struct wpa_scan_results *scan_res;
3057
Sunil Ravi99c035e2024-07-12 01:42:03 +00003058 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
3059 NULL);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003060 if (scan_res == NULL) {
3061 /* Back to HT20 */
3062 freq->sec_channel_offset = 0;
3063 return;
3064 }
3065
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003066 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003067 switch (res) {
3068 case 0:
3069 /* Back to HT20 */
3070 freq->sec_channel_offset = 0;
3071 break;
3072 case 1:
3073 /* Configuration allowed */
3074 break;
3075 case 2:
3076 /* Switch pri/sec channels */
3077 freq->freq = hw_get_freq(mode, sec_chan->chan);
3078 freq->sec_channel_offset = -freq->sec_channel_offset;
3079 freq->channel = sec_chan->chan;
3080 break;
3081 default:
3082 freq->sec_channel_offset = 0;
3083 break;
3084 }
3085
3086 wpa_scan_results_free(scan_res);
3087 }
3088
3089 wpa_printf(MSG_DEBUG,
3090 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
3091 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07003092}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003093
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003094
Sunil Ravi036cec52023-03-29 11:35:17 -07003095static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
3096 const struct wpa_ssid *ssid,
3097 struct hostapd_hw_modes *mode,
3098 struct hostapd_freq_params *freq,
3099 int ieee80211_mode, bool is_6ghz) {
3100 static const int bw80[] = {
3101 5180, 5260, 5500, 5580, 5660, 5745, 5825,
3102 5955, 6035, 6115, 6195, 6275, 6355, 6435,
3103 6515, 6595, 6675, 6755, 6835, 6915, 6995
3104 };
3105 static const int bw160[] = {
3106 5955, 6115, 6275, 6435, 6595, 6755, 6915
3107 };
3108 struct hostapd_freq_params vht_freq;
3109 int i;
3110 unsigned int j, k;
3111 int chwidth, seg0, seg1;
3112 u32 vht_caps = 0;
3113 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003114
Sunil Ravi036cec52023-03-29 11:35:17 -07003115 if (!freq->vht_enabled && !freq->he_enabled)
3116 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08003117
Hai Shalomc1a21442022-02-04 13:43:00 -08003118 vht_freq = *freq;
3119
Sunil Ravi036cec52023-03-29 11:35:17 -07003120 chwidth = CONF_OPER_CHWIDTH_USE_HT;
3121 seg0 = freq->channel + 2 * freq->sec_channel_offset;
3122 seg1 = 0;
3123 if (freq->sec_channel_offset == 0) {
3124 seg0 = 0;
3125 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
3126 if (freq->ht_enabled && !is_6ghz)
3127 goto skip_80mhz;
3128 }
3129 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
3130 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07003131
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003132 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003133 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
3134 if (freq->freq >= bw80[j] &&
3135 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003136 break;
3137 }
3138
Hai Shalomc1a21442022-02-04 13:43:00 -08003139 if (j == ARRAY_SIZE(bw80) ||
3140 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003141 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003142
Sunil Ravi036cec52023-03-29 11:35:17 -07003143 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08003144 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07003145 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003146
Sunil8cd6f4d2022-06-28 18:40:46 +00003147 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003148 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003149 seg1 = 0;
3150
Sunil Ravi036cec52023-03-29 11:35:17 -07003151 /* In 160 MHz, the initial four 20 MHz channels were validated
3152 * above. If 160 MHz is supported, check the remaining four 20 MHz
3153 * channels for the total of 160 MHz bandwidth for 6 GHz.
3154 */
Hai Shalomc1a21442022-02-04 13:43:00 -08003155 if ((mode->he_capab[ieee80211_mode].phy_cap[
3156 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07003157 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
3158 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003159 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
3160 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003161 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003162 seg0 = channel + 14;
3163 break;
3164 }
3165 }
3166 }
3167
Sunil8cd6f4d2022-06-28 18:40:46 +00003168 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003169 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003170 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003171 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003172 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003173 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003174
3175 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3176 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003177 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003178
3179 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003180 struct hostapd_channel_data *chan;
3181
3182 chan = hw_get_channel_chan(mode, i, NULL);
3183 if (!chan)
3184 continue;
3185
3186 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3187 HOSTAPD_CHAN_NO_IR |
3188 HOSTAPD_CHAN_RADAR))
3189 continue;
3190
3191 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003192 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003193 if (!is_6ghz)
3194 vht_caps |=
3195 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3196 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003197 }
3198
Sunil8cd6f4d2022-06-28 18:40:46 +00003199 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003200 break;
3201 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003202 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003203 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003204 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003205 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3206 seg0 = 50;
3207 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003208 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003209 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3210 seg0 = 114;
3211 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003212 }
3213
Sunil Ravi036cec52023-03-29 11:35:17 -07003214skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003215 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003216 freq->channel, ssid->enable_edmg,
3217 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003218 freq->vht_enabled, freq->he_enabled,
3219 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003220 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003221 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003222 &mode->he_capab[ieee80211_mode],
Sunil Ravi99c035e2024-07-12 01:42:03 +00003223 &mode->eht_capab[ieee80211_mode], 0) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003224 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003225
3226 *freq = vht_freq;
3227
3228 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3229 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003230 return true;
3231}
3232
3233
3234void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3235 const struct wpa_ssid *ssid,
3236 struct hostapd_freq_params *freq)
3237{
3238 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3239 enum hostapd_hw_mode hw_mode;
3240 struct hostapd_hw_modes *mode = NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +00003241 int obss_scan = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -07003242 u8 channel;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003243 bool is_6ghz, is_24ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003244
3245 freq->freq = ssid->frequency;
3246
3247 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3248 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3249
3250 if (bss) {
3251 wpa_printf(MSG_DEBUG,
3252 "IBSS already found in scan results, adjust control freq: %d",
3253 bss->freq);
3254 freq->freq = bss->freq;
3255 obss_scan = 0;
3256 }
3257 }
3258
3259 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Sunil Ravi7f769292024-07-23 22:21:32 +00003260 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3261 hw_mode, is_6ghz_freq(ssid->frequency));
Sunil Ravi036cec52023-03-29 11:35:17 -07003262
3263 if (!mode)
3264 return;
3265
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003266 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
3267 hw_mode == HOSTAPD_MODE_IEEE80211B;
3268
Sunil Ravi036cec52023-03-29 11:35:17 -07003269 is_6ghz = is_6ghz_freq(freq->freq);
3270
3271 freq->ht_enabled = 0;
3272 freq->vht_enabled = 0;
3273 freq->he_enabled = 0;
3274 freq->eht_enabled = 0;
3275
3276 if (!is_6ghz)
3277 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3278 if (freq->ht_enabled)
3279 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003280 if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003281 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3282 ieee80211_mode);
3283 freq->channel = channel;
3284 /* Setup higher BW only for 5 GHz */
3285 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3286 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3287 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3288 ieee80211_mode, is_6ghz))
3289 freq->he_enabled = freq->vht_enabled = false;
3290 }
3291
3292 if (freq->he_enabled)
3293 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3294 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003295}
3296
3297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003298#ifdef CONFIG_FILS
3299static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3300 size_t ie_buf_len)
3301{
3302 struct fils_hlp_req *req;
3303 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3304 const u8 *pos;
3305 u8 *buf = ie_buf;
3306
3307 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3308 list) {
3309 rem_len = ie_buf_len - ie_len;
3310 pos = wpabuf_head(req->pkt);
3311 hdr_len = 1 + 2 * ETH_ALEN + 6;
3312 hlp_len = wpabuf_len(req->pkt);
3313
3314 if (rem_len < 2 + hdr_len + hlp_len) {
3315 wpa_printf(MSG_ERROR,
3316 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3317 (unsigned long) rem_len,
3318 (unsigned long) (2 + hdr_len + hlp_len));
3319 break;
3320 }
3321
3322 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3323 /* Element ID */
3324 *buf++ = WLAN_EID_EXTENSION;
3325 /* Length */
3326 *buf++ = len;
3327 /* Element ID Extension */
3328 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3329 /* Destination MAC address */
3330 os_memcpy(buf, req->dst, ETH_ALEN);
3331 buf += ETH_ALEN;
3332 /* Source MAC address */
3333 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3334 buf += ETH_ALEN;
3335 /* LLC/SNAP Header */
3336 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3337 buf += 6;
3338 /* HLP Packet */
3339 os_memcpy(buf, pos, len - hdr_len);
3340 buf += len - hdr_len;
3341 pos += len - hdr_len;
3342
3343 hlp_len -= len - hdr_len;
3344 ie_len += 2 + len;
3345 rem_len -= 2 + len;
3346
3347 while (hlp_len) {
3348 len = (hlp_len > 255) ? 255 : hlp_len;
3349 if (rem_len < 2 + len)
3350 break;
3351 *buf++ = WLAN_EID_FRAGMENT;
3352 *buf++ = len;
3353 os_memcpy(buf, pos, len);
3354 buf += len;
3355 pos += len;
3356
3357 hlp_len -= len;
3358 ie_len += 2 + len;
3359 rem_len -= 2 + len;
3360 }
3361 }
3362
3363 return ie_len;
3364}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003365
3366
3367int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3368{
3369 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3370 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3371 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3372 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3373}
3374
3375
3376int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3377{
3378#ifdef CONFIG_FILS_SK_PFS
3379 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3380 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3381#else /* CONFIG_FILS_SK_PFS */
3382 return 0;
3383#endif /* CONFIG_FILS_SK_PFS */
3384}
3385
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003386#endif /* CONFIG_FILS */
3387
3388
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003389bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3390{
3391 const u8 *wfa_capa;
3392
3393 if (!bss)
3394 return false;
3395
3396 /* Get WFA capability from Beacon or Probe Response frame elements */
3397 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3398 if (!wfa_capa)
3399 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3400 bss, WFA_CAPA_IE_VENDOR_TYPE);
3401
3402 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3403 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3404 /* AP does not enable QM non EHT traffic description policy */
3405 return false;
3406 }
3407
3408 return true;
3409}
3410
3411
Hai Shalomc1a21442022-02-04 13:43:00 -08003412static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3413 struct wpa_bss *bss,
3414 u8 *wpa_ie, size_t wpa_ie_len,
3415 size_t max_wpa_ie_len)
3416{
3417 struct wpabuf *wfa_ie = NULL;
3418 u8 wfa_capa[1];
3419 size_t wfa_ie_len, buf_len;
3420
3421 os_memset(wfa_capa, 0, sizeof(wfa_capa));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003422#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003423 if (wpa_s->enable_dscp_policy_capa)
3424 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003425#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003426
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003427 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3428 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3429
Hai Shalomc1a21442022-02-04 13:43:00 -08003430 if (!wfa_capa[0])
3431 return wpa_ie_len;
3432
3433 /* Wi-Fi Alliance element */
3434 buf_len = 1 + /* Element ID */
3435 1 + /* Length */
3436 3 + /* OUI */
3437 1 + /* OUI Type */
3438 1 + /* Capabilities Length */
3439 sizeof(wfa_capa); /* Capabilities */
3440 wfa_ie = wpabuf_alloc(buf_len);
3441 if (!wfa_ie)
3442 return wpa_ie_len;
3443
3444 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3445 wpabuf_put_u8(wfa_ie, buf_len - 2);
3446 wpabuf_put_be24(wfa_ie, OUI_WFA);
3447 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3448 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3449 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3450
3451 wfa_ie_len = wpabuf_len(wfa_ie);
3452 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3453 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3454 wfa_ie);
3455 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3456 wfa_ie_len);
3457 wpa_ie_len += wfa_ie_len;
3458 }
3459
3460 wpabuf_free(wfa_ie);
3461 return wpa_ie_len;
3462}
3463
3464
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003465static u8 * wpas_populate_assoc_ies(
3466 struct wpa_supplicant *wpa_s,
3467 struct wpa_bss *bss, struct wpa_ssid *ssid,
3468 struct wpa_driver_associate_params *params,
3469 enum wpa_drv_update_connect_params_mask *mask)
3470{
3471 u8 *wpa_ie;
3472 size_t max_wpa_ie_len = 500;
3473 size_t wpa_ie_len;
3474 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003475#ifdef CONFIG_MBO
3476 const u8 *mbo_ie;
3477#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303478#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3479 int pmksa_cached = 0;
3480#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003481#ifdef CONFIG_FILS
3482 const u8 *realm, *username, *rrk;
3483 size_t realm_len, username_len, rrk_len;
3484 u16 next_seq_num;
3485 struct fils_hlp_req *req;
3486
3487 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3488 list) {
3489 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3490 2 + 2 * wpabuf_len(req->pkt) / 255;
3491 }
3492#endif /* CONFIG_FILS */
3493
3494 wpa_ie = os_malloc(max_wpa_ie_len);
3495 if (!wpa_ie) {
3496 wpa_printf(MSG_ERROR,
3497 "Failed to allocate connect IE buffer for %lu bytes",
3498 (unsigned long) max_wpa_ie_len);
3499 return NULL;
3500 }
3501
3502 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
Sunil Ravi7f769292024-07-23 22:21:32 +00003503 wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003504 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3505 int try_opportunistic;
3506 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003507 const u8 *addr = bss->bssid;
3508
Sunil Ravi036cec52023-03-29 11:35:17 -07003509 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3510 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3511 !is_zero_ether_addr(bss->mld_addr))
3512 addr = bss->mld_addr;
3513
3514 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3515 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003516 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003517
3518 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3519 wpa_s->conf->okc :
3520 ssid->proactive_key_caching) &&
3521 (ssid->proto & WPA_PROTO_RSN);
3522#ifdef CONFIG_FILS
3523 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3524 cache_id = wpa_bss_get_fils_cache_id(bss);
3525#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003526 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003527 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003528 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003529 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303530#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3531 pmksa_cached = 1;
3532#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003533 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003534 wpa_ie_len = max_wpa_ie_len;
3535 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003536 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003537 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3538 "key management and encryption suites");
3539 os_free(wpa_ie);
3540 return NULL;
3541 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003542#ifdef CONFIG_HS20
3543 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3544 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3545 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3546 wpa_ie_len = max_wpa_ie_len;
3547 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003548 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003549 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3550 "key management and encryption suites");
3551 os_free(wpa_ie);
3552 return NULL;
3553 }
3554#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003555 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3556 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3557 /*
3558 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3559 * use non-WPA since the scan results did not indicate that the
3560 * AP is using WPA or WPA2.
3561 */
3562 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3563 wpa_ie_len = 0;
3564 wpa_s->wpa_proto = 0;
3565 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3566 wpa_ie_len = max_wpa_ie_len;
3567 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003568 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003569 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3570 "key management and encryption suites (no "
3571 "scan results)");
3572 os_free(wpa_ie);
3573 return NULL;
3574 }
3575#ifdef CONFIG_WPS
3576 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3577 struct wpabuf *wps_ie;
3578 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3579 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3580 wpa_ie_len = wpabuf_len(wps_ie);
3581 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3582 } else
3583 wpa_ie_len = 0;
3584 wpabuf_free(wps_ie);
3585 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3586 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3587 params->wps = WPS_MODE_PRIVACY;
3588 else
3589 params->wps = WPS_MODE_OPEN;
3590 wpa_s->wpa_proto = 0;
3591#endif /* CONFIG_WPS */
3592 } else {
3593 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3594 wpa_ie_len = 0;
3595 wpa_s->wpa_proto = 0;
3596 }
3597
3598#ifdef IEEE8021X_EAPOL
3599 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3600 if (ssid->leap) {
3601 if (ssid->non_leap == 0)
3602 algs = WPA_AUTH_ALG_LEAP;
3603 else
3604 algs |= WPA_AUTH_ALG_LEAP;
3605 }
3606 }
3607
3608#ifdef CONFIG_FILS
3609 /* Clear FILS association */
3610 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3611
3612 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3613 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3614 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3615 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003616 &next_seq_num, &rrk, &rrk_len) == 0 &&
3617 (!wpa_s->last_con_fail_realm ||
3618 wpa_s->last_con_fail_realm_len != realm_len ||
3619 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620 algs = WPA_AUTH_ALG_FILS;
3621 params->fils_erp_username = username;
3622 params->fils_erp_username_len = username_len;
3623 params->fils_erp_realm = realm;
3624 params->fils_erp_realm_len = realm_len;
3625 params->fils_erp_next_seq_num = next_seq_num;
3626 params->fils_erp_rrk = rrk;
3627 params->fils_erp_rrk_len = rrk_len;
3628
3629 if (mask)
3630 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303631 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3632 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3633 pmksa_cached) {
3634 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003635 }
3636#endif /* CONFIG_FILS */
3637#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003638#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003639 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003640 algs = WPA_AUTH_ALG_SAE;
3641#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003642
3643 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3644 if (ssid->auth_alg) {
3645 algs = ssid->auth_alg;
3646 wpa_dbg(wpa_s, MSG_DEBUG,
3647 "Overriding auth_alg selection: 0x%x", algs);
3648 }
3649
Hai Shalom5f92bc92019-04-18 11:54:11 -07003650#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303651 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003652 wpa_dbg(wpa_s, MSG_DEBUG,
3653 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3654 algs = WPA_AUTH_ALG_OPEN;
3655 }
3656#endif /* CONFIG_SAE */
3657
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003658#ifdef CONFIG_P2P
3659 if (wpa_s->global->p2p) {
3660 u8 *pos;
3661 size_t len;
3662 int res;
3663 pos = wpa_ie + wpa_ie_len;
3664 len = max_wpa_ie_len - wpa_ie_len;
3665 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3666 ssid->p2p_group);
3667 if (res >= 0)
3668 wpa_ie_len += res;
3669 }
3670
3671 wpa_s->cross_connect_disallowed = 0;
3672 if (bss) {
3673 struct wpabuf *p2p;
3674 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3675 if (p2p) {
3676 wpa_s->cross_connect_disallowed =
3677 p2p_get_cross_connect_disallowed(p2p);
3678 wpabuf_free(p2p);
3679 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3680 "connection",
3681 wpa_s->cross_connect_disallowed ?
3682 "disallows" : "allows");
3683 }
3684 }
3685
3686 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3687#endif /* CONFIG_P2P */
3688
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003689#ifndef CONFIG_NO_RRM
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003690 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003691 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003692 wpa_ie + wpa_ie_len,
3693 max_wpa_ie_len -
3694 wpa_ie_len);
3695 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003696#endif /* CONFIG_NO_RRM */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003697
3698 /*
3699 * Workaround: Add Extended Capabilities element only if the AP
3700 * included this element in Beacon/Probe Response frames. Some older
3701 * APs seem to have interoperability issues if this element is
3702 * included, so while the standard may require us to include the
3703 * element in all cases, it is justifiable to skip it to avoid
3704 * interoperability issues.
3705 */
3706 if (ssid->p2p_group)
3707 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3708 else
3709 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3710
3711 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3712 u8 ext_capab[18];
3713 int ext_capab_len;
3714 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003715 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003716 if (ext_capab_len > 0 &&
3717 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3718 u8 *pos = wpa_ie;
3719 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3720 pos += 2 + pos[1];
3721 os_memmove(pos + ext_capab_len, pos,
3722 wpa_ie_len - (pos - wpa_ie));
3723 wpa_ie_len += ext_capab_len;
3724 os_memcpy(pos, ext_capab, ext_capab_len);
3725 }
3726 }
3727
Sunil Ravi7f769292024-07-23 22:21:32 +00003728 if (ssid->max_idle && wpa_ie_len + 5 <= max_wpa_ie_len) {
3729 u8 *pos = wpa_ie;
3730
3731 *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
3732 *pos++ = 3;
3733 WPA_PUT_LE16(pos, ssid->max_idle);
3734 pos += 2;
3735 *pos = 0; /* Idle Options */
3736 wpa_ie_len += 5;
3737 }
3738
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003739#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003740 if (is_hs20_network(wpa_s, ssid, bss)
3741#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3742 && is_hs20_config(wpa_s)
3743#endif /* ANDROID */
3744 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003745 struct wpabuf *hs20;
3746
Roshan Pius3a1667e2018-07-03 15:17:14 -07003747 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003748 if (hs20) {
3749 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3750 size_t len;
3751
Hai Shalom74f70d42019-02-11 14:42:39 -08003752 wpas_hs20_add_indication(hs20, pps_mo_id,
3753 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003754 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003755 len = max_wpa_ie_len - wpa_ie_len;
3756 if (wpabuf_len(hs20) <= len) {
3757 os_memcpy(wpa_ie + wpa_ie_len,
3758 wpabuf_head(hs20), wpabuf_len(hs20));
3759 wpa_ie_len += wpabuf_len(hs20);
3760 }
3761 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003762 }
3763 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003764 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003765#endif /* CONFIG_HS20 */
3766
3767 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3768 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3769 size_t len;
3770
3771 len = max_wpa_ie_len - wpa_ie_len;
3772 if (wpabuf_len(buf) <= len) {
3773 os_memcpy(wpa_ie + wpa_ie_len,
3774 wpabuf_head(buf), wpabuf_len(buf));
3775 wpa_ie_len += wpabuf_len(buf);
3776 }
3777 }
3778
3779#ifdef CONFIG_FST
3780 if (wpa_s->fst_ies) {
3781 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3782
3783 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3784 os_memcpy(wpa_ie + wpa_ie_len,
3785 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3786 wpa_ie_len += fst_ies_len;
3787 }
3788 }
3789#endif /* CONFIG_FST */
3790
3791#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003792 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003793 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003794 int len;
3795
3796 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003797 max_wpa_ie_len - wpa_ie_len,
3798 !!mbo_attr_from_mbo_ie(mbo_ie,
3799 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003800 if (len >= 0)
3801 wpa_ie_len += len;
3802 }
3803#endif /* CONFIG_MBO */
3804
3805#ifdef CONFIG_FILS
3806 if (algs == WPA_AUTH_ALG_FILS) {
3807 size_t len;
3808
3809 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3810 max_wpa_ie_len - wpa_ie_len);
3811 wpa_ie_len += len;
3812 }
3813#endif /* CONFIG_FILS */
3814
3815#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003816#ifdef CONFIG_TESTING_OPTIONS
3817 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3818 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3819 } else
3820#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003821 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003822 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3823 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003824 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003825 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003826
Roshan Pius3a1667e2018-07-03 15:17:14 -07003827 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003828 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003829 } else if (wpa_s->assoc_status_code ==
3830 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003831 if (wpa_s->last_owe_group == 19)
3832 group = 20;
3833 else if (wpa_s->last_owe_group == 20)
3834 group = 21;
3835 else
3836 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003837 } else {
3838 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003839 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003840
Roshan Pius3a1667e2018-07-03 15:17:14 -07003841 wpa_s->last_owe_group = group;
3842 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003843 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3844 if (owe_ie &&
3845 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3846 os_memcpy(wpa_ie + wpa_ie_len,
3847 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3848 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003849 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003850 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003851 }
3852#endif /* CONFIG_OWE */
3853
Hai Shalom021b0b52019-04-10 11:17:58 -07003854#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003855 if (DPP_VERSION > 1 &&
3856 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003857 ssid->dpp_netaccesskey &&
3858 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003859 struct rsn_pmksa_cache_entry *pmksa;
3860
3861 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3862 if (!pmksa || !pmksa->dpp_pfs)
3863 goto pfs_fail;
3864
Hai Shalom021b0b52019-04-10 11:17:58 -07003865 dpp_pfs_free(wpa_s->dpp_pfs);
3866 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3867 ssid->dpp_netaccesskey_len);
3868 if (!wpa_s->dpp_pfs) {
3869 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3870 /* Try to continue without PFS */
3871 goto pfs_fail;
3872 }
3873 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3874 max_wpa_ie_len - wpa_ie_len) {
3875 os_memcpy(wpa_ie + wpa_ie_len,
3876 wpabuf_head(wpa_s->dpp_pfs->ie),
3877 wpabuf_len(wpa_s->dpp_pfs->ie));
3878 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3879 }
3880 }
3881pfs_fail:
3882#endif /* CONFIG_DPP2 */
3883
Roshan Pius3a1667e2018-07-03 15:17:14 -07003884#ifdef CONFIG_IEEE80211R
3885 /*
3886 * Add MDIE under these conditions: the network profile allows FT,
3887 * the AP supports FT, and the mobility domain ID matches.
3888 */
3889 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3890 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3891
3892 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3893 size_t len = 0;
3894 const u8 *md = mdie + 2;
3895 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3896
3897 if (os_memcmp(md, wpa_md,
3898 MOBILITY_DOMAIN_ID_LEN) == 0) {
3899 /* Add mobility domain IE */
3900 len = wpa_ft_add_mdie(
3901 wpa_s->wpa, wpa_ie + wpa_ie_len,
3902 max_wpa_ie_len - wpa_ie_len, mdie);
3903 wpa_ie_len += len;
3904 }
3905#ifdef CONFIG_SME
3906 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003907 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003908 wpa_dbg(wpa_s, MSG_DEBUG,
3909 "SME: Trying to use FT over-the-air");
3910 algs |= WPA_AUTH_ALG_FT;
3911 }
3912#endif /* CONFIG_SME */
3913 }
3914 }
3915#endif /* CONFIG_IEEE80211R */
3916
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003917#ifdef CONFIG_TESTING_OPTIONS
3918 if (wpa_s->rsnxe_override_assoc &&
3919 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3920 max_wpa_ie_len - wpa_ie_len) {
3921 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3922 os_memcpy(wpa_ie + wpa_ie_len,
3923 wpabuf_head(wpa_s->rsnxe_override_assoc),
3924 wpabuf_len(wpa_s->rsnxe_override_assoc));
3925 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3926 } else
3927#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003928 if (wpa_s->rsnxe_len > 0 &&
3929 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3930 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3931 wpa_ie_len += wpa_s->rsnxe_len;
3932 }
3933
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003934#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003935#ifdef CONFIG_TESTING_OPTIONS
3936 if (wpa_s->disable_mscs_support)
3937 goto mscs_end;
3938#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003939 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3940 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003941 struct wpabuf *mscs_ie;
3942 size_t mscs_ie_len, buf_len;
3943
Hai Shalom899fcc72020-10-19 14:38:18 -07003944 buf_len = 3 + /* MSCS descriptor IE header */
3945 1 + /* Request type */
3946 2 + /* User priority control */
3947 4 + /* Stream timeout */
3948 3 + /* TCLAS Mask IE header */
3949 wpa_s->robust_av.frame_classifier_len;
3950 mscs_ie = wpabuf_alloc(buf_len);
3951 if (!mscs_ie) {
3952 wpa_printf(MSG_INFO,
3953 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003954 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003955 }
3956
3957 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3958 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3959 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3960 mscs_ie_len = wpabuf_len(mscs_ie);
3961 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3962 mscs_ie_len);
3963 wpa_ie_len += mscs_ie_len;
3964 }
3965
3966 wpabuf_free(mscs_ie);
3967 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003968mscs_end:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003969#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003970
3971 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3972 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003973
Hai Shalom74f70d42019-02-11 14:42:39 -08003974 if (ssid->multi_ap_backhaul_sta) {
3975 size_t multi_ap_ie_len;
Sunil Ravi99c035e2024-07-12 01:42:03 +00003976 struct multi_ap_params multi_ap = { 0 };
3977
3978 multi_ap.capability = MULTI_AP_BACKHAUL_STA;
3979 multi_ap.profile = ssid->multi_ap_profile;
Hai Shalom74f70d42019-02-11 14:42:39 -08003980
3981 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3982 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi99c035e2024-07-12 01:42:03 +00003983 &multi_ap);
Hai Shalom74f70d42019-02-11 14:42:39 -08003984 if (multi_ap_ie_len == 0) {
3985 wpa_printf(MSG_ERROR,
3986 "Multi-AP: Failed to build Multi-AP IE");
3987 os_free(wpa_ie);
3988 return NULL;
3989 }
3990 wpa_ie_len += multi_ap_ie_len;
3991 }
3992
Sunil Ravic0f5d412024-09-11 22:12:49 +00003993 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
3994 wpas_rsn_overriding(wpa_s));
3995 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
3996 RSN_OVERRIDE_NOT_USED);
3997 if (wpas_rsn_overriding(wpa_s) &&
Sunil Ravi7f769292024-07-23 22:21:32 +00003998 wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
Sunil Ravic0f5d412024-09-11 22:12:49 +00003999 wpa_ie_len + 2 + 4 + 1 <= max_wpa_ie_len) {
4000 u8 *pos = wpa_ie + wpa_ie_len, *start = pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004001 const u8 *ie;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004002 enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
Sunil Ravi7f769292024-07-23 22:21:32 +00004003
Sunil Ravic0f5d412024-09-11 22:12:49 +00004004 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
4005 RSN_OVERRIDE_RSNE);
Sunil Ravi7f769292024-07-23 22:21:32 +00004006 ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004007 if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
4008 u32 type;
4009
Sunil Ravi7f769292024-07-23 22:21:32 +00004010 type = WPA_GET_BE32(&ie[2]);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004011 if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
4012 variant = RSN_SELECTION_RSNE_OVERRIDE;
4013 wpa_sm_set_param(wpa_s->wpa,
4014 WPA_PARAM_RSN_OVERRIDE,
4015 RSN_OVERRIDE_RSNE_OVERRIDE);
4016 } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
4017 variant = RSN_SELECTION_RSNE_OVERRIDE_2;
4018 wpa_sm_set_param(wpa_s->wpa,
4019 WPA_PARAM_RSN_OVERRIDE,
4020 RSN_OVERRIDE_RSNE_OVERRIDE_2);
4021 }
Sunil Ravi7f769292024-07-23 22:21:32 +00004022 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00004023
4024 /* Indicate which RSNE variant was used */
4025 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4026 *pos++ = 4 + 1;
4027 WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
4028 pos += 4;
4029 *pos++ = variant;
4030 wpa_hexdump(MSG_MSGDUMP, "RSN Selection", start, pos - start);
4031 wpa_ie_len += pos - start;
Sunil Ravi7f769292024-07-23 22:21:32 +00004032 }
4033
Sunil Ravic0f5d412024-09-11 22:12:49 +00004034 params->rsn_overriding = wpas_rsn_overriding(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004035 params->wpa_ie = wpa_ie;
4036 params->wpa_ie_len = wpa_ie_len;
4037 params->auth_alg = algs;
4038 if (mask)
4039 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
4040
4041 return wpa_ie;
4042}
4043
4044
Hai Shalomc3565922019-10-28 11:58:20 -07004045#ifdef CONFIG_OWE
4046static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
4047{
4048 struct wpa_driver_associate_params params;
4049 u8 *wpa_ie;
4050
4051 os_memset(&params, 0, sizeof(params));
4052 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4053 wpa_s->current_ssid, &params, NULL);
4054 if (!wpa_ie)
4055 return;
4056
4057 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4058 os_free(wpa_ie);
4059}
4060#endif /* CONFIG_OWE */
4061
4062
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004063#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
4064static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
4065{
4066 struct wpa_driver_associate_params params;
4067 enum wpa_drv_update_connect_params_mask mask = 0;
4068 u8 *wpa_ie;
4069
4070 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
4071 return; /* nothing to do */
4072
4073 os_memset(&params, 0, sizeof(params));
4074 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4075 wpa_s->current_ssid, &params, &mask);
4076 if (!wpa_ie)
4077 return;
4078
Hai Shalomc1a21442022-02-04 13:43:00 -08004079 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
4080 wpa_s->auth_alg = params.auth_alg;
4081 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004082 }
4083
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004084 os_free(wpa_ie);
4085}
4086#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
4087
4088
Hai Shalomc3565922019-10-28 11:58:20 -07004089static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
4090{
4091 if (!edmg_ie || edmg_ie[1] < 6)
4092 return 0;
4093 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
4094}
4095
4096
4097static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
4098{
4099 if (!edmg_ie || edmg_ie[1] < 6)
4100 return 0;
4101 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
4102}
4103
4104
4105/* Returns the intersection of two EDMG configurations.
4106 * Note: The current implementation is limited to CB2 only (CB1 included),
4107 * i.e., the implementation supports up to 2 contiguous channels.
4108 * For supporting non-contiguous (aggregated) channels and for supporting
4109 * CB3 and above, this function will need to be extended.
4110 */
4111static struct ieee80211_edmg_config
4112get_edmg_intersection(struct ieee80211_edmg_config a,
4113 struct ieee80211_edmg_config b,
4114 u8 primary_channel)
4115{
4116 struct ieee80211_edmg_config result;
4117 int i, contiguous = 0;
4118 int max_contiguous = 0;
4119
4120 result.channels = b.channels & a.channels;
4121 if (!result.channels) {
4122 wpa_printf(MSG_DEBUG,
4123 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
4124 a.channels, b.channels);
4125 goto fail;
4126 }
4127
4128 if (!(result.channels & BIT(primary_channel - 1))) {
4129 wpa_printf(MSG_DEBUG,
4130 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
4131 primary_channel, result.channels);
4132 goto fail;
4133 }
4134
4135 /* Find max contiguous channels */
4136 for (i = 0; i < 6; i++) {
4137 if (result.channels & BIT(i))
4138 contiguous++;
4139 else
4140 contiguous = 0;
4141
4142 if (contiguous > max_contiguous)
4143 max_contiguous = contiguous;
4144 }
4145
4146 /* Assuming AP and STA supports ONLY contiguous channels,
4147 * bw configuration can have value between 4-7.
4148 */
4149 if ((b.bw_config < a.bw_config))
4150 result.bw_config = b.bw_config;
4151 else
4152 result.bw_config = a.bw_config;
4153
4154 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
4155 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
4156 wpa_printf(MSG_DEBUG,
4157 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
4158 max_contiguous);
4159 goto fail;
4160 }
4161
4162 return result;
4163
4164fail:
4165 result.channels = 0;
4166 result.bw_config = 0;
4167 return result;
4168}
4169
4170
4171static struct ieee80211_edmg_config
4172get_supported_edmg(struct wpa_supplicant *wpa_s,
4173 struct hostapd_freq_params *freq,
4174 struct ieee80211_edmg_config request_edmg)
4175{
4176 enum hostapd_hw_mode hw_mode;
4177 struct hostapd_hw_modes *mode = NULL;
4178 u8 primary_channel;
4179
4180 if (!wpa_s->hw.modes)
4181 goto fail;
4182
4183 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
4184 if (hw_mode == NUM_HOSTAPD_MODES)
4185 goto fail;
4186
Hai Shalom60840252021-02-19 19:02:11 -08004187 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004188 if (!mode)
4189 goto fail;
4190
4191 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
4192
4193fail:
4194 request_edmg.channels = 0;
4195 request_edmg.bw_config = 0;
4196 return request_edmg;
4197}
4198
4199
Hai Shalom021b0b52019-04-10 11:17:58 -07004200#ifdef CONFIG_MBO
4201void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
4202{
4203 struct wpa_driver_associate_params params;
4204 u8 *wpa_ie;
4205
4206 /*
4207 * Update MBO connect params only in case of change of MBO attributes
4208 * when connected, if the AP support MBO.
4209 */
4210
4211 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
4212 !wpa_s->current_bss ||
4213 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
4214 return;
4215
4216 os_memset(&params, 0, sizeof(params));
4217 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4218 wpa_s->current_ssid, &params, NULL);
4219 if (!wpa_ie)
4220 return;
4221
4222 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4223 os_free(wpa_ie);
4224}
4225#endif /* CONFIG_MBO */
4226
4227
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004228static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4229{
4230 struct wpa_connect_work *cwork = work->ctx;
4231 struct wpa_bss *bss = cwork->bss;
4232 struct wpa_ssid *ssid = cwork->ssid;
4233 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004234 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004235 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004236 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004237 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004238 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004239 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004240#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004241 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004242#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004243 int assoc_failed = 0;
4244 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004245 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004246#ifdef CONFIG_HT_OVERRIDES
4247 struct ieee80211_ht_capabilities htcaps;
4248 struct ieee80211_ht_capabilities htcaps_mask;
4249#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004250#ifdef CONFIG_VHT_OVERRIDES
4251 struct ieee80211_vht_capabilities vhtcaps;
4252 struct ieee80211_vht_capabilities vhtcaps_mask;
4253#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004254
Hai Shalomc1a21442022-02-04 13:43:00 -08004255 wpa_s->roam_in_progress = false;
4256#ifdef CONFIG_WNM
4257 wpa_s->bss_trans_mgmt_in_progress = false;
4258#endif /* CONFIG_WNM */
Sunil Ravi7f769292024-07-23 22:21:32 +00004259 wpa_s->no_suitable_network = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08004260
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004261 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004262 if (work->started) {
4263 wpa_s->connect_work = NULL;
4264
4265 /* cancel possible auth. timeout */
4266 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4267 NULL);
4268 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004269 wpas_connect_work_free(cwork);
4270 return;
4271 }
4272
4273 wpa_s->connect_work = work;
4274
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004275 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4276 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004277 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4278 wpas_connect_work_done(wpa_s);
4279 return;
4280 }
4281
Sunil Ravi640215c2023-06-28 23:08:09 +00004282 /*
4283 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4284 * (for MLO connection) as the previous BSSID for reassociation requests
4285 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4286 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4287 * will be zero.
4288 */
4289 os_memcpy(prev_bssid,
4290 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4291 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 os_memset(&params, 0, sizeof(params));
4293 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004294 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004295
4296 /* Starting new association, so clear the possibly used WPA IE from the
4297 * previous association. */
4298 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4299 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4300 wpa_s->rsnxe_len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004301#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom60840252021-02-19 19:02:11 -08004302 wpa_s->mscs_setup_done = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004303#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08004304
4305 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4306 if (!wpa_ie) {
4307 wpas_connect_work_done(wpa_s);
4308 return;
4309 }
4310
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004311 if (bss &&
4312 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313#ifdef CONFIG_IEEE80211R
4314 const u8 *ie, *md = NULL;
4315#endif /* CONFIG_IEEE80211R */
4316 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4317 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4318 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4319 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4320 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4321 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4322 if (bssid_changed)
4323 wpas_notify_bssid_changed(wpa_s);
4324#ifdef CONFIG_IEEE80211R
4325 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4326 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4327 md = ie + 2;
4328 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4329 if (md) {
4330 /* Prepare for the next transition */
4331 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4332 }
4333#endif /* CONFIG_IEEE80211R */
4334#ifdef CONFIG_WPS
4335 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4336 wpa_s->conf->ap_scan == 2 &&
4337 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4338 /* Use ap_scan==1 style network selection to find the network
4339 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004340 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004341 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004342 wpa_s->reassociate = 1;
4343 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004344 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 return;
4346#endif /* CONFIG_WPS */
4347 } else {
4348 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4349 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004350 if (bss)
4351 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4352 else
4353 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004355 if (!wpa_s->pno)
4356 wpa_supplicant_cancel_sched_scan(wpa_s);
4357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358 wpa_supplicant_cancel_scan(wpa_s);
4359
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4361 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004362 cipher_pairwise = wpa_s->pairwise_cipher;
4363 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004364 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004365 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4366 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4368 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004369#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004370 if (wpa_set_wep_keys(wpa_s, ssid)) {
4371 use_crypt = 1;
4372 wep_keys_set = 1;
4373 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004374#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375 }
4376 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4377 use_crypt = 0;
4378
4379#ifdef IEEE8021X_EAPOL
4380 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4381 if ((ssid->eapol_flags &
4382 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4383 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4384 !wep_keys_set) {
4385 use_crypt = 0;
4386 } else {
4387 /* Assume that dynamic WEP-104 keys will be used and
4388 * set cipher suites in order for drivers to expect
4389 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004390 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391 }
4392 }
4393#endif /* IEEE8021X_EAPOL */
4394
4395 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4396 /* Set the key before (and later after) association */
4397 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4398 }
4399
Sunil8cd6f4d2022-06-28 18:40:46 +00004400 /* Set current_ssid before changing state to ASSOCIATING, so that the
4401 * selected SSID is available to wpas_notify_state_changed(). */
4402 old_ssid = wpa_s->current_ssid;
4403 wpa_s->current_ssid = ssid;
4404
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004405 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4406 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407 params.ssid = bss->ssid;
4408 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004409 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4410 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004411 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4412 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004413 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004414 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004415 ssid->bssid_set,
4416 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004417 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004418 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004419 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004420 params.bssid_hint = bss->bssid;
4421 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004422 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004423 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004424 if (ssid->bssid_hint_set)
4425 params.bssid_hint = ssid->bssid_hint;
4426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004427 params.ssid = ssid->ssid;
4428 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004429 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004430 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004431
4432 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4433 wpa_s->conf->ap_scan == 2) {
4434 params.bssid = ssid->bssid;
4435 params.fixed_bssid = 1;
4436 }
4437
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004438 /* Initial frequency for IBSS/mesh */
4439 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004440 ssid->frequency > 0 && params.freq.freq == 0)
4441 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004442
4443 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004444 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004445 if (ssid->beacon_int)
4446 params.beacon_int = ssid->beacon_int;
4447 else
4448 params.beacon_int = wpa_s->conf->beacon_int;
4449 }
4450
Hai Shalomc3565922019-10-28 11:58:20 -07004451 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004452 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4453 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004454 else
4455 edmg_ie_oper = NULL;
4456
4457 if (edmg_ie_oper) {
4458 params.freq.edmg.channels =
4459 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4460 params.freq.edmg.bw_config =
4461 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4462 wpa_printf(MSG_DEBUG,
4463 "AP supports EDMG channels 0x%x, bw_config %d",
4464 params.freq.edmg.channels,
4465 params.freq.edmg.bw_config);
4466
4467 /* User may ask for specific EDMG channel for EDMG connection
4468 * (must be supported by AP)
4469 */
4470 if (ssid->edmg_channel) {
4471 struct ieee80211_edmg_config configured_edmg;
4472 enum hostapd_hw_mode hw_mode;
4473 u8 primary_channel;
4474
4475 hw_mode = ieee80211_freq_to_chan(bss->freq,
4476 &primary_channel);
4477 if (hw_mode == NUM_HOSTAPD_MODES)
4478 goto edmg_fail;
4479
4480 hostapd_encode_edmg_chan(ssid->enable_edmg,
4481 ssid->edmg_channel,
4482 primary_channel,
4483 &configured_edmg);
4484
4485 if (ieee802_edmg_is_allowed(params.freq.edmg,
4486 configured_edmg)) {
4487 params.freq.edmg = configured_edmg;
4488 wpa_printf(MSG_DEBUG,
4489 "Use EDMG channel %d for connection",
4490 ssid->edmg_channel);
4491 } else {
4492 edmg_fail:
4493 params.freq.edmg.channels = 0;
4494 params.freq.edmg.bw_config = 0;
4495 wpa_printf(MSG_WARNING,
4496 "EDMG channel %d not supported by AP, fallback to DMG",
4497 ssid->edmg_channel);
4498 }
4499 }
4500
4501 if (params.freq.edmg.channels) {
4502 wpa_printf(MSG_DEBUG,
4503 "EDMG before: channels 0x%x, bw_config %d",
4504 params.freq.edmg.channels,
4505 params.freq.edmg.bw_config);
4506 params.freq.edmg = get_supported_edmg(wpa_s,
4507 &params.freq,
4508 params.freq.edmg);
4509 wpa_printf(MSG_DEBUG,
4510 "EDMG after: channels 0x%x, bw_config %d",
4511 params.freq.edmg.channels,
4512 params.freq.edmg.bw_config);
4513 }
4514 }
4515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004516 params.pairwise_suite = cipher_pairwise;
4517 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004518 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004519 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004520 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004521 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004522 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004523 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004524 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004525#ifdef CONFIG_WEP
4526 {
4527 int i;
4528
4529 for (i = 0; i < NUM_WEP_KEYS; i++) {
4530 if (ssid->wep_key_len[i])
4531 params.wep_key[i] = ssid->wep_key[i];
4532 params.wep_key_len[i] = ssid->wep_key_len[i];
4533 }
4534 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004535 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004536#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537
Hai Shalom74f70d42019-02-11 14:42:39 -08004538 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004539#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4540 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004541 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4542 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004543#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4544 defined(CONFIG_DRIVER_NL80211_SYNA)
4545 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4546 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4547 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4548 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304549#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004550 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4551 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4552 (params.allowed_key_mgmts &
4553 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004554#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4555 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004556 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004557 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4558 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004559 }
4560
Hai Shalom74f70d42019-02-11 14:42:39 -08004561 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4562 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4563 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4564 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004565 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4566 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004567 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004568
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004569 if (wpa_s->conf->key_mgmt_offload) {
4570 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4571 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004572 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004573 params.key_mgmt_suite ==
4574 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4575 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004576 params.req_key_mgmt_offload =
4577 ssid->proactive_key_caching < 0 ?
4578 wpa_s->conf->okc : ssid->proactive_key_caching;
4579 else
4580 params.req_key_mgmt_offload = 1;
4581
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004582#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4583 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004584 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004585 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4586 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004587#else
4588 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4589 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004590#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4591 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004592 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4593 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004594 }
4595
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004596 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4597 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4598 params.auth_alg = WPA_AUTH_ALG_SAE;
4599 if (ssid->sae_password) {
4600 params.sae_password = ssid->sae_password;
4601 params.sae_password_id = ssid->sae_password_id;
4602 } else if (ssid->passphrase) {
4603 params.passphrase = ssid->passphrase;
4604 }
4605 }
4606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607 params.drop_unencrypted = use_crypt;
4608
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004609 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004610 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004611 const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004612 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004613 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4614 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615 ie.capabilities &
4616 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4617 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4618 "MFP: require MFP");
4619 params.mgmt_frame_protection =
4620 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004621#ifdef CONFIG_OWE
4622 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4623 !ssid->owe_only) {
4624 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4625#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004626 }
4627 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004629 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004631 if (wpa_s->p2pdev->set_sta_uapsd)
4632 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004633 else
4634 params.uapsd = -1;
4635
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004636#ifdef CONFIG_HT_OVERRIDES
4637 os_memset(&htcaps, 0, sizeof(htcaps));
4638 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4639 params.htcaps = (u8 *) &htcaps;
4640 params.htcaps_mask = (u8 *) &htcaps_mask;
4641 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4642#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004643#ifdef CONFIG_VHT_OVERRIDES
4644 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4645 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4646 params.vhtcaps = &vhtcaps;
4647 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004648 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004649#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004650#ifdef CONFIG_HE_OVERRIDES
4651 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4652#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004653 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004654
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004655#ifdef CONFIG_P2P
4656 /*
4657 * If multi-channel concurrency is not supported, check for any
4658 * frequency conflict. In case of any frequency conflict, remove the
4659 * least prioritized connection.
4660 */
4661 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004662 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004663 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004664 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004665 wpa_printf(MSG_DEBUG,
4666 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004667 freq, params.freq.freq);
4668 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004669 wpa_s, params.freq.freq, ssid) < 0) {
4670 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004671 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004672 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004673 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004674 }
4675 }
4676#endif /* CONFIG_P2P */
4677
Dmitry Shmidte4663042016-04-04 10:07:49 -07004678 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004679 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004680 params.prev_bssid = prev_bssid;
4681
Hai Shalom60840252021-02-19 19:02:11 -08004682#ifdef CONFIG_SAE
4683 params.sae_pwe = wpa_s->conf->sae_pwe;
4684#endif /* CONFIG_SAE */
4685
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004686 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004687 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004688 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004689 if (ret < 0) {
4690 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4691 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004692 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004693 /*
4694 * The driver is known to mean what is saying, so we
4695 * can stop right here; the association will not
4696 * succeed.
4697 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004698 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
4699 NULL);
Roger Wang4c09cc92020-11-05 18:57:12 +08004700 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004701 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004702 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4704 return;
4705 }
4706 /* try to continue anyway; new association will be tried again
4707 * after timeout */
4708 assoc_failed = 1;
4709 }
4710
4711 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4712 /* Set the key after the association just in case association
4713 * cleared the previously configured key. */
4714 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4715 /* No need to timeout authentication since there is no key
4716 * management. */
4717 wpa_supplicant_cancel_auth_timeout(wpa_s);
4718 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4719#ifdef CONFIG_IBSS_RSN
4720 } else if (ssid->mode == WPAS_MODE_IBSS &&
4721 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4722 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4723 /*
4724 * RSN IBSS authentication is per-STA and we can disable the
4725 * per-BSSID authentication.
4726 */
4727 wpa_supplicant_cancel_auth_timeout(wpa_s);
4728#endif /* CONFIG_IBSS_RSN */
4729 } else {
4730 /* Timeout for IEEE 802.11 authentication and association */
4731 int timeout = 60;
4732
4733 if (assoc_failed) {
4734 /* give IBSS a bit more time */
4735 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4736 } else if (wpa_s->conf->ap_scan == 1) {
4737 /* give IBSS a bit more time */
4738 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4739 }
4740 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4741 }
4742
Hai Shalomfdcde762020-04-02 11:19:20 -07004743#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004744 if (wep_keys_set &&
4745 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004746 /* Set static WEP keys again */
4747 wpa_set_wep_keys(wpa_s, ssid);
4748 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004749#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004750
Sunil8cd6f4d2022-06-28 18:40:46 +00004751 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004752 /*
4753 * Do not allow EAP session resumption between different
4754 * network configurations.
4755 */
4756 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4757 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004758
mtk30479d7f89782024-01-24 11:51:43 +08004759 if (!wpas_driver_bss_selection(wpa_s) ||
4760#ifdef CONFIG_P2P
4761 wpa_s->p2p_in_invitation ||
4762#endif /* CONFIG_P2P */
4763 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004764 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004765#ifdef CONFIG_HS20
4766 hs20_configure_frame_filters(wpa_s);
4767#endif /* CONFIG_HS20 */
4768 }
4769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
Sunil Ravi7f769292024-07-23 22:21:32 +00004771 if (bss)
4772 wpa_sm_set_ssid(wpa_s->wpa, bss->ssid, bss->ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004773 wpa_supplicant_initiate_eapol(wpa_s);
4774 if (old_ssid != wpa_s->current_ssid)
4775 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004776 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4777 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778}
4779
4780
4781static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4782 const u8 *addr)
4783{
4784 struct wpa_ssid *old_ssid;
4785
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004786 wpa_s->ml_connect_probe_ssid = NULL;
4787 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004788 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004789 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004790 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004791 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004792 wpa_sm_set_config(wpa_s->wpa, NULL);
4793 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4794 if (old_ssid != wpa_s->current_ssid)
4795 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004796
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004797#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08004798 wpas_scs_deinit(wpa_s);
4799 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004800#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4802}
4803
4804
4805/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4807 * @wpa_s: Pointer to wpa_supplicant data
4808 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4809 *
4810 * This function is used to request %wpa_supplicant to deauthenticate from the
4811 * current AP.
4812 */
4813void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004814 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815{
4816 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004817 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004818 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004819
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004820 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Sunil Ravi7f769292024-07-23 22:21:32 +00004821 " pending_bssid=" MACSTR
4822 " reason=%d (%s) state=%s valid_links=0x%x ap_mld_addr=" MACSTR,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004823 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004824 reason_code, reason2str(reason_code),
Sunil Ravi7f769292024-07-23 22:21:32 +00004825 wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_s->valid_links,
4826 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004827
Sunil Ravi7f769292024-07-23 22:21:32 +00004828 if (wpa_s->valid_links && !is_zero_ether_addr(wpa_s->ap_mld_addr))
4829 addr = wpa_s->ap_mld_addr;
4830 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4831 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4832 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004833 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004834 else if (!is_zero_ether_addr(wpa_s->bssid))
4835 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004836 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4837 /*
4838 * When using driver-based BSS selection, we may not know the
4839 * BSSID with which we are currently trying to associate. We
4840 * need to notify the driver of this disconnection even in such
4841 * a case, so use the all zeros address here.
4842 */
4843 addr = wpa_s->bssid;
4844 zero_addr = 1;
4845 }
4846
Hai Shalom74f70d42019-02-11 14:42:39 -08004847 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4848 wpa_s->enabled_4addr_mode = 0;
4849
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004850#ifdef CONFIG_TDLS
4851 wpa_tdls_teardown_peers(wpa_s->wpa);
4852#endif /* CONFIG_TDLS */
4853
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004854#ifdef CONFIG_MESH
4855 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004856 struct mesh_conf *mconf;
4857
4858 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004859 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4860 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004861 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4862 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004863 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004864 }
4865#endif /* CONFIG_MESH */
4866
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004867 if (addr) {
4868 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004869 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004870 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004871 event.deauth_info.locally_generated = 1;
4872 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004873 if (zero_addr)
4874 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004875 }
4876
4877 wpa_supplicant_clear_connection(wpa_s, addr);
4878}
4879
Hai Shalomfdcde762020-04-02 11:19:20 -07004880
4881void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4882{
4883 wpa_s->own_reconnect_req = 1;
4884 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4885
4886}
4887
4888
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004889static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4890 struct wpa_ssid *ssid)
4891{
4892 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4893 return;
4894
4895 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004896 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004897 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4898 wpas_notify_network_enabled_changed(wpa_s, ssid);
4899
4900 /*
4901 * Try to reassociate since there is no current configuration and a new
4902 * network was made available.
4903 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004904 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004905 wpa_s->reassociate = 1;
4906}
4907
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004908
Roshan Pius950bec92016-07-19 09:49:24 -07004909/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004910 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004911 * @wpa_s: wpa_supplicant structure for a network interface
4912 * Returns: The new network configuration or %NULL if operation failed
4913 *
4914 * This function performs the following operations:
4915 * 1. Adds a new network.
4916 * 2. Send network addition notification.
4917 * 3. Marks the network disabled.
4918 * 4. Set network default parameters.
4919 */
4920struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4921{
4922 struct wpa_ssid *ssid;
4923
4924 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004925 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004926 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004927 wpas_notify_network_added(wpa_s, ssid);
4928 ssid->disabled = 1;
4929 wpa_config_set_network_defaults(ssid);
4930
4931 return ssid;
4932}
4933
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004934
Roshan Pius950bec92016-07-19 09:49:24 -07004935/**
4936 * wpa_supplicant_remove_network - Remove a configured network based on id
4937 * @wpa_s: wpa_supplicant structure for a network interface
4938 * @id: Unique network id to search for
4939 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4940 * could not be removed
4941 *
4942 * This function performs the following operations:
4943 * 1. Removes the network.
4944 * 2. Send network removal notification.
4945 * 3. Update internal state machines.
4946 * 4. Stop any running sched scans.
4947 */
4948int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4949{
Sunil Ravia04bd252022-05-02 22:54:18 -07004950 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004951 int was_disabled;
4952
4953 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004954 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004955 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004956 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004957
Sunil Ravia04bd252022-05-02 22:54:18 -07004958 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004959#ifdef CONFIG_SME
4960 wpa_s->sme.prev_bssid_set = 0;
4961#endif /* CONFIG_SME */
4962 /*
4963 * Invalidate the EAP session cache if the current or
4964 * previously used network is removed.
4965 */
4966 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4967 }
4968
Sunil Ravia04bd252022-05-02 22:54:18 -07004969 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004970 wpa_sm_set_config(wpa_s->wpa, NULL);
4971 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4972
4973 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4974 wpa_s->own_disconnect_req = 1;
4975 wpa_supplicant_deauthenticate(wpa_s,
4976 WLAN_REASON_DEAUTH_LEAVING);
4977 }
4978
4979 was_disabled = ssid->disabled;
4980
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004981 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004982 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004983
4984 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004985 wpa_printf(MSG_DEBUG,
4986 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004987 wpa_supplicant_cancel_sched_scan(wpa_s);
4988 wpa_supplicant_req_scan(wpa_s, 0, 0);
4989 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004990
Roshan Pius950bec92016-07-19 09:49:24 -07004991 return 0;
4992}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004993
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004995/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004996 * wpa_supplicant_remove_all_networks - Remove all configured networks
4997 * @wpa_s: wpa_supplicant structure for a network interface
4998 * Returns: 0 on success (errors are currently ignored)
4999 *
5000 * This function performs the following operations:
5001 * 1. Remove all networks.
5002 * 2. Send network removal notifications.
5003 * 3. Update internal state machines.
5004 * 4. Stop any running sched scans.
5005 */
5006int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
5007{
5008 struct wpa_ssid *ssid;
5009
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05305010 if (wpa_s->drv_flags2 &
5011 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
5012 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
5013 wpa_drv_flush_pmkid(wpa_s);
5014
Hai Shalom899fcc72020-10-19 14:38:18 -07005015 if (wpa_s->sched_scanning)
5016 wpa_supplicant_cancel_sched_scan(wpa_s);
5017
5018 eapol_sm_invalidate_cached_session(wpa_s->eapol);
5019 if (wpa_s->current_ssid) {
5020#ifdef CONFIG_SME
5021 wpa_s->sme.prev_bssid_set = 0;
5022#endif /* CONFIG_SME */
5023 wpa_sm_set_config(wpa_s->wpa, NULL);
5024 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
5025 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5026 wpa_s->own_disconnect_req = 1;
5027 wpa_supplicant_deauthenticate(
5028 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5029 }
5030 ssid = wpa_s->conf->ssid;
5031 while (ssid) {
5032 struct wpa_ssid *remove_ssid = ssid;
5033 int id;
5034
5035 id = ssid->id;
5036 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07005037 wpas_notify_network_removed(wpa_s, remove_ssid);
5038 wpa_config_remove_network(wpa_s->conf, id);
5039 }
5040 return 0;
5041}
5042
5043
5044/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005045 * wpa_supplicant_enable_network - Mark a configured network as enabled
5046 * @wpa_s: wpa_supplicant structure for a network interface
5047 * @ssid: wpa_ssid structure for a configured network or %NULL
5048 *
5049 * Enables the specified network or all networks if no network specified.
5050 */
5051void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
5052 struct wpa_ssid *ssid)
5053{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005054 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005055 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5056 wpa_supplicant_enable_one_network(wpa_s, ssid);
5057 } else
5058 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005059
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005060 if (wpa_s->reassociate && !wpa_s->disconnected &&
5061 (!wpa_s->current_ssid ||
5062 wpa_s->wpa_state == WPA_DISCONNECTED ||
5063 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005064 if (wpa_s->sched_scanning) {
5065 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
5066 "new network to scan filters");
5067 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005068 }
5069
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005070 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
5071 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07005072 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005073 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005074 }
5075}
5076
5077
5078/**
5079 * wpa_supplicant_disable_network - Mark a configured network as disabled
5080 * @wpa_s: wpa_supplicant structure for a network interface
5081 * @ssid: wpa_ssid structure for a configured network or %NULL
5082 *
5083 * Disables the specified network or all networks if no network specified.
5084 */
5085void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
5086 struct wpa_ssid *ssid)
5087{
5088 struct wpa_ssid *other_ssid;
5089 int was_disabled;
5090
5091 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005092 if (wpa_s->sched_scanning)
5093 wpa_supplicant_cancel_sched_scan(wpa_s);
5094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005095 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5096 other_ssid = other_ssid->next) {
5097 was_disabled = other_ssid->disabled;
5098 if (was_disabled == 2)
5099 continue; /* do not change persistent P2P group
5100 * data */
5101
5102 other_ssid->disabled = 1;
5103
5104 if (was_disabled != other_ssid->disabled)
5105 wpas_notify_network_enabled_changed(
5106 wpa_s, other_ssid);
5107 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005108 if (wpa_s->current_ssid) {
5109 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5110 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005111 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005112 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005113 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005115 if (ssid == wpa_s->current_ssid) {
5116 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5117 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005118 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005119 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005120 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005121
5122 was_disabled = ssid->disabled;
5123
5124 ssid->disabled = 1;
5125
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005126 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005127 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005128 if (wpa_s->sched_scanning) {
5129 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
5130 "to remove network from filters");
5131 wpa_supplicant_cancel_sched_scan(wpa_s);
5132 wpa_supplicant_req_scan(wpa_s, 0, 0);
5133 }
5134 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005135 }
5136}
5137
5138
5139/**
5140 * wpa_supplicant_select_network - Attempt association with a network
5141 * @wpa_s: wpa_supplicant structure for a network interface
5142 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
5143 */
5144void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
5145 struct wpa_ssid *ssid)
5146{
5147
5148 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005149 int disconnected = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00005150 bool request_new_scan = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005152 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005153 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5154 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005155 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005156 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005157 disconnected = 1;
5158 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005159
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005160 if (ssid)
5161 wpas_clear_temp_disabled(wpa_s, ssid, 1);
5162
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005163 /*
5164 * Mark all other networks disabled or mark all networks enabled if no
5165 * network specified.
5166 */
5167 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5168 other_ssid = other_ssid->next) {
5169 int was_disabled = other_ssid->disabled;
5170 if (was_disabled == 2)
5171 continue; /* do not change persistent P2P group data */
5172
5173 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005174 if (was_disabled && !other_ssid->disabled)
5175 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005176
5177 if (was_disabled != other_ssid->disabled)
5178 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
5179 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005180
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005181 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
5182 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005183 /* We are already associated with the selected network */
5184 wpa_printf(MSG_DEBUG, "Already associated with the "
5185 "selected network - do nothing");
5186 return;
5187 }
5188
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005189 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005190 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005191 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005192 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00005193 (ssid->mode == WPAS_MODE_MESH ||
5194 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005195
Sunil Ravi7f769292024-07-23 22:21:32 +00005196 if (ssid->scan_ssid &&
5197 (wpa_s->no_suitable_network || wpa_s->last_scan_external)) {
5198 wpa_printf(MSG_DEBUG,
5199 "Request a new scan for hidden network");
5200 request_new_scan = true;
5201 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
5202 !ssid->owe_only) {
5203 wpa_printf(MSG_DEBUG,
5204 "Request a new scan for OWE transition SSID");
5205 request_new_scan = true;
5206 }
5207
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005208 /*
5209 * Don't optimize next scan freqs since a new ESS has been
5210 * selected.
5211 */
5212 os_free(wpa_s->next_scan_freqs);
5213 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005214 } else {
5215 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005216 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005218 wpa_s->disconnected = 0;
5219 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005220 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005221 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005222 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005223 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07005224 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07005225 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005226
Sunil Ravi7f769292024-07-23 22:21:32 +00005227 if (wpa_s->connect_without_scan || request_new_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005228 wpa_supplicant_fast_associate(wpa_s) != 1) {
5229 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005230 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005231 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233
5234 if (ssid)
5235 wpas_notify_network_selected(wpa_s, ssid);
5236}
5237
5238
5239/**
Hai Shalomc1a21442022-02-04 13:43:00 -08005240 * wpas_remove_cred - Remove the specified credential and all the network
5241 * entries created based on the removed credential
5242 * @wpa_s: wpa_supplicant structure for a network interface
5243 * @cred: The credential to remove
5244 * Returns: 0 on success, -1 on failure
5245 */
5246int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
5247{
5248 struct wpa_ssid *ssid, *next;
5249 int id;
5250
5251 if (!cred) {
5252 wpa_printf(MSG_DEBUG, "Could not find cred");
5253 return -1;
5254 }
5255
5256 id = cred->id;
5257 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5258 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5259 return -1;
5260 }
5261
5262 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5263
5264 /* Remove any network entry created based on the removed credential */
5265 ssid = wpa_s->conf->ssid;
5266 while (ssid) {
5267 next = ssid->next;
5268
5269 if (ssid->parent_cred == cred) {
5270 wpa_printf(MSG_DEBUG,
5271 "Remove network id %d since it used the removed credential",
5272 ssid->id);
5273 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5274 -1) {
5275 wpa_printf(MSG_DEBUG,
5276 "Could not find network id=%d",
5277 ssid->id);
5278 }
5279 }
5280
5281 ssid = next;
5282 }
5283
5284 return 0;
5285}
5286
5287
5288/**
5289 * wpas_remove_cred - Remove all the Interworking credentials
5290 * @wpa_s: wpa_supplicant structure for a network interface
5291 * Returns: 0 on success, -1 on failure
5292 */
5293int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5294{
5295 int res, ret = 0;
5296 struct wpa_cred *cred, *prev;
5297
5298 cred = wpa_s->conf->cred;
5299 while (cred) {
5300 prev = cred;
5301 cred = cred->next;
5302 res = wpas_remove_cred(wpa_s, prev);
5303 if (res < 0) {
5304 wpa_printf(MSG_DEBUG,
5305 "Removal of all credentials failed - failed to remove credential id=%d",
5306 prev->id);
5307 ret = -1;
5308 }
5309 }
5310
5311 return ret;
5312}
5313
5314
5315/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005316 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5317 * @wpa_s: wpa_supplicant structure for a network interface
5318 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5319 * @pkcs11_module_path: PKCS #11 module path or NULL
5320 * Returns: 0 on success; -1 on failure
5321 *
5322 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5323 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5324 * module path fails the paths will be reset to the default value (NULL).
5325 */
5326int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5327 const char *pkcs11_engine_path,
5328 const char *pkcs11_module_path)
5329{
5330 char *pkcs11_engine_path_copy = NULL;
5331 char *pkcs11_module_path_copy = NULL;
5332
5333 if (pkcs11_engine_path != NULL) {
5334 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5335 if (pkcs11_engine_path_copy == NULL)
5336 return -1;
5337 }
5338 if (pkcs11_module_path != NULL) {
5339 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005340 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005341 os_free(pkcs11_engine_path_copy);
5342 return -1;
5343 }
5344 }
5345
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005346#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005347 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005348 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005349#endif /* CONFIG_PKCS11_ENGINE_PATH */
5350#ifndef CONFIG_PKCS11_MODULE_PATH
5351 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005352 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005353#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005354
5355 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5356 eapol_sm_deinit(wpa_s->eapol);
5357 wpa_s->eapol = NULL;
5358 if (wpa_supplicant_init_eapol(wpa_s)) {
5359 /* Error -> Reset paths to the default value (NULL) once. */
5360 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5361 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5362 NULL);
5363
5364 return -1;
5365 }
5366 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5367
5368 return 0;
5369}
5370
5371
5372/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5374 * @wpa_s: wpa_supplicant structure for a network interface
5375 * @ap_scan: AP scan mode
5376 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5377 *
5378 */
5379int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5380{
5381
5382 int old_ap_scan;
5383
5384 if (ap_scan < 0 || ap_scan > 2)
5385 return -1;
5386
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005387 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5388 wpa_printf(MSG_INFO,
5389 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5390 }
5391
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005392#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005393 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5394 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5395 wpa_s->wpa_state < WPA_COMPLETED) {
5396 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5397 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005398 return 0;
5399 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005400#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005402 old_ap_scan = wpa_s->conf->ap_scan;
5403 wpa_s->conf->ap_scan = ap_scan;
5404
5405 if (old_ap_scan != wpa_s->conf->ap_scan)
5406 wpas_notify_ap_scan_changed(wpa_s);
5407
5408 return 0;
5409}
5410
5411
5412/**
5413 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5414 * @wpa_s: wpa_supplicant structure for a network interface
5415 * @expire_age: Expiration age in seconds
5416 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5417 *
5418 */
5419int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5420 unsigned int bss_expire_age)
5421{
5422 if (bss_expire_age < 10) {
5423 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5424 bss_expire_age);
5425 return -1;
5426 }
5427 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5428 bss_expire_age);
5429 wpa_s->conf->bss_expiration_age = bss_expire_age;
5430
5431 return 0;
5432}
5433
5434
5435/**
5436 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5437 * @wpa_s: wpa_supplicant structure for a network interface
5438 * @expire_count: number of scans after which an unseen BSS is reclaimed
5439 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5440 *
5441 */
5442int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5443 unsigned int bss_expire_count)
5444{
5445 if (bss_expire_count < 1) {
5446 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5447 bss_expire_count);
5448 return -1;
5449 }
5450 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5451 bss_expire_count);
5452 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5453
5454 return 0;
5455}
5456
5457
5458/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005459 * wpa_supplicant_set_scan_interval - Set scan interval
5460 * @wpa_s: wpa_supplicant structure for a network interface
5461 * @scan_interval: scan interval in seconds
5462 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5463 *
5464 */
5465int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5466 int scan_interval)
5467{
5468 if (scan_interval < 0) {
5469 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5470 scan_interval);
5471 return -1;
5472 }
5473 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5474 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005475 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005476
5477 return 0;
5478}
5479
5480
5481/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005482 * wpa_supplicant_set_debug_params - Set global debug params
5483 * @global: wpa_global structure
5484 * @debug_level: debug level
5485 * @debug_timestamp: determines if show timestamp in debug data
5486 * @debug_show_keys: determines if show keys in debug data
5487 * Returns: 0 if succeed or -1 if debug_level has wrong value
5488 */
5489int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5490 int debug_timestamp, int debug_show_keys)
5491{
5492
5493 int old_level, old_timestamp, old_show_keys;
5494
5495 /* check for allowed debuglevels */
5496 if (debug_level != MSG_EXCESSIVE &&
5497 debug_level != MSG_MSGDUMP &&
5498 debug_level != MSG_DEBUG &&
5499 debug_level != MSG_INFO &&
5500 debug_level != MSG_WARNING &&
5501 debug_level != MSG_ERROR)
5502 return -1;
5503
5504 old_level = wpa_debug_level;
5505 old_timestamp = wpa_debug_timestamp;
5506 old_show_keys = wpa_debug_show_keys;
5507
5508 wpa_debug_level = debug_level;
5509 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5510 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5511
5512 if (wpa_debug_level != old_level)
5513 wpas_notify_debug_level_changed(global);
5514 if (wpa_debug_timestamp != old_timestamp)
5515 wpas_notify_debug_timestamp_changed(global);
5516 if (wpa_debug_show_keys != old_show_keys)
5517 wpas_notify_debug_show_keys_changed(global);
5518
5519 return 0;
5520}
5521
5522
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005523#ifdef CONFIG_OWE
5524static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5525 const u8 *entry_ssid, size_t entry_ssid_len)
5526{
Sunil Ravic0f5d412024-09-11 22:12:49 +00005527 const u8 *owe, *owe_bssid, *owe_ssid;
5528 size_t owe_ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005529 struct wpa_bss *bss;
5530
5531 /* Check network profile SSID aganst the SSID in the
5532 * OWE Transition Mode element. */
5533
5534 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5535 if (!bss)
5536 return 0;
5537
5538 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5539 if (!owe)
5540 return 0;
5541
Sunil Ravic0f5d412024-09-11 22:12:49 +00005542 if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
5543 &owe_ssid_len))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005544 return 0;
5545
Sunil Ravic0f5d412024-09-11 22:12:49 +00005546 return entry_ssid_len == owe_ssid_len &&
5547 os_memcmp(owe_ssid, entry_ssid, owe_ssid_len) == 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005548}
5549#endif /* CONFIG_OWE */
5550
5551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005552/**
5553 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5554 * @wpa_s: Pointer to wpa_supplicant data
5555 * Returns: A pointer to the current network structure or %NULL on failure
5556 */
5557struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5558{
5559 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005560 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005561 int res;
5562 size_t ssid_len;
5563 u8 bssid[ETH_ALEN];
5564 int wired;
5565
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005566 res = wpa_drv_get_ssid(wpa_s, ssid);
5567 if (res < 0) {
5568 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5569 "driver");
5570 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005571 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005572 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005574 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005575 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5576 "driver");
5577 return NULL;
5578 }
5579
5580 wired = wpa_s->conf->ap_scan == 0 &&
5581 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5582
5583 entry = wpa_s->conf->ssid;
5584 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005585 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005586 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005587 (!entry->ssid ||
5588 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5589 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005590 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005591 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005592 return entry;
5593#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005594 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005595 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5596 (entry->ssid == NULL || entry->ssid_len == 0) &&
5597 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005598 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005599 return entry;
5600#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005601
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005602#ifdef CONFIG_OWE
5603 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005604 (entry->ssid &&
5605 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5606 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005607 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005608 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005609 return entry;
5610#endif /* CONFIG_OWE */
5611
Dmitry Shmidt04949592012-07-19 12:16:46 -07005612 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005613 entry->ssid_len == 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005614 ether_addr_equal(bssid, entry->bssid))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005615 return entry;
5616
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617 entry = entry->next;
5618 }
5619
5620 return NULL;
5621}
5622
5623
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005624static int select_driver(struct wpa_supplicant *wpa_s, int i)
5625{
5626 struct wpa_global *global = wpa_s->global;
5627
5628 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005629 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005630 if (global->drv_priv[i] == NULL) {
5631 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5632 "'%s'", wpa_drivers[i]->name);
5633 return -1;
5634 }
5635 }
5636
5637 wpa_s->driver = wpa_drivers[i];
5638 wpa_s->global_drv_priv = global->drv_priv[i];
5639
5640 return 0;
5641}
5642
5643
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005644static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5645 const char *name)
5646{
5647 int i;
5648 size_t len;
5649 const char *pos, *driver = name;
5650
5651 if (wpa_s == NULL)
5652 return -1;
5653
5654 if (wpa_drivers[0] == NULL) {
5655 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5656 "wpa_supplicant");
5657 return -1;
5658 }
5659
5660 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005661 /* Default to first successful driver in the list */
5662 for (i = 0; wpa_drivers[i]; i++) {
5663 if (select_driver(wpa_s, i) == 0)
5664 return 0;
5665 }
5666 /* Drivers have each reported failure, so no wpa_msg() here. */
5667 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005668 }
5669
5670 do {
5671 pos = os_strchr(driver, ',');
5672 if (pos)
5673 len = pos - driver;
5674 else
5675 len = os_strlen(driver);
5676
5677 for (i = 0; wpa_drivers[i]; i++) {
5678 if (os_strlen(wpa_drivers[i]->name) == len &&
5679 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005680 0) {
5681 /* First driver that succeeds wins */
5682 if (select_driver(wpa_s, i) == 0)
5683 return 0;
5684 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685 }
5686
5687 driver = pos + 1;
5688 } while (pos);
5689
5690 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5691 return -1;
5692}
5693
5694
5695/**
5696 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5697 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5698 * with struct wpa_driver_ops::init()
5699 * @src_addr: Source address of the EAPOL frame
5700 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5701 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005702 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005703 *
5704 * This function is called for each received EAPOL frame. Most driver
5705 * interfaces rely on more generic OS mechanism for receiving frames through
5706 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5707 * take care of received EAPOL frames and deliver them to the core supplicant
5708 * code by calling this function.
5709 */
5710void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005711 const u8 *buf, size_t len,
5712 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713{
5714 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005715 const u8 *connected_addr = wpa_s->valid_links ?
5716 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005717
Sunil8cd6f4d2022-06-28 18:40:46 +00005718 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5719 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005720 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5721
Hai Shalomc1a21442022-02-04 13:43:00 -08005722 if (wpa_s->own_disconnect_req) {
5723 wpa_printf(MSG_DEBUG,
5724 "Drop received EAPOL frame as we are disconnecting");
5725 return;
5726 }
5727
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005728#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005729 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5730 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005731 if (wpa_s->ignore_auth_resp) {
5732 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5733 return;
5734 }
5735#endif /* CONFIG_TESTING_OPTIONS */
5736
Jouni Malinena05074c2012-12-21 21:35:35 +02005737 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5738 (wpa_s->last_eapol_matches_bssid &&
5739#ifdef CONFIG_AP
5740 !wpa_s->ap_iface &&
5741#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005742 !ether_addr_equal(src_addr, connected_addr))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743 /*
5744 * There is possible race condition between receiving the
5745 * association event and the EAPOL frame since they are coming
5746 * through different paths from the driver. In order to avoid
5747 * issues in trying to process the EAPOL frame before receiving
5748 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005749 * the association event is received. This may also be needed in
5750 * driver-based roaming case, so also use src_addr != BSSID as a
5751 * trigger if we have previously confirmed that the
5752 * Authenticator uses BSSID as the src_addr (which is not the
5753 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005754 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005755 wpa_dbg(wpa_s, MSG_DEBUG,
5756 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5757 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005758 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005759 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005760 wpabuf_free(wpa_s->pending_eapol_rx);
5761 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5762 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005763 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005764 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5765 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005766 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005767 }
5768 return;
5769 }
5770
Jouni Malinena05074c2012-12-21 21:35:35 +02005771 wpa_s->last_eapol_matches_bssid =
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005772 ether_addr_equal(src_addr, connected_addr);
Jouni Malinena05074c2012-12-21 21:35:35 +02005773
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005774#ifdef CONFIG_AP
5775 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005776 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5777 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005778 return;
5779 }
5780#endif /* CONFIG_AP */
5781
5782 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5783 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5784 "no key management is configured");
5785 return;
5786 }
5787
5788 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005789 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005790 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5791 wpa_s->wpa_state != WPA_COMPLETED) &&
5792 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005793 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005794 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005795 int timeout = 10;
5796
5797 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5798 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5799 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5800 /* Use longer timeout for IEEE 802.1X/EAP */
5801 timeout = 70;
5802 }
5803
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005804#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005805 if (wpa_s->current_ssid && wpa_s->current_bss &&
5806 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5807 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5808 /*
5809 * Use shorter timeout if going through WPS AP iteration
5810 * for PIN config method with an AP that does not
5811 * advertise Selected Registrar.
5812 */
5813 struct wpabuf *wps_ie;
5814
5815 wps_ie = wpa_bss_get_vendor_ie_multi(
5816 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5817 if (wps_ie &&
5818 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5819 timeout = 10;
5820 wpabuf_free(wps_ie);
5821 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005822#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005823
5824 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005825 }
5826 wpa_s->eapol_received++;
5827
5828 if (wpa_s->countermeasures) {
5829 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5830 "EAPOL packet");
5831 return;
5832 }
5833
5834#ifdef CONFIG_IBSS_RSN
5835 if (wpa_s->current_ssid &&
5836 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005837 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5838 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005839 return;
5840 }
5841#endif /* CONFIG_IBSS_RSN */
5842
5843 /* Source address of the incoming EAPOL frame could be compared to the
5844 * current BSSID. However, it is possible that a centralized
5845 * Authenticator could be using another MAC address than the BSSID of
5846 * an AP, so just allow any address to be used for now. The replies are
5847 * still sent to the current BSSID (if available), though. */
5848
5849 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5850 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005851 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5852 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005853 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5854 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005855 return;
5856 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005857 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005858 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5860 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005861 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005862 * handshake processing which would normally set portValid. We
5863 * need this to allow the EAPOL state machines to be completed
5864 * without going through EAPOL-Key handshake.
5865 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005866 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867 }
5868}
5869
5870
Sunil8cd6f4d2022-06-28 18:40:46 +00005871static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5872 const u8 *buf, size_t len)
5873{
5874 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5875 FRAME_ENCRYPTION_UNKNOWN);
5876}
5877
5878
Hai Shalomb755a2a2020-04-23 21:49:02 -07005879static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5880{
5881 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5882 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5883}
5884
5885
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005886int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005887{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005888 u8 prev_mac_addr[ETH_ALEN];
5889
5890 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5891
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005892 if ((!wpa_s->p2p_mgmt ||
5893 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5894 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005895 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005896 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5897 wpa_drv_get_mac_addr(wpa_s),
5898 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005899 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005900 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005901 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005902 if (wpa_s->l2 == NULL)
5903 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005904
5905 if (l2_packet_set_packet_filter(wpa_s->l2,
5906 L2_PACKET_FILTER_PKTTYPE))
5907 wpa_dbg(wpa_s, MSG_DEBUG,
5908 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005909
5910 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5911 wpa_msg(wpa_s, MSG_ERROR,
5912 "Failed to get own L2 address");
5913 return -1;
5914 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005915 } else {
5916 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5917 if (addr)
5918 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5919 }
5920
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005921 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005922 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005923
Hai Shalomc3565922019-10-28 11:58:20 -07005924#ifdef CONFIG_FST
5925 if (wpa_s->fst)
5926 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5927#endif /* CONFIG_FST */
5928
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005929 if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00005930 wpas_notify_mac_address_changed(wpa_s);
5931
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005932 return 0;
5933}
5934
5935
Dmitry Shmidt04949592012-07-19 12:16:46 -07005936static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5937 const u8 *buf, size_t len)
5938{
5939 struct wpa_supplicant *wpa_s = ctx;
5940 const struct l2_ethhdr *eth;
5941
5942 if (len < sizeof(*eth))
5943 return;
5944 eth = (const struct l2_ethhdr *) buf;
5945
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005946 if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005947 !(eth->h_dest[0] & 0x01)) {
5948 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5949 " (bridge - not for this interface - ignore)",
5950 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5951 return;
5952 }
5953
5954 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5955 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5956 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005957 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005958}
5959
5960
Hai Shalom899fcc72020-10-19 14:38:18 -07005961int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5962 const char *bridge_ifname)
5963{
5964 if (wpa_s->wpa_state > WPA_SCANNING)
5965 return -EBUSY;
5966
5967 if (bridge_ifname &&
5968 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5969 return -EINVAL;
5970
5971 if (!bridge_ifname)
5972 bridge_ifname = "";
5973
5974 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5975 return 0;
5976
5977 if (wpa_s->l2_br) {
5978 l2_packet_deinit(wpa_s->l2_br);
5979 wpa_s->l2_br = NULL;
5980 }
5981
5982 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5983 sizeof(wpa_s->bridge_ifname));
5984
5985 if (wpa_s->bridge_ifname[0]) {
5986 wpa_dbg(wpa_s, MSG_DEBUG,
5987 "Receiving packets from bridge interface '%s'",
5988 wpa_s->bridge_ifname);
5989 wpa_s->l2_br = l2_packet_init_bridge(
5990 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5991 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5992 if (!wpa_s->l2_br) {
5993 wpa_msg(wpa_s, MSG_ERROR,
5994 "Failed to open l2_packet connection for the bridge interface '%s'",
5995 wpa_s->bridge_ifname);
5996 goto fail;
5997 }
5998 }
5999
6000#ifdef CONFIG_TDLS
6001 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
6002 goto fail;
6003#endif /* CONFIG_TDLS */
6004
6005 return 0;
6006fail:
6007 wpa_s->bridge_ifname[0] = 0;
6008 if (wpa_s->l2_br) {
6009 l2_packet_deinit(wpa_s->l2_br);
6010 wpa_s->l2_br = NULL;
6011 }
6012#ifdef CONFIG_TDLS
6013 if (!wpa_s->p2p_mgmt)
6014 wpa_tdls_init(wpa_s->wpa);
6015#endif /* CONFIG_TDLS */
6016 return -EIO;
6017}
6018
6019
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006020/**
6021 * wpa_supplicant_driver_init - Initialize driver interface parameters
6022 * @wpa_s: Pointer to wpa_supplicant data
6023 * Returns: 0 on success, -1 on failure
6024 *
6025 * This function is called to initialize driver interface parameters.
6026 * wpa_drv_init() must have been called before this function to initialize the
6027 * driver interface.
6028 */
6029int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
6030{
6031 static int interface_count = 0;
6032
6033 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
6034 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006036 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
6037 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006038 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006039 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
6040
Hai Shalomb755a2a2020-04-23 21:49:02 -07006041 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006042 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
6043 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006044 wpa_s->l2_br = l2_packet_init_bridge(
6045 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
6046 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006047 if (wpa_s->l2_br == NULL) {
6048 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
6049 "connection for the bridge interface '%s'",
6050 wpa_s->bridge_ifname);
6051 return -1;
6052 }
6053 }
6054
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006055 if (wpa_s->conf->ap_scan == 2 &&
6056 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
6057 wpa_printf(MSG_INFO,
6058 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
6059 }
6060
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006061 wpa_clear_keys(wpa_s, NULL);
6062
6063 /* Make sure that TKIP countermeasures are not left enabled (could
6064 * happen if wpa_supplicant is killed during countermeasures. */
6065 wpa_drv_set_countermeasures(wpa_s, 0);
6066
6067 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
6068 wpa_drv_flush_pmkid(wpa_s);
6069
6070 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006071 wpa_s->prev_scan_wildcard = 0;
6072
Dmitry Shmidt04949592012-07-19 12:16:46 -07006073 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08006074 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6075 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
6076 interface_count = 0;
6077 }
Keith Mok4389c282022-11-23 21:36:48 +00006078#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08006079 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07006080 wpa_supplicant_delayed_sched_scan(wpa_s,
6081 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006082 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07006083 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006084 100000);
Keith Mok4389c282022-11-23 21:36:48 +00006085#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006086 interface_count++;
6087 } else
6088 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
6089
6090 return 0;
6091}
6092
6093
6094static int wpa_supplicant_daemon(const char *pid_file)
6095{
6096 wpa_printf(MSG_DEBUG, "Daemonize..");
6097 return os_daemonize(pid_file);
6098}
6099
6100
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006101static struct wpa_supplicant *
6102wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006103{
6104 struct wpa_supplicant *wpa_s;
6105
6106 wpa_s = os_zalloc(sizeof(*wpa_s));
6107 if (wpa_s == NULL)
6108 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006109 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006110 wpa_s->scan_interval = 5;
6111 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006112 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006113 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006114 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08006115 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006116
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006117 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08006118 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07006119#ifdef CONFIG_TESTING_OPTIONS
6120 dl_list_init(&wpa_s->drv_signal_override);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006121 wpa_s->test_assoc_comeback_type = -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07006122#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006123#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08006124 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006125#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00006126 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006128 return wpa_s;
6129}
6130
6131
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006132#ifdef CONFIG_HT_OVERRIDES
6133
6134static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
6135 struct ieee80211_ht_capabilities *htcaps,
6136 struct ieee80211_ht_capabilities *htcaps_mask,
6137 const char *ht_mcs)
6138{
6139 /* parse ht_mcs into hex array */
6140 int i;
6141 const char *tmp = ht_mcs;
6142 char *end = NULL;
6143
6144 /* If ht_mcs is null, do not set anything */
6145 if (!ht_mcs)
6146 return 0;
6147
6148 /* This is what we are setting in the kernel */
6149 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
6150
6151 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
6152
6153 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08006154 long v;
6155
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006156 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08006157 v = strtol(tmp, &end, 16);
6158
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006159 if (errno == 0) {
6160 wpa_msg(wpa_s, MSG_DEBUG,
6161 "htcap value[%i]: %ld end: %p tmp: %p",
6162 i, v, end, tmp);
6163 if (end == tmp)
6164 break;
6165
6166 htcaps->supported_mcs_set[i] = v;
6167 tmp = end;
6168 } else {
6169 wpa_msg(wpa_s, MSG_ERROR,
6170 "Failed to parse ht-mcs: %s, error: %s\n",
6171 ht_mcs, strerror(errno));
6172 return -1;
6173 }
6174 }
6175
6176 /*
6177 * If we were able to parse any values, then set mask for the MCS set.
6178 */
6179 if (i) {
6180 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
6181 IEEE80211_HT_MCS_MASK_LEN - 1);
6182 /* skip the 3 reserved bits */
6183 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
6184 0x1f;
6185 }
6186
6187 return 0;
6188}
6189
6190
6191static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
6192 struct ieee80211_ht_capabilities *htcaps,
6193 struct ieee80211_ht_capabilities *htcaps_mask,
6194 int disabled)
6195{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006196 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006197
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006198 if (disabled == -1)
6199 return 0;
6200
Hai Shalom74f70d42019-02-11 14:42:39 -08006201 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
6202
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006203 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
6204 htcaps_mask->ht_capabilities_info |= msk;
6205 if (disabled)
6206 htcaps->ht_capabilities_info &= msk;
6207 else
6208 htcaps->ht_capabilities_info |= msk;
6209
6210 return 0;
6211}
6212
6213
6214static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
6215 struct ieee80211_ht_capabilities *htcaps,
6216 struct ieee80211_ht_capabilities *htcaps_mask,
6217 int factor)
6218{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006219 if (factor == -1)
6220 return 0;
6221
Hai Shalom74f70d42019-02-11 14:42:39 -08006222 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
6223
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006224 if (factor < 0 || factor > 3) {
6225 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
6226 "Must be 0-3 or -1", factor);
6227 return -EINVAL;
6228 }
6229
6230 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
6231 htcaps->a_mpdu_params &= ~0x3;
6232 htcaps->a_mpdu_params |= factor & 0x3;
6233
6234 return 0;
6235}
6236
6237
6238static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
6239 struct ieee80211_ht_capabilities *htcaps,
6240 struct ieee80211_ht_capabilities *htcaps_mask,
6241 int density)
6242{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006243 if (density == -1)
6244 return 0;
6245
Hai Shalom74f70d42019-02-11 14:42:39 -08006246 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
6247
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006248 if (density < 0 || density > 7) {
6249 wpa_msg(wpa_s, MSG_ERROR,
6250 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6251 density);
6252 return -EINVAL;
6253 }
6254
6255 htcaps_mask->a_mpdu_params |= 0x1C;
6256 htcaps->a_mpdu_params &= ~(0x1C);
6257 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6258
6259 return 0;
6260}
6261
6262
6263static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6264 struct ieee80211_ht_capabilities *htcaps,
6265 struct ieee80211_ht_capabilities *htcaps_mask,
6266 int disabled)
6267{
Hai Shalom74f70d42019-02-11 14:42:39 -08006268 if (disabled)
6269 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006270
Paul Stewart092955c2017-02-06 09:13:09 -08006271 set_disable_ht40(htcaps, disabled);
6272 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006273
6274 return 0;
6275}
6276
6277
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006278static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6279 struct ieee80211_ht_capabilities *htcaps,
6280 struct ieee80211_ht_capabilities *htcaps_mask,
6281 int disabled)
6282{
6283 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006284 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6285 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006286
Hai Shalom74f70d42019-02-11 14:42:39 -08006287 if (disabled)
6288 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006289
6290 if (disabled)
6291 htcaps->ht_capabilities_info &= ~msk;
6292 else
6293 htcaps->ht_capabilities_info |= msk;
6294
6295 htcaps_mask->ht_capabilities_info |= msk;
6296
6297 return 0;
6298}
6299
6300
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006301static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6302 struct ieee80211_ht_capabilities *htcaps,
6303 struct ieee80211_ht_capabilities *htcaps_mask,
6304 int disabled)
6305{
6306 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006307 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006308
Hai Shalom74f70d42019-02-11 14:42:39 -08006309 if (disabled)
6310 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006311
6312 if (disabled)
6313 htcaps->ht_capabilities_info &= ~msk;
6314 else
6315 htcaps->ht_capabilities_info |= msk;
6316
6317 htcaps_mask->ht_capabilities_info |= msk;
6318
6319 return 0;
6320}
6321
6322
Hai Shalom74f70d42019-02-11 14:42:39 -08006323static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6324 struct ieee80211_ht_capabilities *htcaps,
6325 struct ieee80211_ht_capabilities *htcaps_mask,
6326 int tx_stbc)
6327{
6328 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6329
6330 if (tx_stbc == -1)
6331 return 0;
6332
6333 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6334
6335 if (tx_stbc < 0 || tx_stbc > 1) {
6336 wpa_msg(wpa_s, MSG_ERROR,
6337 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6338 return -EINVAL;
6339 }
6340
6341 htcaps_mask->ht_capabilities_info |= msk;
6342 htcaps->ht_capabilities_info &= ~msk;
6343 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6344
6345 return 0;
6346}
6347
6348
6349static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6350 struct ieee80211_ht_capabilities *htcaps,
6351 struct ieee80211_ht_capabilities *htcaps_mask,
6352 int rx_stbc)
6353{
6354 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6355
6356 if (rx_stbc == -1)
6357 return 0;
6358
6359 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6360
6361 if (rx_stbc < 0 || rx_stbc > 3) {
6362 wpa_msg(wpa_s, MSG_ERROR,
6363 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6364 return -EINVAL;
6365 }
6366
6367 htcaps_mask->ht_capabilities_info |= msk;
6368 htcaps->ht_capabilities_info &= ~msk;
6369 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6370
6371 return 0;
6372}
6373
6374
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006375void wpa_supplicant_apply_ht_overrides(
6376 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6377 struct wpa_driver_associate_params *params)
6378{
6379 struct ieee80211_ht_capabilities *htcaps;
6380 struct ieee80211_ht_capabilities *htcaps_mask;
6381
6382 if (!ssid)
6383 return;
6384
6385 params->disable_ht = ssid->disable_ht;
6386 if (!params->htcaps || !params->htcaps_mask)
6387 return;
6388
6389 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6390 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6391 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6392 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6393 ssid->disable_max_amsdu);
6394 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6395 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6396 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006397 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006398 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006399 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6400 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006401
6402 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006403 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006404 htcaps->ht_capabilities_info |= bit;
6405 htcaps_mask->ht_capabilities_info |= bit;
6406 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006407}
6408
6409#endif /* CONFIG_HT_OVERRIDES */
6410
6411
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006412#ifdef CONFIG_VHT_OVERRIDES
6413void wpa_supplicant_apply_vht_overrides(
6414 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6415 struct wpa_driver_associate_params *params)
6416{
6417 struct ieee80211_vht_capabilities *vhtcaps;
6418 struct ieee80211_vht_capabilities *vhtcaps_mask;
6419
6420 if (!ssid)
6421 return;
6422
6423 params->disable_vht = ssid->disable_vht;
6424
6425 vhtcaps = (void *) params->vhtcaps;
6426 vhtcaps_mask = (void *) params->vhtcaps_mask;
6427
6428 if (!vhtcaps || !vhtcaps_mask)
6429 return;
6430
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006431 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6432 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006433
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006434#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006435 if (ssid->disable_sgi) {
6436 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6437 VHT_CAP_SHORT_GI_160);
6438 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6439 VHT_CAP_SHORT_GI_160);
6440 wpa_msg(wpa_s, MSG_DEBUG,
6441 "disable-sgi override specified, vht-caps: 0x%x",
6442 vhtcaps->vht_capabilities_info);
6443 }
6444
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006445 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006446 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6447 int max_ampdu;
6448
6449 max_ampdu = (ssid->vht_capa &
6450 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6451 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006452
6453 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6454 wpa_set_ampdu_factor(wpa_s,
6455 (void *) params->htcaps,
6456 (void *) params->htcaps_mask,
6457 max_ampdu);
6458 }
6459#endif /* CONFIG_HT_OVERRIDES */
6460
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006461#define OVERRIDE_MCS(i) \
6462 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6463 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006464 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006465 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006466 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6467 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006468 } \
6469 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6470 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006471 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006472 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006473 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6474 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006475 }
6476
6477 OVERRIDE_MCS(1);
6478 OVERRIDE_MCS(2);
6479 OVERRIDE_MCS(3);
6480 OVERRIDE_MCS(4);
6481 OVERRIDE_MCS(5);
6482 OVERRIDE_MCS(6);
6483 OVERRIDE_MCS(7);
6484 OVERRIDE_MCS(8);
6485}
6486#endif /* CONFIG_VHT_OVERRIDES */
6487
6488
Hai Shalomfdcde762020-04-02 11:19:20 -07006489#ifdef CONFIG_HE_OVERRIDES
6490void wpa_supplicant_apply_he_overrides(
6491 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6492 struct wpa_driver_associate_params *params)
6493{
6494 if (!ssid)
6495 return;
6496
6497 params->disable_he = ssid->disable_he;
6498}
6499#endif /* CONFIG_HE_OVERRIDES */
6500
6501
Sunil Ravi77d572f2023-01-17 23:58:31 +00006502void wpa_supplicant_apply_eht_overrides(
6503 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6504 struct wpa_driver_associate_params *params)
6505{
6506 if (!ssid)
6507 return;
6508
6509 params->disable_eht = ssid->disable_eht;
6510}
6511
6512
Dmitry Shmidt04949592012-07-19 12:16:46 -07006513static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6514{
6515#ifdef PCSC_FUNCS
6516 size_t len;
6517
6518 if (!wpa_s->conf->pcsc_reader)
6519 return 0;
6520
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006521 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006522 if (!wpa_s->scard)
6523 return 1;
6524
6525 if (wpa_s->conf->pcsc_pin &&
6526 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6527 scard_deinit(wpa_s->scard);
6528 wpa_s->scard = NULL;
6529 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6530 return -1;
6531 }
6532
6533 len = sizeof(wpa_s->imsi) - 1;
6534 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6535 scard_deinit(wpa_s->scard);
6536 wpa_s->scard = NULL;
6537 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6538 return -1;
6539 }
6540 wpa_s->imsi[len] = '\0';
6541
6542 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6543
6544 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6545 wpa_s->imsi, wpa_s->mnc_len);
6546
6547 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6548 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6549#endif /* PCSC_FUNCS */
6550
6551 return 0;
6552}
6553
6554
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006555int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6556{
6557 char *val, *pos;
6558
6559 ext_password_deinit(wpa_s->ext_pw);
6560 wpa_s->ext_pw = NULL;
6561 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6562
6563 if (!wpa_s->conf->ext_password_backend)
6564 return 0;
6565
6566 val = os_strdup(wpa_s->conf->ext_password_backend);
6567 if (val == NULL)
6568 return -1;
6569 pos = os_strchr(val, ':');
6570 if (pos)
6571 *pos++ = '\0';
6572
6573 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6574
6575 wpa_s->ext_pw = ext_password_init(val, pos);
6576 os_free(val);
6577 if (wpa_s->ext_pw == NULL) {
6578 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6579 return -1;
6580 }
6581 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6582
6583 return 0;
6584}
6585
6586
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006587#ifdef CONFIG_FST
6588
6589static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6590{
6591 struct wpa_supplicant *wpa_s = ctx;
6592
6593 return (is_zero_ether_addr(wpa_s->bssid) ||
6594 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6595}
6596
6597
6598static void wpas_fst_get_channel_info_cb(void *ctx,
6599 enum hostapd_hw_mode *hw_mode,
6600 u8 *channel)
6601{
6602 struct wpa_supplicant *wpa_s = ctx;
6603
6604 if (wpa_s->current_bss) {
6605 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6606 channel);
6607 } else if (wpa_s->hw.num_modes) {
6608 *hw_mode = wpa_s->hw.modes[0].mode;
6609 } else {
6610 WPA_ASSERT(0);
6611 *hw_mode = 0;
6612 }
6613}
6614
6615
6616static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6617{
6618 struct wpa_supplicant *wpa_s = ctx;
6619
6620 *modes = wpa_s->hw.modes;
6621 return wpa_s->hw.num_modes;
6622}
6623
6624
6625static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6626{
6627 struct wpa_supplicant *wpa_s = ctx;
6628
6629 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6630 wpa_s->fst_ies = fst_ies;
6631}
6632
6633
6634static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6635{
6636 struct wpa_supplicant *wpa_s = ctx;
6637
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006638 if (!ether_addr_equal(wpa_s->bssid, da)) {
Paul Stewart092955c2017-02-06 09:13:09 -08006639 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6640 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6641 return -1;
6642 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006643 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006644 wpa_s->own_addr, wpa_s->bssid,
6645 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006646 0);
6647}
6648
6649
6650static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6651{
6652 struct wpa_supplicant *wpa_s = ctx;
6653
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006654 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006655 return wpa_s->received_mb_ies;
6656}
6657
6658
6659static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6660 const u8 *buf, size_t size)
6661{
6662 struct wpa_supplicant *wpa_s = ctx;
6663 struct mb_ies_info info;
6664
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006665 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006666
6667 if (!mb_ies_info_by_ies(&info, buf, size)) {
6668 wpabuf_free(wpa_s->received_mb_ies);
6669 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6670 }
6671}
6672
6673
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006674static const u8 * wpas_fst_get_peer_first(void *ctx,
6675 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006676 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006677{
6678 struct wpa_supplicant *wpa_s = ctx;
6679
6680 *get_ctx = NULL;
6681 if (!is_zero_ether_addr(wpa_s->bssid))
6682 return (wpa_s->received_mb_ies || !mb_only) ?
6683 wpa_s->bssid : NULL;
6684 return NULL;
6685}
6686
6687
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006688static const u8 * wpas_fst_get_peer_next(void *ctx,
6689 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006690 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006691{
6692 return NULL;
6693}
6694
6695void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6696 struct fst_wpa_obj *iface_obj)
6697{
Sunil8cd6f4d2022-06-28 18:40:46 +00006698 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006699 iface_obj->ctx = wpa_s;
6700 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6701 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6702 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6703 iface_obj->set_ies = wpas_fst_set_ies_cb;
6704 iface_obj->send_action = wpas_fst_send_action_cb;
6705 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6706 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6707 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6708 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6709}
6710#endif /* CONFIG_FST */
6711
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006712static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006713 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006714{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006715 struct wowlan_triggers *triggers;
6716 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006717
6718 if (!wpa_s->conf->wowlan_triggers)
6719 return 0;
6720
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006721 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6722 if (triggers) {
6723 ret = wpa_drv_wowlan(wpa_s, triggers);
6724 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006725 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006726 return ret;
6727}
6728
6729
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006730enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006731{
6732 if (freq < 3000)
6733 return BAND_2_4_GHZ;
6734 if (freq > 50000)
6735 return BAND_60_GHZ;
6736 return BAND_5_GHZ;
6737}
6738
6739
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006740unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006741{
6742 int i;
6743 unsigned int band = 0;
6744
6745 if (freqs) {
6746 /* freqs are specified for the radio work */
6747 for (i = 0; freqs[i]; i++)
6748 band |= wpas_freq_to_band(freqs[i]);
6749 } else {
6750 /*
6751 * freqs are not specified, implies all
6752 * the supported freqs by HW
6753 */
6754 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6755 if (wpa_s->hw.modes[i].num_channels != 0) {
6756 if (wpa_s->hw.modes[i].mode ==
6757 HOSTAPD_MODE_IEEE80211B ||
6758 wpa_s->hw.modes[i].mode ==
6759 HOSTAPD_MODE_IEEE80211G)
6760 band |= BAND_2_4_GHZ;
6761 else if (wpa_s->hw.modes[i].mode ==
6762 HOSTAPD_MODE_IEEE80211A)
6763 band |= BAND_5_GHZ;
6764 else if (wpa_s->hw.modes[i].mode ==
6765 HOSTAPD_MODE_IEEE80211AD)
6766 band |= BAND_60_GHZ;
6767 else if (wpa_s->hw.modes[i].mode ==
6768 HOSTAPD_MODE_IEEE80211ANY)
6769 band = BAND_2_4_GHZ | BAND_5_GHZ |
6770 BAND_60_GHZ;
6771 }
6772 }
6773 }
6774
6775 return band;
6776}
6777
6778
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006779static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6780 const char *rn)
6781{
6782 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6783 struct wpa_radio *radio;
6784
6785 while (rn && iface) {
6786 radio = iface->radio;
6787 if (radio && os_strcmp(rn, radio->name) == 0) {
6788 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6789 wpa_s->ifname, rn);
6790 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6791 return radio;
6792 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006793
6794 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006795 }
6796
6797 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6798 wpa_s->ifname, rn ? rn : "N/A");
6799 radio = os_zalloc(sizeof(*radio));
6800 if (radio == NULL)
6801 return NULL;
6802
6803 if (rn)
6804 os_strlcpy(radio->name, rn, sizeof(radio->name));
6805 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006806 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006807 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6808
6809 return radio;
6810}
6811
6812
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006813static void radio_work_free(struct wpa_radio_work *work)
6814{
6815 if (work->wpa_s->scan_work == work) {
6816 /* This should not really happen. */
6817 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6818 work->type, work, work->started);
6819 work->wpa_s->scan_work = NULL;
6820 }
6821
6822#ifdef CONFIG_P2P
6823 if (work->wpa_s->p2p_scan_work == work) {
6824 /* This should not really happen. */
6825 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6826 work->type, work, work->started);
6827 work->wpa_s->p2p_scan_work = NULL;
6828 }
6829#endif /* CONFIG_P2P */
6830
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006831 if (work->started) {
6832 work->wpa_s->radio->num_active_works--;
6833 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006834 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006835 work->type, work,
6836 work->wpa_s->radio->num_active_works);
6837 }
6838
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006839 dl_list_del(&work->list);
6840 os_free(work);
6841}
6842
6843
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006844static int radio_work_is_connect(struct wpa_radio_work *work)
6845{
6846 return os_strcmp(work->type, "sme-connect") == 0 ||
6847 os_strcmp(work->type, "connect") == 0;
6848}
6849
6850
6851static int radio_work_is_scan(struct wpa_radio_work *work)
6852{
6853 return os_strcmp(work->type, "scan") == 0 ||
6854 os_strcmp(work->type, "p2p-scan") == 0;
6855}
6856
6857
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006858static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6859{
6860 struct wpa_radio_work *active_work = NULL;
6861 struct wpa_radio_work *tmp;
6862
6863 /* Get the active work to know the type and band. */
6864 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6865 if (tmp->started) {
6866 active_work = tmp;
6867 break;
6868 }
6869 }
6870
6871 if (!active_work) {
6872 /* No active work, start one */
6873 radio->num_active_works = 0;
6874 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6875 list) {
6876 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006877 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006878 (((struct wpa_driver_scan_params *)
6879 tmp->ctx)->only_new_results ||
6880 tmp->wpa_s->clear_driver_scan_cache))
6881 continue;
6882 return tmp;
6883 }
6884 return NULL;
6885 }
6886
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006887 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006888 /*
6889 * If the active work is either connect or sme-connect,
6890 * do not parallelize them with other radio works.
6891 */
6892 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6893 "Do not parallelize radio work with %s",
6894 active_work->type);
6895 return NULL;
6896 }
6897
6898 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6899 if (tmp->started)
6900 continue;
6901
6902 /*
6903 * If connect or sme-connect are enqueued, parallelize only
6904 * those operations ahead of them in the queue.
6905 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006906 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006907 break;
6908
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006909 /* Serialize parallel scan and p2p_scan operations on the same
6910 * interface since the driver_nl80211 mechanism for tracking
6911 * scan cookies does not yet have support for this. */
6912 if (active_work->wpa_s == tmp->wpa_s &&
6913 radio_work_is_scan(active_work) &&
6914 radio_work_is_scan(tmp)) {
6915 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6916 "Do not start work '%s' when another work '%s' is already scheduled",
6917 tmp->type, active_work->type);
6918 continue;
6919 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006920 /*
6921 * Check that the radio works are distinct and
6922 * on different bands.
6923 */
6924 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6925 (active_work->bands != tmp->bands)) {
6926 /*
6927 * If a scan has to be scheduled through nl80211 scan
6928 * interface and if an external scan is already running,
6929 * do not schedule the scan since it is likely to get
6930 * rejected by kernel.
6931 */
6932 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006933 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006934 (((struct wpa_driver_scan_params *)
6935 tmp->ctx)->only_new_results ||
6936 tmp->wpa_s->clear_driver_scan_cache))
6937 continue;
6938
6939 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6940 "active_work:%s new_work:%s",
6941 active_work->type, tmp->type);
6942 return tmp;
6943 }
6944 }
6945
6946 /* Did not find a radio work to schedule in parallel. */
6947 return NULL;
6948}
6949
6950
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006951static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6952{
6953 struct wpa_radio *radio = eloop_ctx;
6954 struct wpa_radio_work *work;
6955 struct os_reltime now, diff;
6956 struct wpa_supplicant *wpa_s;
6957
6958 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006959 if (work == NULL) {
6960 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006961 return;
6962 }
6963
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006964 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6965 radio_list);
6966
6967 if (!(wpa_s &&
6968 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6969 if (work->started)
6970 return; /* already started and still in progress */
6971
Hai Shalom60840252021-02-19 19:02:11 -08006972 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006973 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6974 return;
6975 }
6976 } else {
6977 work = NULL;
6978 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6979 /* get the work to schedule next */
6980 work = radio_work_get_next_work(radio);
6981 }
6982 if (!work)
6983 return;
6984 }
6985
6986 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006987 os_get_reltime(&now);
6988 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006989 wpa_dbg(wpa_s, MSG_DEBUG,
6990 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006991 work->type, work, diff.sec, diff.usec);
6992 work->started = 1;
6993 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006994 radio->num_active_works++;
6995
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006996 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006997
6998 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6999 radio->num_active_works < MAX_ACTIVE_WORKS)
7000 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007001}
7002
7003
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007004/*
7005 * This function removes both started and pending radio works running on
7006 * the provided interface's radio.
7007 * Prior to the removal of the radio work, its callback (cb) is called with
7008 * deinit set to be 1. Each work's callback is responsible for clearing its
7009 * internal data and restoring to a correct state.
7010 * @wpa_s: wpa_supplicant data
7011 * @type: type of works to be removed
7012 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
7013 * this interface's works.
7014 */
7015void radio_remove_works(struct wpa_supplicant *wpa_s,
7016 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007017{
7018 struct wpa_radio_work *work, *tmp;
7019 struct wpa_radio *radio = wpa_s->radio;
7020
7021 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
7022 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007023 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007024 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007025
7026 /* skip other ifaces' works */
7027 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007028 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007029
7030 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
7031 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007032 work->cb(work, 1);
7033 radio_work_free(work);
7034 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007035
7036 /* in case we removed the started work */
7037 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007038}
7039
7040
Roshan Pius3a1667e2018-07-03 15:17:14 -07007041void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
7042{
7043 struct wpa_radio_work *work;
7044 struct wpa_radio *radio = wpa_s->radio;
7045
7046 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7047 if (work->ctx != ctx)
7048 continue;
7049 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
7050 work->type, work, work->started ? " (started)" : "");
7051 radio_work_free(work);
7052 break;
7053 }
7054}
7055
7056
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007057static void radio_remove_interface(struct wpa_supplicant *wpa_s)
7058{
7059 struct wpa_radio *radio = wpa_s->radio;
7060
7061 if (!radio)
7062 return;
7063
7064 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
7065 wpa_s->ifname, radio->name);
7066 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007067 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08007068 /* If the interface that triggered the external scan was removed, the
7069 * external scan is no longer running. */
7070 if (wpa_s == radio->external_scan_req_interface)
7071 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007072 wpa_s->radio = NULL;
7073 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007074 return; /* Interfaces remain for this radio */
7075
7076 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007077 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007078 os_free(radio);
7079}
7080
7081
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007082void radio_work_check_next(struct wpa_supplicant *wpa_s)
7083{
7084 struct wpa_radio *radio = wpa_s->radio;
7085
7086 if (dl_list_empty(&radio->work))
7087 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007088 if (wpa_s->ext_work_in_progress) {
7089 wpa_printf(MSG_DEBUG,
7090 "External radio work in progress - delay start of pending item");
7091 return;
7092 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007093 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
7094 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
7095}
7096
7097
7098/**
7099 * radio_add_work - Add a radio work item
7100 * @wpa_s: Pointer to wpa_supplicant data
7101 * @freq: Frequency of the offchannel operation in MHz or 0
7102 * @type: Unique identifier for each type of work
7103 * @next: Force as the next work to be executed
7104 * @cb: Callback function for indicating when radio is available
7105 * @ctx: Context pointer for the work (work->ctx in cb())
7106 * Returns: 0 on success, -1 on failure
7107 *
7108 * This function is used to request time for an operation that requires
7109 * exclusive radio control. Once the radio is available, the registered callback
7110 * function will be called. radio_work_done() must be called once the exclusive
7111 * radio operation has been completed, so that the radio is freed for other
7112 * operations. The special case of deinit=1 is used to free the context data
7113 * during interface removal. That does not allow the callback function to start
7114 * the radio operation, i.e., it must free any resources allocated for the radio
7115 * work and return.
7116 *
7117 * The @freq parameter can be used to indicate a single channel on which the
7118 * offchannel operation will occur. This may allow multiple radio work
7119 * operations to be performed in parallel if they apply for the same channel.
7120 * Setting this to 0 indicates that the work item may use multiple channels or
7121 * requires exclusive control of the radio.
7122 */
7123int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
7124 const char *type, int next,
7125 void (*cb)(struct wpa_radio_work *work, int deinit),
7126 void *ctx)
7127{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007128 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007129 struct wpa_radio_work *work;
7130 int was_empty;
7131
7132 work = os_zalloc(sizeof(*work));
7133 if (work == NULL)
7134 return -1;
7135 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
7136 os_get_reltime(&work->time);
7137 work->freq = freq;
7138 work->type = type;
7139 work->wpa_s = wpa_s;
7140 work->cb = cb;
7141 work->ctx = ctx;
7142
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007143 if (freq)
7144 work->bands = wpas_freq_to_band(freq);
7145 else if (os_strcmp(type, "scan") == 0 ||
7146 os_strcmp(type, "p2p-scan") == 0)
7147 work->bands = wpas_get_bands(wpa_s,
7148 ((struct wpa_driver_scan_params *)
7149 ctx)->freqs);
7150 else
7151 work->bands = wpas_get_bands(wpa_s, NULL);
7152
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007153 was_empty = dl_list_empty(&wpa_s->radio->work);
7154 if (next)
7155 dl_list_add(&wpa_s->radio->work, &work->list);
7156 else
7157 dl_list_add_tail(&wpa_s->radio->work, &work->list);
7158 if (was_empty) {
7159 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
7160 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007161 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
7162 && radio->num_active_works < MAX_ACTIVE_WORKS) {
7163 wpa_dbg(wpa_s, MSG_DEBUG,
7164 "Try to schedule a radio work (num_active_works=%u)",
7165 radio->num_active_works);
7166 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007167 }
7168
7169 return 0;
7170}
7171
7172
7173/**
7174 * radio_work_done - Indicate that a radio work item has been completed
7175 * @work: Completed work
7176 *
7177 * This function is called once the callback function registered with
7178 * radio_add_work() has completed its work.
7179 */
7180void radio_work_done(struct wpa_radio_work *work)
7181{
7182 struct wpa_supplicant *wpa_s = work->wpa_s;
7183 struct os_reltime now, diff;
7184 unsigned int started = work->started;
7185
7186 os_get_reltime(&now);
7187 os_reltime_sub(&now, &work->time, &diff);
7188 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
7189 work->type, work, started ? "done" : "canceled",
7190 diff.sec, diff.usec);
7191 radio_work_free(work);
7192 if (started)
7193 radio_work_check_next(wpa_s);
7194}
7195
7196
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007197struct wpa_radio_work *
7198radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007199{
7200 struct wpa_radio_work *work;
7201 struct wpa_radio *radio = wpa_s->radio;
7202
7203 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7204 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007205 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007206 }
7207
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007208 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007209}
7210
7211
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007212static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007213 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007214{
7215 const char *ifname, *driver, *rn;
7216
7217 driver = iface->driver;
7218next_driver:
7219 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
7220 return -1;
7221
7222 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
7223 if (wpa_s->drv_priv == NULL) {
7224 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07007225 int level = MSG_ERROR;
7226
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007227 pos = driver ? os_strchr(driver, ',') : NULL;
7228 if (pos) {
7229 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
7230 "driver interface - try next driver wrapper");
7231 driver = pos + 1;
7232 goto next_driver;
7233 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007234
7235#ifdef CONFIG_MATCH_IFACE
7236 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
7237 level = MSG_DEBUG;
7238#endif /* CONFIG_MATCH_IFACE */
7239 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007240 return -1;
7241 }
7242 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
7243 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
7244 "driver_param '%s'", wpa_s->conf->driver_param);
7245 return -1;
7246 }
7247
7248 ifname = wpa_drv_get_ifname(wpa_s);
7249 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7250 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7251 "interface name with '%s'", ifname);
7252 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7253 }
7254
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007255 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007256 if (rn && rn[0] == '\0')
7257 rn = NULL;
7258
7259 wpa_s->radio = radio_add_interface(wpa_s, rn);
7260 if (wpa_s->radio == NULL)
7261 return -1;
7262
7263 return 0;
7264}
7265
7266
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007267#ifdef CONFIG_GAS_SERVER
7268
7269static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7270 unsigned int freq, const u8 *dst,
7271 const u8 *src, const u8 *bssid,
7272 const u8 *data, size_t data_len,
7273 enum offchannel_send_action_result result)
7274{
7275 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7276 " result=%s",
7277 freq, MAC2STR(dst),
7278 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7279 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7280 "FAILED"));
7281 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7282 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7283}
7284
7285
7286static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7287 struct wpabuf *buf, unsigned int wait_time)
7288{
7289 struct wpa_supplicant *wpa_s = ctx;
7290 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7291
7292 if (wait_time > wpa_s->max_remain_on_chan)
7293 wait_time = wpa_s->max_remain_on_chan;
7294
7295 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7296 wpabuf_head(buf), wpabuf_len(buf),
7297 wait_time, wpas_gas_server_tx_status, 0);
7298}
7299
7300#endif /* CONFIG_GAS_SERVER */
7301
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007302static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007303 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007304{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007305 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007306 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007307 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007308
7309 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7310 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7311 iface->confname ? iface->confname : "N/A",
7312 iface->driver ? iface->driver : "default",
7313 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7314 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7315
7316 if (iface->confname) {
7317#ifdef CONFIG_BACKEND_FILE
7318 wpa_s->confname = os_rel2abs_path(iface->confname);
7319 if (wpa_s->confname == NULL) {
7320 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7321 "for configuration file '%s'.",
7322 iface->confname);
7323 return -1;
7324 }
7325 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7326 iface->confname, wpa_s->confname);
7327#else /* CONFIG_BACKEND_FILE */
7328 wpa_s->confname = os_strdup(iface->confname);
7329#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007330 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007331 if (wpa_s->conf == NULL) {
7332 wpa_printf(MSG_ERROR, "Failed to read or parse "
7333 "configuration '%s'.", wpa_s->confname);
7334 return -1;
7335 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007336 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007337 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007338 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007339 wpa_printf(MSG_ERROR,
7340 "Failed to read or parse configuration '%s'.",
7341 wpa_s->confanother);
7342 return -1;
7343 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007344
7345 /*
7346 * Override ctrl_interface and driver_param if set on command
7347 * line.
7348 */
7349 if (iface->ctrl_interface) {
7350 os_free(wpa_s->conf->ctrl_interface);
7351 wpa_s->conf->ctrl_interface =
7352 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007353 if (!wpa_s->conf->ctrl_interface) {
7354 wpa_printf(MSG_ERROR,
7355 "Failed to duplicate control interface '%s'.",
7356 iface->ctrl_interface);
7357 return -1;
7358 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007359 }
7360
7361 if (iface->driver_param) {
7362 os_free(wpa_s->conf->driver_param);
7363 wpa_s->conf->driver_param =
7364 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007365 if (!wpa_s->conf->driver_param) {
7366 wpa_printf(MSG_ERROR,
7367 "Failed to duplicate driver param '%s'.",
7368 iface->driver_param);
7369 return -1;
7370 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007371 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007372
7373 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7374 os_free(wpa_s->conf->ctrl_interface);
7375 wpa_s->conf->ctrl_interface = NULL;
7376 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007377 } else
7378 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7379 iface->driver_param);
7380
7381 if (wpa_s->conf == NULL) {
7382 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7383 return -1;
7384 }
7385
7386 if (iface->ifname == NULL) {
7387 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7388 return -1;
7389 }
7390 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7391 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7392 iface->ifname);
7393 return -1;
7394 }
7395 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007396#ifdef CONFIG_MATCH_IFACE
7397 wpa_s->matched = iface->matched;
7398#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007399
7400 if (iface->bridge_ifname) {
7401 if (os_strlen(iface->bridge_ifname) >=
7402 sizeof(wpa_s->bridge_ifname)) {
7403 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7404 "name '%s'.", iface->bridge_ifname);
7405 return -1;
7406 }
7407 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7408 sizeof(wpa_s->bridge_ifname));
7409 }
7410
7411 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007412 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7413 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007414
7415 /* Initialize driver interface and register driver event handler before
7416 * L2 receive handler so that association events are processed before
7417 * EAPOL-Key packets if both become available for the same select()
7418 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007419 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007420 return -1;
7421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007422 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7423 return -1;
7424
7425 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7426 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7427 NULL);
7428 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7429
7430 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7431 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7432 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7433 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7434 "dot11RSNAConfigPMKLifetime");
7435 return -1;
7436 }
7437
7438 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7439 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7440 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7441 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7442 "dot11RSNAConfigPMKReauthThreshold");
7443 return -1;
7444 }
7445
7446 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7447 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7448 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7449 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7450 "dot11RSNAConfigSATimeout");
7451 return -1;
7452 }
7453
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007454 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
7455 wpa_s->conf->ft_prepend_pmkid);
7456
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007457 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7458 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007459 &wpa_s->hw.flags,
7460 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007461 if (wpa_s->hw.modes) {
7462 u16 i;
7463
7464 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7465 if (wpa_s->hw.modes[i].vht_capab) {
7466 wpa_s->hw_capab = CAPAB_VHT;
7467 break;
7468 }
7469
7470 if (wpa_s->hw.modes[i].ht_capab &
7471 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7472 wpa_s->hw_capab = CAPAB_HT40;
7473 else if (wpa_s->hw.modes[i].ht_capab &&
7474 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7475 wpa_s->hw_capab = CAPAB_HT;
7476 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007477 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007478 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007479
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007480 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7481 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007482 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007484 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007485 wpa_s->drv_enc = capa.enc;
Sunil Ravi7f769292024-07-23 22:21:32 +00007486 wpa_s->drv_key_mgmt = capa.key_mgmt;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007487 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007488 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007489 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007490 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007491 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007492 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7493 wpa_s->max_sched_scan_plan_interval =
7494 capa.max_sched_scan_plan_interval;
7495 wpa_s->max_sched_scan_plan_iterations =
7496 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007497 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7498 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007499 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7500 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007501 wpa_s->extended_capa = capa.extended_capa;
7502 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7503 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007504 wpa_s->num_multichan_concurrent =
7505 capa.num_multichan_concurrent;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007506#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007507 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007508#endif /* CONFIG_NO_WMM_AC */
Sunil Ravi89eba102022-09-13 21:04:37 -07007509 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007510
7511 if (capa.mac_addr_rand_scan_supported)
7512 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7513 if (wpa_s->sched_scan_supported &&
7514 capa.mac_addr_rand_sched_scan_supported)
7515 wpa_s->mac_addr_rand_supported |=
7516 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007517
7518 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7519 if (wpa_s->extended_capa &&
7520 wpa_s->extended_capa_len >= 3 &&
7521 wpa_s->extended_capa[2] & 0x40)
7522 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007523 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007524#ifdef CONFIG_PASN
7525 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7526#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007527 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7528 !!(wpa_s->drv_flags &
7529 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007530 if (wpa_s->max_remain_on_chan == 0)
7531 wpa_s->max_remain_on_chan = 1000;
7532
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007533 /*
7534 * Only take p2p_mgmt parameters when P2P Device is supported.
7535 * Doing it here as it determines whether l2_packet_init() will be done
7536 * during wpa_supplicant_driver_init().
7537 */
7538 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7539 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007540
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007541 if (wpa_s->num_multichan_concurrent == 0)
7542 wpa_s->num_multichan_concurrent = 1;
7543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007544 if (wpa_supplicant_driver_init(wpa_s) < 0)
7545 return -1;
7546
7547#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007548 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007549 return -1;
7550#endif /* CONFIG_TDLS */
7551
7552 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7553 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7554 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7555 return -1;
7556 }
7557
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007558#ifdef CONFIG_FST
7559 if (wpa_s->conf->fst_group_id) {
7560 struct fst_iface_cfg cfg;
7561 struct fst_wpa_obj iface_obj;
7562
7563 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7564 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7565 sizeof(cfg.group_id));
7566 cfg.priority = wpa_s->conf->fst_priority;
7567 cfg.llt = wpa_s->conf->fst_llt;
7568
7569 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7570 &iface_obj, &cfg);
7571 if (!wpa_s->fst) {
7572 wpa_msg(wpa_s, MSG_ERROR,
7573 "FST: Cannot attach iface %s to group %s",
7574 wpa_s->ifname, cfg.group_id);
7575 return -1;
7576 }
7577 }
7578#endif /* CONFIG_FST */
7579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007580 if (wpas_wps_init(wpa_s))
7581 return -1;
7582
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007583#ifdef CONFIG_GAS_SERVER
7584 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7585 if (!wpa_s->gas_server) {
7586 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7587 return -1;
7588 }
7589#endif /* CONFIG_GAS_SERVER */
7590
7591#ifdef CONFIG_DPP
7592 if (wpas_dpp_init(wpa_s) < 0)
7593 return -1;
7594#endif /* CONFIG_DPP */
7595
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007596#ifdef CONFIG_NAN_USD
7597 if (wpas_nan_usd_init(wpa_s) < 0)
7598 return -1;
7599#endif /* CONFIG_NAN_USD */
7600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007601 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7602 return -1;
7603 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7604
7605 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7606 if (wpa_s->ctrl_iface == NULL) {
7607 wpa_printf(MSG_ERROR,
7608 "Failed to initialize control interface '%s'.\n"
7609 "You may have another wpa_supplicant process "
7610 "already running or the file was\n"
7611 "left by an unclean termination of wpa_supplicant "
7612 "in which case you will need\n"
7613 "to manually remove this file before starting "
7614 "wpa_supplicant again.\n",
7615 wpa_s->conf->ctrl_interface);
7616 return -1;
7617 }
7618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007619 wpa_s->gas = gas_query_init(wpa_s);
7620 if (wpa_s->gas == NULL) {
7621 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7622 return -1;
7623 }
7624
Roshan Pius3a1667e2018-07-03 15:17:14 -07007625 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7626 wpa_s->p2p_mgmt) &&
7627 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007628 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7629 return -1;
7630 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007631
7632 if (wpa_bss_init(wpa_s) < 0)
7633 return -1;
7634
Paul Stewart092955c2017-02-06 09:13:09 -08007635#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7636#ifdef CONFIG_MESH
7637 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7638#endif /* CONFIG_MESH */
7639#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7640
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007641 /*
7642 * Set Wake-on-WLAN triggers, if configured.
7643 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7644 * have effect anyway when the interface is down).
7645 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007646 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007647 return -1;
7648
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007649#ifdef CONFIG_EAP_PROXY
7650{
7651 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007652 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7653 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007654 if (wpa_s->mnc_len > 0) {
7655 wpa_s->imsi[len] = '\0';
7656 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7657 wpa_s->imsi, wpa_s->mnc_len);
7658 } else {
7659 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7660 }
7661}
7662#endif /* CONFIG_EAP_PROXY */
7663
Dmitry Shmidt04949592012-07-19 12:16:46 -07007664 if (pcsc_reader_init(wpa_s) < 0)
7665 return -1;
7666
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007667 if (wpas_init_ext_pw(wpa_s) < 0)
7668 return -1;
7669
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007670#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007671 wpas_rrm_reset(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007672#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007673
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007674 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7675
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007676#ifdef CONFIG_HS20
7677 hs20_init(wpa_s);
7678#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007679#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007680 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007681 if ((wpa_s->conf->oce & OCE_STA) &&
7682 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7683 wpa_s->enable_oce = OCE_STA;
7684 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7685 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7686 /* TODO: Need to add STA-CFON support */
7687 wpa_printf(MSG_ERROR,
7688 "OCE STA-CFON feature is not yet supported");
7689 }
7690 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007691 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7692#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007693
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007694 wpa_supplicant_set_default_scan_ies(wpa_s);
7695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007696 return 0;
7697}
7698
7699
7700static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007701 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007702{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007703 struct wpa_global *global = wpa_s->global;
7704 struct wpa_supplicant *iface, *prev;
7705
Jimmy Chen0e73c002021-08-18 13:21:30 +08007706 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007707 wpas_p2p_group_remove(wpa_s, "*");
7708
7709 iface = global->ifaces;
7710 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007711 if (iface->p2pdev == wpa_s)
7712 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007713 if (iface == wpa_s || iface->parent != wpa_s) {
7714 iface = iface->next;
7715 continue;
7716 }
7717 wpa_printf(MSG_DEBUG,
7718 "Remove remaining child interface %s from parent %s",
7719 iface->ifname, wpa_s->ifname);
7720 prev = iface;
7721 iface = iface->next;
7722 wpa_supplicant_remove_iface(global, prev, terminate);
7723 }
7724
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007725 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007726 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007727 /*
7728 * Don't deauthenticate if WoWLAN is enable and not explicitly
7729 * been configured to disconnect.
7730 */
7731 if (!wpa_drv_get_wowlan(wpa_s) ||
7732 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007733 wpa_supplicant_deauthenticate(
7734 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007735
Hai Shalomfdcde762020-04-02 11:19:20 -07007736 wpa_drv_set_countermeasures(wpa_s, 0);
7737 wpa_clear_keys(wpa_s, NULL);
7738 } else {
7739 wpa_msg(wpa_s, MSG_INFO,
7740 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7741 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007742 }
7743
7744 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007745 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007746
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007747 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007748 radio_remove_interface(wpa_s);
7749
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007750#ifdef CONFIG_FST
7751 if (wpa_s->fst) {
7752 fst_detach(wpa_s->fst);
7753 wpa_s->fst = NULL;
7754 }
7755 if (wpa_s->received_mb_ies) {
7756 wpabuf_free(wpa_s->received_mb_ies);
7757 wpa_s->received_mb_ies = NULL;
7758 }
7759#endif /* CONFIG_FST */
7760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007761 if (wpa_s->drv_priv)
7762 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007763
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007764 if (notify)
7765 wpas_notify_iface_removed(wpa_s);
7766
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007767 if (terminate)
7768 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007769
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007770 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7771 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007772
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007773#ifdef CONFIG_MESH
7774 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007775 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007776 wpa_s->ifmsh = NULL;
7777 }
7778#endif /* CONFIG_MESH */
7779
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007780 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007781 wpa_config_free(wpa_s->conf);
7782 wpa_s->conf = NULL;
7783 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007784
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007785 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007786 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007787
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007788 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007789}
7790
7791
Dmitry Shmidte4663042016-04-04 10:07:49 -07007792#ifdef CONFIG_MATCH_IFACE
7793
7794/**
7795 * wpa_supplicant_match_iface - Match an interface description to a name
7796 * @global: Pointer to global data from wpa_supplicant_init()
7797 * @ifname: Name of the interface to match
7798 * Returns: Pointer to the created interface description or %NULL on failure
7799 */
7800struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7801 const char *ifname)
7802{
7803 int i;
7804 struct wpa_interface *iface, *miface;
7805
7806 for (i = 0; i < global->params.match_iface_count; i++) {
7807 miface = &global->params.match_ifaces[i];
7808 if (!miface->ifname ||
7809 fnmatch(miface->ifname, ifname, 0) == 0) {
7810 iface = os_zalloc(sizeof(*iface));
7811 if (!iface)
7812 return NULL;
7813 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007814 if (!miface->ifname)
7815 iface->matched = WPA_IFACE_MATCHED_NULL;
7816 else
7817 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007818 iface->ifname = ifname;
7819 return iface;
7820 }
7821 }
7822
7823 return NULL;
7824}
7825
7826
7827/**
7828 * wpa_supplicant_match_existing - Match existing interfaces
7829 * @global: Pointer to global data from wpa_supplicant_init()
7830 * Returns: 0 on success, -1 on failure
7831 */
7832static int wpa_supplicant_match_existing(struct wpa_global *global)
7833{
7834 struct if_nameindex *ifi, *ifp;
7835 struct wpa_supplicant *wpa_s;
7836 struct wpa_interface *iface;
7837
7838 ifp = if_nameindex();
7839 if (!ifp) {
7840 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7841 return -1;
7842 }
7843
7844 for (ifi = ifp; ifi->if_name; ifi++) {
7845 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7846 if (wpa_s)
7847 continue;
7848 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7849 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007850 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007851 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007852 }
7853 }
7854
7855 if_freenameindex(ifp);
7856 return 0;
7857}
7858
7859#endif /* CONFIG_MATCH_IFACE */
7860
7861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007862/**
7863 * wpa_supplicant_add_iface - Add a new network interface
7864 * @global: Pointer to global data from wpa_supplicant_init()
7865 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007866 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007867 * Returns: Pointer to the created interface or %NULL on failure
7868 *
7869 * This function is used to add new network interfaces for %wpa_supplicant.
7870 * This can be called before wpa_supplicant_run() to add interfaces before the
7871 * main event loop has been started. In addition, new interfaces can be added
7872 * dynamically while %wpa_supplicant is already running. This could happen,
7873 * e.g., when a hotplug network adapter is inserted.
7874 */
7875struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007876 struct wpa_interface *iface,
7877 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007878{
7879 struct wpa_supplicant *wpa_s;
7880 struct wpa_interface t_iface;
7881 struct wpa_ssid *ssid;
7882
7883 if (global == NULL || iface == NULL)
7884 return NULL;
7885
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007886 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007887 if (wpa_s == NULL)
7888 return NULL;
7889
7890 wpa_s->global = global;
7891
7892 t_iface = *iface;
7893 if (global->params.override_driver) {
7894 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7895 "('%s' -> '%s')",
7896 iface->driver, global->params.override_driver);
7897 t_iface.driver = global->params.override_driver;
7898 }
7899 if (global->params.override_ctrl_interface) {
7900 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7901 "ctrl_interface ('%s' -> '%s')",
7902 iface->ctrl_interface,
7903 global->params.override_ctrl_interface);
7904 t_iface.ctrl_interface =
7905 global->params.override_ctrl_interface;
7906 }
7907 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7908 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7909 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007910 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007911 return NULL;
7912 }
7913
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007914 /* Notify the control interfaces about new iface */
7915 if (wpas_notify_iface_added(wpa_s)) {
7916 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7917 return NULL;
7918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007919
Jimmy Chene2206be2022-07-10 10:25:21 +08007920 /* Notify the control interfaces about new networks */
7921 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7922 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007923 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007924 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7925 && os_strncmp((const char *) ssid->ssid,
7926 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7927 wpas_notify_persistent_group_added(wpa_s, ssid);
7928 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007929 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007930
7931 wpa_s->next = global->ifaces;
7932 global->ifaces = wpa_s;
7933
7934 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007935 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007936
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007937#ifdef CONFIG_P2P
7938 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007939 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007940 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007941 wpas_p2p_add_p2pdev_interface(
7942 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007943 wpa_printf(MSG_INFO,
7944 "P2P: Failed to enable P2P Device interface");
7945 /* Try to continue without. P2P will be disabled. */
7946 }
7947#endif /* CONFIG_P2P */
7948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007949 return wpa_s;
7950}
7951
7952
7953/**
7954 * wpa_supplicant_remove_iface - Remove a network interface
7955 * @global: Pointer to global data from wpa_supplicant_init()
7956 * @wpa_s: Pointer to the network interface to be removed
7957 * Returns: 0 if interface was removed, -1 if interface was not found
7958 *
7959 * This function can be used to dynamically remove network interfaces from
7960 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7961 * addition, this function is used to remove all remaining interfaces when
7962 * %wpa_supplicant is terminated.
7963 */
7964int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007965 struct wpa_supplicant *wpa_s,
7966 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007967{
7968 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007969#ifdef CONFIG_MESH
7970 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7971 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007972 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007973#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007974
7975 /* Remove interface from the global list of interfaces */
7976 prev = global->ifaces;
7977 if (prev == wpa_s) {
7978 global->ifaces = wpa_s->next;
7979 } else {
7980 while (prev && prev->next != wpa_s)
7981 prev = prev->next;
7982 if (prev == NULL)
7983 return -1;
7984 prev->next = wpa_s->next;
7985 }
7986
7987 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7988
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007989#ifdef CONFIG_MESH
7990 if (mesh_if_created) {
7991 ifname = os_strdup(wpa_s->ifname);
7992 if (ifname == NULL) {
7993 wpa_dbg(wpa_s, MSG_ERROR,
7994 "mesh: Failed to malloc ifname");
7995 return -1;
7996 }
7997 }
7998#endif /* CONFIG_MESH */
7999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008000 if (global->p2p_group_formation == wpa_s)
8001 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008002 if (global->p2p_invite_group == wpa_s)
8003 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008004 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008005
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008006#ifdef CONFIG_MESH
8007 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008008 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008009 os_free(ifname);
8010 }
8011#endif /* CONFIG_MESH */
8012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008013 return 0;
8014}
8015
8016
8017/**
8018 * wpa_supplicant_get_eap_mode - Get the current EAP mode
8019 * @wpa_s: Pointer to the network interface
8020 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
8021 */
8022const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
8023{
8024 const char *eapol_method;
8025
8026 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
8027 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
8028 return "NO-EAP";
8029 }
8030
8031 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
8032 if (eapol_method == NULL)
8033 return "UNKNOWN-EAP";
8034
8035 return eapol_method;
8036}
8037
8038
8039/**
8040 * wpa_supplicant_get_iface - Get a new network interface
8041 * @global: Pointer to global data from wpa_supplicant_init()
8042 * @ifname: Interface name
8043 * Returns: Pointer to the interface or %NULL if not found
8044 */
8045struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
8046 const char *ifname)
8047{
8048 struct wpa_supplicant *wpa_s;
8049
8050 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8051 if (os_strcmp(wpa_s->ifname, ifname) == 0)
8052 return wpa_s;
8053 }
8054 return NULL;
8055}
8056
8057
8058#ifndef CONFIG_NO_WPA_MSG
8059static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
8060{
8061 struct wpa_supplicant *wpa_s = ctx;
8062 if (wpa_s == NULL)
8063 return NULL;
8064 return wpa_s->ifname;
8065}
8066#endif /* CONFIG_NO_WPA_MSG */
8067
8068
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008069#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
8070#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
8071#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
8072
8073/* Periodic cleanup tasks */
8074static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
8075{
8076 struct wpa_global *global = eloop_ctx;
8077 struct wpa_supplicant *wpa_s;
8078
8079 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8080 wpas_periodic, global, NULL);
8081
8082#ifdef CONFIG_P2P
8083 if (global->p2p)
8084 p2p_expire_peers(global->p2p);
8085#endif /* CONFIG_P2P */
8086
8087 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8088 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
8089#ifdef CONFIG_AP
8090 ap_periodic(wpa_s);
8091#endif /* CONFIG_AP */
8092 }
8093}
8094
8095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008096/**
8097 * wpa_supplicant_init - Initialize %wpa_supplicant
8098 * @params: Parameters for %wpa_supplicant
8099 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
8100 *
8101 * This function is used to initialize %wpa_supplicant. After successful
8102 * initialization, the returned data pointer can be used to add and remove
8103 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
8104 */
8105struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
8106{
8107 struct wpa_global *global;
8108 int ret, i;
8109
8110 if (params == NULL)
8111 return NULL;
8112
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008113#ifdef CONFIG_DRIVER_NDIS
8114 {
8115 void driver_ndis_init_ops(void);
8116 driver_ndis_init_ops();
8117 }
8118#endif /* CONFIG_DRIVER_NDIS */
8119
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008120#ifndef CONFIG_NO_WPA_MSG
8121 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
8122#endif /* CONFIG_NO_WPA_MSG */
8123
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008124 if (params->wpa_debug_file_path)
8125 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07008126 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008127 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008128 if (params->wpa_debug_syslog)
8129 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008130 if (params->wpa_debug_tracing) {
8131 ret = wpa_debug_open_linux_tracing();
8132 if (ret) {
8133 wpa_printf(MSG_ERROR,
8134 "Failed to enable trace logging");
8135 return NULL;
8136 }
8137 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008138
8139 ret = eap_register_methods();
8140 if (ret) {
8141 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
8142 if (ret == -2)
8143 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
8144 "the same EAP type.");
8145 return NULL;
8146 }
8147
8148 global = os_zalloc(sizeof(*global));
8149 if (global == NULL)
8150 return NULL;
8151 dl_list_init(&global->p2p_srv_bonjour);
8152 dl_list_init(&global->p2p_srv_upnp);
8153 global->params.daemonize = params->daemonize;
8154 global->params.wait_for_monitor = params->wait_for_monitor;
8155 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008156
8157 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008158 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008159 if (!global->params.pid_file) {
8160 wpa_supplicant_deinit(global);
8161 return NULL;
8162 }
8163 }
8164
8165 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008166 global->params.ctrl_interface =
8167 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008168 if (!global->params.ctrl_interface) {
8169 wpa_supplicant_deinit(global);
8170 return NULL;
8171 }
8172 }
8173
8174 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008175 global->params.ctrl_interface_group =
8176 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008177 if (!global->params.ctrl_interface_group) {
8178 wpa_supplicant_deinit(global);
8179 return NULL;
8180 }
8181 }
8182
8183 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008184 global->params.override_driver =
8185 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008186 if (!global->params.override_driver) {
8187 wpa_supplicant_deinit(global);
8188 return NULL;
8189 }
8190 }
8191
8192 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008193 global->params.override_ctrl_interface =
8194 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008195 if (!global->params.override_ctrl_interface) {
8196 wpa_supplicant_deinit(global);
8197 return NULL;
8198 }
8199 }
8200
Dmitry Shmidte4663042016-04-04 10:07:49 -07008201#ifdef CONFIG_MATCH_IFACE
8202 global->params.match_iface_count = params->match_iface_count;
8203 if (params->match_iface_count) {
8204 global->params.match_ifaces =
8205 os_calloc(params->match_iface_count,
8206 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00008207 if (!global->params.match_ifaces) {
8208 wpa_printf(MSG_ERROR,
8209 "Failed to allocate match interfaces");
8210 wpa_supplicant_deinit(global);
8211 return NULL;
8212 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07008213 os_memcpy(global->params.match_ifaces,
8214 params->match_ifaces,
8215 params->match_iface_count *
8216 sizeof(struct wpa_interface));
8217 }
8218#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008219#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00008220 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008221 global->params.conf_p2p_dev =
8222 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008223 if (!global->params.conf_p2p_dev) {
8224 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
8225 wpa_supplicant_deinit(global);
8226 return NULL;
8227 }
8228 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008229#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008230 wpa_debug_level = global->params.wpa_debug_level =
8231 params->wpa_debug_level;
8232 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
8233 params->wpa_debug_show_keys;
8234 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
8235 params->wpa_debug_timestamp;
8236
Hai Shalomfdcde762020-04-02 11:19:20 -07008237 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008238
8239 if (eloop_init()) {
8240 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
8241 wpa_supplicant_deinit(global);
8242 return NULL;
8243 }
8244
Jouni Malinen75ecf522011-06-27 15:19:46 -07008245 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008246
8247 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
8248 if (global->ctrl_iface == NULL) {
8249 wpa_supplicant_deinit(global);
8250 return NULL;
8251 }
8252
8253 if (wpas_notify_supplicant_initialized(global)) {
8254 wpa_supplicant_deinit(global);
8255 return NULL;
8256 }
8257
8258 for (i = 0; wpa_drivers[i]; i++)
8259 global->drv_count++;
8260 if (global->drv_count == 0) {
8261 wpa_printf(MSG_ERROR, "No drivers enabled");
8262 wpa_supplicant_deinit(global);
8263 return NULL;
8264 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008265 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008266 if (global->drv_priv == NULL) {
8267 wpa_supplicant_deinit(global);
8268 return NULL;
8269 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008270
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008271#ifdef CONFIG_WIFI_DISPLAY
8272 if (wifi_display_init(global) < 0) {
8273 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8274 wpa_supplicant_deinit(global);
8275 return NULL;
8276 }
8277#endif /* CONFIG_WIFI_DISPLAY */
8278
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008279 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8280 wpas_periodic, global, NULL);
8281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008282 return global;
8283}
8284
8285
8286/**
8287 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8288 * @global: Pointer to global data from wpa_supplicant_init()
8289 * Returns: 0 after successful event loop run, -1 on failure
8290 *
8291 * This function starts the main event loop and continues running as long as
8292 * there are any remaining events. In most cases, this function is running as
8293 * long as the %wpa_supplicant process in still in use.
8294 */
8295int wpa_supplicant_run(struct wpa_global *global)
8296{
8297 struct wpa_supplicant *wpa_s;
8298
8299 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008300 (wpa_supplicant_daemon(global->params.pid_file) ||
8301 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008302 return -1;
8303
Dmitry Shmidte4663042016-04-04 10:07:49 -07008304#ifdef CONFIG_MATCH_IFACE
8305 if (wpa_supplicant_match_existing(global))
8306 return -1;
8307#endif
8308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008309 if (global->params.wait_for_monitor) {
8310 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008311 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008312 wpa_supplicant_ctrl_iface_wait(
8313 wpa_s->ctrl_iface);
8314 }
8315
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008316#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008317 // If daemonize is enabled, initialize AIDL here.
8318 if (global->params.daemonize) {
8319 global->aidl = wpas_aidl_init(global);
8320 if (!global->aidl)
8321 return -1;
8322 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008323#endif /* CONFIG_AIDL */
8324
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008325 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8326 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8327
8328 eloop_run();
8329
8330 return 0;
8331}
8332
8333
8334/**
8335 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8336 * @global: Pointer to global data from wpa_supplicant_init()
8337 *
8338 * This function is called to deinitialize %wpa_supplicant and to free all
8339 * allocated resources. Remaining network interfaces will also be removed.
8340 */
8341void wpa_supplicant_deinit(struct wpa_global *global)
8342{
8343 int i;
8344
8345 if (global == NULL)
8346 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008347
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008348 eloop_cancel_timeout(wpas_periodic, global, NULL);
8349
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008350#ifdef CONFIG_WIFI_DISPLAY
8351 wifi_display_deinit(global);
8352#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008353
8354 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008355 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008356
8357 if (global->ctrl_iface)
8358 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8359
8360 wpas_notify_supplicant_deinitialized(global);
8361
8362 eap_peer_unregister_methods();
8363#ifdef CONFIG_AP
8364 eap_server_unregister_methods();
8365#endif /* CONFIG_AP */
8366
8367 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8368 if (!global->drv_priv[i])
8369 continue;
8370 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8371 }
8372 os_free(global->drv_priv);
8373
8374 random_deinit();
8375
8376 eloop_destroy();
8377
8378 if (global->params.pid_file) {
8379 os_daemonize_terminate(global->params.pid_file);
8380 os_free(global->params.pid_file);
8381 }
8382 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008383 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008384 os_free(global->params.override_driver);
8385 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008386#ifdef CONFIG_MATCH_IFACE
8387 os_free(global->params.match_ifaces);
8388#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008389#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008390 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008391#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008392
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008393 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008394 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008395 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008397 os_free(global);
8398 wpa_debug_close_syslog();
8399 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008400 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008401}
8402
8403
8404void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8405{
8406 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8407 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8408 char country[3];
8409 country[0] = wpa_s->conf->country[0];
8410 country[1] = wpa_s->conf->country[1];
8411 country[2] = '\0';
8412 if (wpa_drv_set_country(wpa_s, country) < 0) {
8413 wpa_printf(MSG_ERROR, "Failed to set country code "
8414 "'%s'", country);
8415 }
8416 }
8417
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008418 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8419 wpas_init_ext_pw(wpa_s);
8420
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008421 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8422 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8423
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008424 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8425 struct wpa_driver_capa capa;
8426 int res = wpa_drv_get_capa(wpa_s, &capa);
8427
8428 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8429 wpa_printf(MSG_ERROR,
8430 "Failed to update wowlan_triggers to '%s'",
8431 wpa_s->conf->wowlan_triggers);
8432 }
8433
Hai Shalom81f62d82019-07-22 12:10:00 -07008434 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8435 wpa_supplicant_set_default_scan_ies(wpa_s);
8436
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008437 if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
8438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
8439 wpa_s->conf->ft_prepend_pmkid);
8440
Hai Shalom899fcc72020-10-19 14:38:18 -07008441#ifdef CONFIG_BGSCAN
8442 /*
8443 * We default to global bgscan parameters only when per-network bgscan
8444 * parameters aren't set. Only bother resetting bgscan parameters if
8445 * this is the case.
8446 */
8447 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8448 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8449 wpa_s->wpa_state == WPA_COMPLETED)
8450 wpa_supplicant_reset_bgscan(wpa_s);
8451#endif /* CONFIG_BGSCAN */
8452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008453#ifdef CONFIG_WPS
8454 wpas_wps_update_config(wpa_s);
8455#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008456 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008457 wpa_s->conf->changed_parameters = 0;
8458}
8459
8460
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008461void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008462{
8463 int i;
8464
8465 for (i = 0; i < *num_freqs; i++) {
8466 if (freqs[i] == freq)
8467 return;
8468 }
8469
8470 freqs[*num_freqs] = freq;
8471 (*num_freqs)++;
8472}
8473
8474
8475static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8476{
8477 struct wpa_bss *bss, *cbss;
8478 const int max_freqs = 10;
8479 int *freqs;
8480 int num_freqs = 0;
8481
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008482 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008483 if (freqs == NULL)
8484 return NULL;
8485
8486 cbss = wpa_s->current_bss;
8487
8488 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8489 if (bss == cbss)
8490 continue;
8491 if (bss->ssid_len == cbss->ssid_len &&
8492 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008493 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008494 add_freq(freqs, &num_freqs, bss->freq);
8495 if (num_freqs == max_freqs)
8496 break;
8497 }
8498 }
8499
8500 if (num_freqs == 0) {
8501 os_free(freqs);
8502 freqs = NULL;
8503 }
8504
8505 return freqs;
8506}
8507
8508
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008509void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
8510 const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008511{
8512 int timeout;
8513 int count;
8514 int *freqs = NULL;
8515
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008516 wpas_connect_work_done(wpa_s);
8517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008518 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008519 * Remove possible authentication timeout since the connection failed.
8520 */
8521 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8522
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008523 /*
Hai Shalom60840252021-02-19 19:02:11 -08008524 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008525 * generated based on local request to disconnect.
8526 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008527 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008528 wpa_s->own_disconnect_req = 0;
8529 wpa_dbg(wpa_s, MSG_DEBUG,
8530 "Ignore connection failure due to local request to disconnect");
8531 return;
8532 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008533 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008534 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8535 "indication since interface has been put into "
8536 "disconnected state");
8537 return;
8538 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008539 if (wpa_s->auto_reconnect_disabled) {
8540 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8541 "indication since auto connect is disabled");
8542 return;
8543 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008544
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008545 /* Also mark links as failed */
8546 while (link_bssids && *link_bssids) {
8547 wpa_bssid_ignore_add(wpa_s, *link_bssids);
8548 link_bssids++;
8549 }
8550
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008551 /*
Hai Shalom60840252021-02-19 19:02:11 -08008552 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008553 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008554 */
Hai Shalom60840252021-02-19 19:02:11 -08008555 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008556 if (count == 1 && wpa_s->current_bss) {
8557 /*
Hai Shalom60840252021-02-19 19:02:11 -08008558 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008559 * another BSS available for the same ESS, we should try that
8560 * next. Otherwise, we may as well try this one once more
8561 * before allowing other, likely worse, ESSes to be considered.
8562 */
8563 freqs = get_bss_freqs_in_ess(wpa_s);
8564 if (freqs) {
8565 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8566 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008567 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008568 /*
8569 * On the next scan, go through only the known channels
8570 * used in this ESS based on previous scans to speed up
8571 * common load balancing use case.
8572 */
8573 os_free(wpa_s->next_scan_freqs);
8574 wpa_s->next_scan_freqs = freqs;
8575 }
8576 }
8577
Hai Shalom899fcc72020-10-19 14:38:18 -07008578 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008579
Hai Shalom899fcc72020-10-19 14:38:18 -07008580 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008581 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8582 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008583 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008584 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008585 /*
8586 * Multiple consecutive connection failures mean that other APs are
8587 * either not available or have already been tried, so we can start
8588 * increasing the delay here to avoid constant scanning.
8589 */
8590 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008591 case 1:
8592 timeout = 100;
8593 break;
8594 case 2:
8595 timeout = 500;
8596 break;
8597 case 3:
8598 timeout = 1000;
8599 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008600 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008601 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008602 break;
8603 default:
8604 timeout = 10000;
8605 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008606 }
8607
Hai Shalom899fcc72020-10-19 14:38:18 -07008608 wpa_dbg(wpa_s, MSG_DEBUG,
8609 "Consecutive connection failures: %d --> request scan in %d ms",
8610 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008612 /*
8613 * TODO: if more than one possible AP is available in scan results,
8614 * could try the other ones before requesting a new scan.
8615 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008616
8617 /* speed up the connection attempt with normal scan */
8618 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008619 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8620 1000 * (timeout % 1000));
8621}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008622
8623
Hai Shalomce48b4a2018-09-05 11:41:35 -07008624#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008625
8626void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8627{
8628 struct wpa_ssid *ssid = wpa_s->current_ssid;
8629 const u8 *realm, *username, *rrk;
8630 size_t realm_len, username_len, rrk_len;
8631 u16 next_seq_num;
8632
8633 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8634 * Check for ERP keys existing to limit when this can be done since
8635 * the rejection response is not protected and such triggers should
8636 * really not allow internal state to be modified unless required to
8637 * avoid significant issues in functionality. In addition, drop
8638 * externally configure PMKSA entries even without ERP keys since it
8639 * is possible for an external component to add PMKSA entries for FILS
8640 * authentication without restoring previously generated ERP keys.
8641 *
8642 * In this case, this is needed to allow recovery from cases where the
8643 * AP or authentication server has dropped PMKSAs and ERP keys. */
8644 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8645 return;
8646
8647 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8648 &username, &username_len,
8649 &realm, &realm_len, &next_seq_num,
8650 &rrk, &rrk_len) != 0 ||
8651 !realm) {
8652 wpa_dbg(wpa_s, MSG_DEBUG,
8653 "FILS: Drop external PMKSA cache entry");
8654 wpa_sm_aborted_external_cached(wpa_s->wpa);
8655 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8656 return;
8657 }
8658
8659 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8660 wpa_sm_aborted_cached(wpa_s->wpa);
8661 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8662}
8663
8664
Hai Shalomce48b4a2018-09-05 11:41:35 -07008665void fils_connection_failure(struct wpa_supplicant *wpa_s)
8666{
8667 struct wpa_ssid *ssid = wpa_s->current_ssid;
8668 const u8 *realm, *username, *rrk;
8669 size_t realm_len, username_len, rrk_len;
8670 u16 next_seq_num;
8671
8672 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8673 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8674 &username, &username_len,
8675 &realm, &realm_len, &next_seq_num,
8676 &rrk, &rrk_len) != 0 ||
8677 !realm)
8678 return;
8679
8680 wpa_hexdump_ascii(MSG_DEBUG,
8681 "FILS: Store last connection failure realm",
8682 realm, realm_len);
8683 os_free(wpa_s->last_con_fail_realm);
8684 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8685 if (wpa_s->last_con_fail_realm) {
8686 wpa_s->last_con_fail_realm_len = realm_len;
8687 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8688 }
8689}
8690#endif /* CONFIG_FILS */
8691
8692
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008693int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8694{
8695 return wpa_s->conf->ap_scan == 2 ||
8696 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8697}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008698
Dmitry Shmidt04949592012-07-19 12:16:46 -07008699
Sunil Ravi7f769292024-07-23 22:21:32 +00008700static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
8701{
8702 return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
8703}
8704
8705
8706bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
8707{
8708 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
8709 return false;
8710
8711 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
8712 return true;
8713
8714 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
8715 wpas_driver_bss_selection(wpa_s))
8716 return wpas_driver_rsn_override(wpa_s);
8717
8718 return true;
8719}
8720
8721
Gabriel Biren57ededa2021-09-03 16:08:50 +00008722#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008723int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8724 struct wpa_ssid *ssid,
8725 const char *field,
8726 const char *value)
8727{
8728#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008729 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008730
8731 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8732 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8733 (const u8 *) value, os_strlen(value));
8734
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008735 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008736 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008737#else /* IEEE8021X_EAPOL */
8738 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8739 return -1;
8740#endif /* IEEE8021X_EAPOL */
8741}
8742
8743int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8744 struct wpa_ssid *ssid,
8745 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008746 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008747{
8748#ifdef IEEE8021X_EAPOL
8749 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008750 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008751
8752 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008753 case WPA_CTRL_REQ_EAP_IDENTITY:
8754 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008755 os_free(eap->imsi_identity);
8756 if (value == NULL)
8757 return -1;
8758 identity = os_strchr(value, ':');
8759 if (identity == NULL) {
8760 /* plain identity */
8761 eap->identity = (u8 *)os_strdup(value);
8762 eap->identity_len = os_strlen(value);
8763 } else {
8764 /* have both plain identity and encrypted identity */
8765 imsi_identity = value;
8766 *identity++ = '\0';
8767 /* plain identity */
8768 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8769 eap->imsi_identity_len = strlen(imsi_identity);
8770 /* encrypted identity */
8771 eap->identity = (u8 *)dup_binstr(identity,
8772 value_len - strlen(imsi_identity) - 1);
8773 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8774 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008775 eap->pending_req_identity = 0;
8776 if (ssid == wpa_s->current_ssid)
8777 wpa_s->reassociate = 1;
8778 break;
8779 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008780 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008781 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008782 if (!eap->password)
8783 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008784 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008785 eap->pending_req_password = 0;
8786 if (ssid == wpa_s->current_ssid)
8787 wpa_s->reassociate = 1;
8788 break;
8789 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008790 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008791 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008792 if (!eap->new_password)
8793 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008794 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008795 eap->pending_req_new_password = 0;
8796 if (ssid == wpa_s->current_ssid)
8797 wpa_s->reassociate = 1;
8798 break;
8799 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008800 str_clear_free(eap->cert.pin);
8801 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008802 if (!eap->cert.pin)
8803 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008804 eap->pending_req_pin = 0;
8805 if (ssid == wpa_s->current_ssid)
8806 wpa_s->reassociate = 1;
8807 break;
8808 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008809 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008810 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008811 if (!eap->otp)
8812 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008813 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008814 os_free(eap->pending_req_otp);
8815 eap->pending_req_otp = NULL;
8816 eap->pending_req_otp_len = 0;
8817 break;
8818 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008819 str_clear_free(eap->cert.private_key_passwd);
8820 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008821 if (!eap->cert.private_key_passwd)
8822 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008823 eap->pending_req_passphrase = 0;
8824 if (ssid == wpa_s->current_ssid)
8825 wpa_s->reassociate = 1;
8826 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008827 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008828 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008829 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008830 if (!eap->external_sim_resp)
8831 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008832 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008833 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008834 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8835 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8836 return -1;
8837 ssid->mem_only_psk = 1;
8838 if (ssid->passphrase)
8839 wpa_config_update_psk(ssid);
8840 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8841 wpa_supplicant_req_scan(wpa_s, 0, 0);
8842 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008843 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8844 if (eap->pending_ext_cert_check != PENDING_CHECK)
8845 return -1;
8846 if (os_strcmp(value, "good") == 0)
8847 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8848 else if (os_strcmp(value, "bad") == 0)
8849 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8850 else
8851 return -1;
8852 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008853 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008854 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008855 return -1;
8856 }
8857
8858 return 0;
8859#else /* IEEE8021X_EAPOL */
8860 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8861 return -1;
8862#endif /* IEEE8021X_EAPOL */
8863}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008864#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008865
8866
8867int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8868{
Hai Shalomfdcde762020-04-02 11:19:20 -07008869#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008870 int i;
8871 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008872#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008873
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008874 if (wpa_s->p2p_mgmt)
8875 return 1; /* no normal network profiles on p2p_mgmt interface */
8876
Dmitry Shmidt04949592012-07-19 12:16:46 -07008877 if (ssid == NULL)
8878 return 1;
8879
8880 if (ssid->disabled)
8881 return 1;
8882
Hai Shalomfdcde762020-04-02 11:19:20 -07008883#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008884 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008885 drv_enc = wpa_s->drv_enc;
8886 else
8887 drv_enc = (unsigned int) -1;
8888
8889 for (i = 0; i < NUM_WEP_KEYS; i++) {
8890 size_t len = ssid->wep_key_len[i];
8891 if (len == 0)
8892 continue;
8893 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8894 continue;
8895 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8896 continue;
8897 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8898 continue;
8899 return 1; /* invalid WEP key */
8900 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008901#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008902
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008903 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008904 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008905 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008906 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008907 return 1;
8908
Sunil Ravi89eba102022-09-13 21:04:37 -07008909#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008910#ifdef CRYPTO_RSA_OAEP_SHA256
8911 if (ssid->eap.imsi_privacy_cert) {
8912 struct crypto_rsa_key *key;
8913 bool failed = false;
8914
8915 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8916 if (!key)
8917 failed = true;
8918 crypto_rsa_key_free(key);
8919 if (failed) {
8920 wpa_printf(MSG_DEBUG,
8921 "Invalid imsi_privacy_cert (%s) - disable network",
8922 ssid->eap.imsi_privacy_cert);
8923 return 1;
8924 }
8925 }
8926#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008927#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008928
Dmitry Shmidt04949592012-07-19 12:16:46 -07008929 return 0;
8930}
8931
8932
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008933int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8934{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008935 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8936 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8937 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8938 /*
8939 * Driver does not support BIP -- ignore pmf=1 default
8940 * since the connection with PMF would fail and the
8941 * configuration does not require PMF to be enabled.
8942 */
8943 return NO_MGMT_FRAME_PROTECTION;
8944 }
8945
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008946 if (ssid &&
8947 (ssid->key_mgmt &
8948 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8949 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8950 /*
8951 * Do not use the default PMF value for non-RSN networks
8952 * since PMF is available only with RSN and pmf=2
8953 * configuration would otherwise prevent connections to
8954 * all open networks.
8955 */
8956 return NO_MGMT_FRAME_PROTECTION;
8957 }
8958
Sunil Ravi77d572f2023-01-17 23:58:31 +00008959#ifdef CONFIG_OCV
8960 /* Enable PMF if OCV is being enabled */
8961 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8962 ssid && ssid->ocv)
8963 return MGMT_FRAME_PROTECTION_OPTIONAL;
8964#endif /* CONFIG_OCV */
8965
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008966 return wpa_s->conf->pmf;
8967 }
8968
8969 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008970}
8971
8972
Sunil Ravi77d572f2023-01-17 23:58:31 +00008973#ifdef CONFIG_SAE
8974bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8975 struct wpa_ssid *ssid,
8976 const struct wpa_ie_data *ie)
8977{
8978 return wpa_s->conf->sae_check_mfp &&
8979 (!(ie->capabilities &
8980 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8981 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8982}
8983#endif /* CONFIG_SAE */
8984
8985
Hai Shalomc1a21442022-02-04 13:43:00 -08008986int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8987{
8988 if (wpa_s->current_ssid == NULL ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008989 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
Hai Shalomc1a21442022-02-04 13:43:00 -08008990 return 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008991 if (wpa_s->valid_links) {
8992 if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
8993 !wpas_ap_link_address(wpa_s, addr))
8994 return 0;
8995 } else {
8996 if (!ether_addr_equal(addr, wpa_s->bssid))
8997 return 0;
8998 }
Hai Shalomc1a21442022-02-04 13:43:00 -08008999 return wpa_sm_pmf_enabled(wpa_s->wpa);
9000}
9001
9002
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009003int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009004{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07009005 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009006 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07009007 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009008 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009009 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009010}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009011
9012
Sunil Ravi77d572f2023-01-17 23:58:31 +00009013void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
9014 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009015{
9016 struct wpa_ssid *ssid = wpa_s->current_ssid;
9017 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009018 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009019
9020 if (ssid == NULL) {
9021 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
9022 "SSID block");
9023 return;
9024 }
9025
9026 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
9027 return;
9028
9029 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07009030
9031#ifdef CONFIG_P2P
9032 if (ssid->p2p_group &&
9033 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
9034 /*
9035 * Skip the wait time since there is a short timeout on the
9036 * connection to a P2P group.
9037 */
9038 return;
9039 }
9040#endif /* CONFIG_P2P */
9041
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009042 if (ssid->auth_failures > 50)
9043 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009044 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009045 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009046 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009047 dur = 90;
9048 else if (ssid->auth_failures > 3)
9049 dur = 60;
9050 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009051 dur = 30;
9052 else if (ssid->auth_failures > 1)
9053 dur = 20;
9054 else
9055 dur = 10;
9056
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009057 if (ssid->auth_failures > 1 &&
9058 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
9059 dur += os_random() % (ssid->auth_failures * 10);
9060
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009061 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009062 if (now.sec + dur <= ssid->disabled_until.sec)
9063 return;
9064
9065 ssid->disabled_until.sec = now.sec + dur;
9066
9067 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009068 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009069 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009070 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009071
9072 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
9073 int msg_len = snprintf(NULL, 0, format_str,
9074 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9075 ssid->auth_failures, dur, reason) + 1;
9076 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05309077 if (!msg)
9078 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009079 snprintf(msg, msg_len, format_str,
9080 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9081 ssid->auth_failures, dur, reason);
9082 wpas_notify_ssid_temp_disabled(wpa_s, msg);
9083 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009084
9085 if (bssid)
9086 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009087}
9088
9089
9090void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
9091 struct wpa_ssid *ssid, int clear_failures)
9092{
9093 if (ssid == NULL)
9094 return;
9095
9096 if (ssid->disabled_until.sec) {
9097 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
9098 "id=%d ssid=\"%s\"",
9099 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
9100 }
9101 ssid->disabled_until.sec = 0;
9102 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009103 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009104 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009105 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
9106 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
9107 " ignored to allow a lower priority BSS, if any, to be tried next",
9108 MAC2STR(ssid->disabled_due_to));
9109 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
9110 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
9111 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009112}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009113
9114
9115int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
9116{
9117 size_t i;
9118
9119 if (wpa_s->disallow_aps_bssid == NULL)
9120 return 0;
9121
9122 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009123 if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
9124 bssid))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009125 return 1;
9126 }
9127
9128 return 0;
9129}
9130
9131
9132int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
9133 size_t ssid_len)
9134{
9135 size_t i;
9136
9137 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
9138 return 0;
9139
9140 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
9141 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
9142 if (ssid_len == s->ssid_len &&
9143 os_memcmp(ssid, s->ssid, ssid_len) == 0)
9144 return 1;
9145 }
9146
9147 return 0;
9148}
9149
9150
9151/**
9152 * wpas_request_connection - Request a new connection
9153 * @wpa_s: Pointer to the network interface
9154 *
9155 * This function is used to request a new connection to be found. It will mark
9156 * the interface to allow reassociation and request a new scan to find a
9157 * suitable network to connect to.
9158 */
9159void wpas_request_connection(struct wpa_supplicant *wpa_s)
9160{
9161 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009162 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009163 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009164 wpa_s->disconnected = 0;
9165 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07009166 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08009167
9168 if (wpa_supplicant_fast_associate(wpa_s) != 1)
9169 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009170 else
9171 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009172}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009173
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009174
Roshan Pius02242d72016-08-09 15:31:48 -07009175/**
9176 * wpas_request_disconnection - Request disconnection
9177 * @wpa_s: Pointer to the network interface
9178 *
9179 * This function is used to request disconnection from the currently connected
9180 * network. This will stop any ongoing scans and initiate deauthentication.
9181 */
9182void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
9183{
9184#ifdef CONFIG_SME
9185 wpa_s->sme.prev_bssid_set = 0;
9186#endif /* CONFIG_SME */
9187 wpa_s->reassociate = 0;
9188 wpa_s->disconnected = 1;
9189 wpa_supplicant_cancel_sched_scan(wpa_s);
9190 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009191 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07009192 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
9193 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07009194 radio_remove_works(wpa_s, "connect", 0);
9195 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08009196 wpa_s->roam_in_progress = false;
9197#ifdef CONFIG_WNM
9198 wpa_s->bss_trans_mgmt_in_progress = false;
9199#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07009200}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009201
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07009202
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009203void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
9204 struct wpa_used_freq_data *freqs_data,
9205 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009206{
9207 unsigned int i;
9208
9209 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
9210 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009211 for (i = 0; i < len; i++) {
9212 struct wpa_used_freq_data *cur = &freqs_data[i];
9213 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
9214 i, cur->freq, cur->flags);
9215 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009216}
9217
9218
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009219/*
9220 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009221 * are using the same radio as the current interface, and in addition, get
9222 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009223 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009224int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
9225 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009226 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009227{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009228 struct wpa_supplicant *ifs;
9229 u8 bssid[ETH_ALEN];
9230 int freq;
9231 unsigned int idx = 0, i;
9232
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009233 wpa_dbg(wpa_s, MSG_DEBUG,
9234 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009235 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009236
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009237 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
9238 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009239 if (idx == len)
9240 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009241
Sunil Ravi77d572f2023-01-17 23:58:31 +00009242 if (exclude_current && ifs == wpa_s)
9243 continue;
9244
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009245 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
9246 continue;
9247
9248 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009249 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
9250 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009251 freq = ifs->current_ssid->frequency;
9252 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
9253 freq = ifs->assoc_freq;
9254 else
9255 continue;
9256
9257 /* Hold only distinct freqs */
9258 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009259 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009260 break;
9261
9262 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009263 freqs_data[idx++].freq = freq;
9264
9265 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009266 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009267 WPA_FREQ_USED_BY_P2P_CLIENT :
9268 WPA_FREQ_USED_BY_INFRA_STATION;
9269 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009270 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009271
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009272 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009273 return idx;
9274}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009275
9276
9277/*
9278 * Find the operating frequencies of any of the virtual interfaces that
9279 * are using the same radio as the current interface.
9280 */
9281int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009282 int *freq_array, unsigned int len,
9283 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009284{
9285 struct wpa_used_freq_data *freqs_data;
9286 int num, i;
9287
9288 os_memset(freq_array, 0, sizeof(int) * len);
9289
9290 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
9291 if (!freqs_data)
9292 return -1;
9293
Sunil Ravi77d572f2023-01-17 23:58:31 +00009294 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
9295 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009296 for (i = 0; i < num; i++)
9297 freq_array[i] = freqs_data[i].freq;
9298
9299 os_free(freqs_data);
9300
9301 return num;
9302}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009303
9304
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009305struct wpa_supplicant *
9306wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9307{
9308 switch (frame) {
9309#ifdef CONFIG_P2P
9310 case VENDOR_ELEM_PROBE_REQ_P2P:
9311 case VENDOR_ELEM_PROBE_RESP_P2P:
9312 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9313 case VENDOR_ELEM_BEACON_P2P_GO:
9314 case VENDOR_ELEM_P2P_PD_REQ:
9315 case VENDOR_ELEM_P2P_PD_RESP:
9316 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9317 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9318 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9319 case VENDOR_ELEM_P2P_INV_REQ:
9320 case VENDOR_ELEM_P2P_INV_RESP:
9321 case VENDOR_ELEM_P2P_ASSOC_REQ:
9322 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009323 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009324#endif /* CONFIG_P2P */
9325 default:
9326 return wpa_s;
9327 }
9328}
9329
9330
9331void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9332{
9333 unsigned int i;
9334 char buf[30];
9335
9336 wpa_printf(MSG_DEBUG, "Update vendor elements");
9337
9338 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9339 if (wpa_s->vendor_elem[i]) {
9340 int res;
9341
9342 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9343 if (!os_snprintf_error(sizeof(buf), res)) {
9344 wpa_hexdump_buf(MSG_DEBUG, buf,
9345 wpa_s->vendor_elem[i]);
9346 }
9347 }
9348 }
9349
9350#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009351 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009352 wpa_s->global->p2p &&
9353 !wpa_s->global->p2p_disabled)
9354 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9355#endif /* CONFIG_P2P */
9356}
9357
9358
9359int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9360 const u8 *elem, size_t len)
9361{
9362 u8 *ie, *end;
9363
9364 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9365 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9366
9367 for (; ie + 1 < end; ie += 2 + ie[1]) {
9368 if (ie + len > end)
9369 break;
9370 if (os_memcmp(ie, elem, len) != 0)
9371 continue;
9372
9373 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9374 wpabuf_free(wpa_s->vendor_elem[frame]);
9375 wpa_s->vendor_elem[frame] = NULL;
9376 } else {
9377 os_memmove(ie, ie + len, end - (ie + len));
9378 wpa_s->vendor_elem[frame]->used -= len;
9379 }
9380 wpas_vendor_elem_update(wpa_s);
9381 return 0;
9382 }
9383
9384 return -1;
9385}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009386
9387
9388struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009389 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009390 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009391{
9392 u16 i;
9393
Hai Shalomc1a21442022-02-04 13:43:00 -08009394 if (!modes)
9395 return NULL;
9396
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009397 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009398 if (modes[i].mode != mode ||
9399 !modes[i].num_channels || !modes[i].channels)
9400 continue;
Sunil Ravi99c035e2024-07-12 01:42:03 +00009401 if (is_6ghz == modes[i].is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009402 return &modes[i];
9403 }
9404
9405 return NULL;
9406}
9407
9408
Hai Shalomc1a21442022-02-04 13:43:00 -08009409struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9410 u16 num_modes, int freq)
9411{
9412 int i, j;
9413
9414 for (i = 0; i < num_modes; i++) {
9415 for (j = 0; j < modes[i].num_channels; j++) {
9416 if (freq == modes[i].channels[j].freq)
9417 return &modes[i];
9418 }
9419 }
9420
9421 return NULL;
9422}
9423
9424
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009425static struct
9426wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9427 const u8 *bssid)
9428{
9429 struct wpa_bss_tmp_disallowed *bss;
9430
9431 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9432 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009433 if (ether_addr_equal(bssid, bss->bssid))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009434 return bss;
9435 }
9436
9437 return NULL;
9438}
9439
9440
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009441static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9442{
9443 struct wpa_bss_tmp_disallowed *tmp;
9444 unsigned int num_bssid = 0;
9445 u8 *bssids;
9446 int ret;
9447
9448 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9449 if (!bssids)
9450 return -1;
9451 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9452 struct wpa_bss_tmp_disallowed, list) {
9453 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9454 ETH_ALEN);
9455 num_bssid++;
9456 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009457 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009458 os_free(bssids);
9459 return ret;
9460}
9461
9462
9463static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9464{
9465 struct wpa_supplicant *wpa_s = eloop_ctx;
9466 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9467
9468 /* Make sure the bss is not already freed */
9469 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9470 struct wpa_bss_tmp_disallowed, list) {
9471 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009472 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009473 wpa_set_driver_tmp_disallow_list(wpa_s);
9474 break;
9475 }
9476 }
9477}
9478
9479
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009480void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009481 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009482{
9483 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009484
9485 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9486 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009487 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009488 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009489 }
9490
9491 bss = os_malloc(sizeof(*bss));
9492 if (!bss) {
9493 wpa_printf(MSG_DEBUG,
9494 "Failed to allocate memory for temp disallow BSS");
9495 return;
9496 }
9497
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009498 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9499 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009500 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009501
9502finish:
9503 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009504 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9505 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009506}
9507
9508
Hai Shalom74f70d42019-02-11 14:42:39 -08009509int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9510 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009511{
Hai Shalom74f70d42019-02-11 14:42:39 -08009512 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009513
9514 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9515 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009516 if (ether_addr_equal(bss->bssid, tmp->bssid)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009517 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009518 break;
9519 }
9520 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009521 if (!disallowed)
9522 return 0;
9523
9524 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009525 bss->level > disallowed->rssi_threshold) {
9526 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9527 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009528 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009529 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009530
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009531 return 1;
9532}
Hai Shalom81f62d82019-07-22 12:10:00 -07009533
9534
9535int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9536 unsigned int type, const u8 *addr,
9537 const u8 *mask)
9538{
9539 if ((addr && !mask) || (!addr && mask)) {
9540 wpa_printf(MSG_INFO,
9541 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9542 return -1;
9543 }
9544
9545 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9546 wpa_printf(MSG_INFO,
9547 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9548 return -1;
9549 }
9550
9551 if (type & MAC_ADDR_RAND_SCAN) {
9552 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9553 addr, mask))
9554 return -1;
9555 }
9556
9557 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9558 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9559 addr, mask))
9560 return -1;
9561
9562 if (wpa_s->sched_scanning && !wpa_s->pno)
9563 wpas_scan_restart_sched_scan(wpa_s);
9564 }
9565
9566 if (type & MAC_ADDR_RAND_PNO) {
9567 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9568 addr, mask))
9569 return -1;
9570
9571 if (wpa_s->pno) {
9572 wpas_stop_pno(wpa_s);
9573 wpas_start_pno(wpa_s);
9574 }
9575 }
9576
9577 return 0;
9578}
9579
9580
9581int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9582 unsigned int type)
9583{
9584 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9585 if (wpa_s->pno) {
9586 if (type & MAC_ADDR_RAND_PNO) {
9587 wpas_stop_pno(wpa_s);
9588 wpas_start_pno(wpa_s);
9589 }
9590 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9591 wpas_scan_restart_sched_scan(wpa_s);
9592 }
9593
9594 return 0;
9595}
Hai Shalomfdcde762020-04-02 11:19:20 -07009596
9597
9598int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9599 struct wpa_signal_info *si)
9600{
9601 int res;
9602
9603 if (!wpa_s->driver->signal_poll)
9604 return -1;
9605
9606 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9607
9608#ifdef CONFIG_TESTING_OPTIONS
9609 if (res == 0) {
9610 struct driver_signal_override *dso;
9611
9612 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9613 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009614 if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009615 continue;
9616 wpa_printf(MSG_DEBUG,
9617 "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 +00009618 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009619 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009620 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009621 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009622 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009623 dso->si_avg_beacon_signal,
9624 si->current_noise,
9625 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009626 si->data.signal = dso->si_current_signal;
9627 si->data.avg_signal = dso->si_avg_signal;
9628 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009629 si->current_noise = dso->si_current_noise;
9630 break;
9631 }
9632 }
9633#endif /* CONFIG_TESTING_OPTIONS */
9634
9635 return res;
9636}
9637
9638
9639struct wpa_scan_results *
Sunil Ravi99c035e2024-07-12 01:42:03 +00009640wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07009641{
9642 struct wpa_scan_results *scan_res;
9643#ifdef CONFIG_TESTING_OPTIONS
9644 size_t idx;
9645#endif /* CONFIG_TESTING_OPTIONS */
9646
Sunil Ravi99c035e2024-07-12 01:42:03 +00009647 if (wpa_s->driver->get_scan_results)
9648 scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
9649 bssid);
9650 else if (wpa_s->driver->get_scan_results2)
9651 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9652 else
Hai Shalomfdcde762020-04-02 11:19:20 -07009653 return NULL;
9654
Hai Shalomfdcde762020-04-02 11:19:20 -07009655
9656#ifdef CONFIG_TESTING_OPTIONS
9657 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9658 struct driver_signal_override *dso;
9659 struct wpa_scan_res *res = scan_res->res[idx];
9660
9661 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9662 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009663 if (!ether_addr_equal(res->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009664 continue;
9665 wpa_printf(MSG_DEBUG,
9666 "Override driver scan signal level %d->%d for "
9667 MACSTR,
9668 res->level, dso->scan_level,
9669 MAC2STR(res->bssid));
9670 res->flags |= WPA_SCAN_QUAL_INVALID;
9671 if (dso->scan_level < 0)
9672 res->flags |= WPA_SCAN_LEVEL_DBM;
9673 else
9674 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9675 res->level = dso->scan_level;
9676 break;
9677 }
9678 }
9679#endif /* CONFIG_TESTING_OPTIONS */
9680
9681 return scan_res;
9682}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009683
9684
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009685bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009686{
9687 int i;
9688
9689 if (!wpa_s->valid_links)
9690 return false;
9691
Sunil Ravi99c035e2024-07-12 01:42:03 +00009692 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009693 if (ether_addr_equal(wpa_s->links[i].bssid, addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00009694 return true;
9695 }
9696
9697 return false;
9698}
9699
9700
9701int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9702 unsigned int wait, const u8 *dst, const u8 *src,
9703 const u8 *bssid, const u8 *data, size_t data_len,
9704 int no_cck)
9705{
9706 if (!wpa_s->driver->send_action)
9707 return -1;
9708
9709 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9710 if (wpas_ap_link_address(wpa_s, dst))
9711 dst = wpa_s->ap_mld_addr;
9712
9713 if (wpas_ap_link_address(wpa_s, bssid))
9714 bssid = wpa_s->ap_mld_addr;
9715 }
9716
9717 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9718 bssid, data, data_len, no_cck);
9719}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009720
9721
9722bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9723{
9724 struct hostapd_channel_data *chnl;
9725 int i, j;
9726
9727 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9728 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9729 chnl = wpa_s->hw.modes[i].channels;
9730 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9731 if (only_enabled &&
9732 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9733 continue;
9734 if (is_6ghz_freq(chnl[j].freq))
9735 return true;
9736 }
9737 }
9738 }
9739
9740 return false;
9741}
Sunil Ravi7f769292024-07-23 22:21:32 +00009742
9743
9744bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
9745 struct wpa_bss *bss)
9746{
9747 int i;
9748
9749 if (!bss)
9750 return false;
9751 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9752 wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9753 return true;
9754
9755 if (!wpa_s->valid_links)
9756 return false;
9757
9758 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9759 if (!(wpa_s->valid_links & BIT(i)))
9760 continue;
9761 if (wpa_s->links[i].bss &&
9762 (wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9763 RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9764 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9765 RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
9766 return true;
9767 }
9768
9769 return false;
9770}
9771
9772
9773bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
9774 struct wpa_bss *bss)
9775{
9776 int i;
9777
9778 if (!bss)
9779 return false;
9780 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9781 return true;
9782
9783 if (!wpa_s->valid_links)
9784 return false;
9785
9786 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9787 if (!(wpa_s->valid_links & BIT(i)))
9788 continue;
9789 if (wpa_s->links[i].bss &&
9790 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9791 RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9792 return true;
9793 }
9794
9795 return false;
9796}
Sunil Ravic0f5d412024-09-11 22:12:49 +00009797
9798
9799int wpas_get_owe_trans_network(const u8 *owe_ie, const u8 **bssid,
9800 const u8 **ssid, size_t *ssid_len)
9801{
9802#ifdef CONFIG_OWE
9803 const u8 *pos, *end;
9804 u8 ssid_len_tmp;
9805
9806 if (!owe_ie)
9807 return -1;
9808
9809 pos = owe_ie + 6;
9810 end = owe_ie + 2 + owe_ie[1];
9811
9812 if (end - pos < ETH_ALEN + 1)
9813 return -1;
9814 *bssid = pos;
9815 pos += ETH_ALEN;
9816 ssid_len_tmp = *pos++;
9817 if (end - pos < ssid_len_tmp || ssid_len_tmp > SSID_MAX_LEN)
9818 return -1;
9819
9820 *ssid = pos;
9821 *ssid_len = ssid_len_tmp;
9822
9823 return 0;
9824#else /* CONFIG_OWE */
9825 return -1;
9826#endif /* CONFIG_OWE */
9827}