blob: 15a859f59c259fd5573c04319328412f5b77e32a [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 */
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -070073#include "aidl/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);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700421 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700422 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
423 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
425 wpa_s->group_cipher = WPA_CIPHER_NONE;
426 wpa_s->mgmt_group_cipher = 0;
427
Hai Shalomfdcde762020-04-02 11:19:20 -0700428#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 for (i = 0; i < NUM_WEP_KEYS; i++) {
430 if (ssid->wep_key_len[i] > 5) {
431 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
432 wpa_s->group_cipher = WPA_CIPHER_WEP104;
433 break;
434 } else if (ssid->wep_key_len[i] > 0) {
435 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
436 wpa_s->group_cipher = WPA_CIPHER_WEP40;
437 break;
438 }
439 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700440#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
444 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
445 wpa_s->pairwise_cipher);
446 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
448 wpa_s->mgmt_group_cipher);
Sunil Ravi7f769292024-07-23 22:21:32 +0000449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450
451 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000452 os_memset(&mlo, 0, sizeof(mlo));
453 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700454}
455
456
Dmitry Shmidt04949592012-07-19 12:16:46 -0700457void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800458{
459 int i;
460 if (wpa_s->hw.modes == NULL)
461 return;
462
463 for (i = 0; i < wpa_s->hw.num_modes; i++) {
464 os_free(wpa_s->hw.modes[i].channels);
465 os_free(wpa_s->hw.modes[i].rates);
466 }
467
468 os_free(wpa_s->hw.modes);
469 wpa_s->hw.modes = NULL;
470}
471
472
Hai Shalomc1a21442022-02-04 13:43:00 -0800473static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
474 struct wpa_bss_tmp_disallowed *bss)
475{
476 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
477 dl_list_del(&bss->list);
478 os_free(bss);
479}
480
481
Hai Shalom74f70d42019-02-11 14:42:39 -0800482void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800483{
484 struct wpa_bss_tmp_disallowed *bss, *prev;
485
486 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800487 struct wpa_bss_tmp_disallowed, list)
488 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800489}
490
491
Paul Stewart092955c2017-02-06 09:13:09 -0800492void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
493{
494 struct fils_hlp_req *req;
495
496 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
497 list)) != NULL) {
498 dl_list_del(&req->list);
499 wpabuf_free(req->pkt);
500 os_free(req);
501 }
502}
503
504
Hai Shalomfdcde762020-04-02 11:19:20 -0700505void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
506{
507 struct wpa_supplicant *wpa_s = eloop_ctx;
508
509 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
510 return;
511 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
512 wpa_bss_flush(wpa_s);
513}
514
515
516#ifdef CONFIG_TESTING_OPTIONS
517void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
518{
519 struct driver_signal_override *dso;
520
521 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
522 struct driver_signal_override, list))) {
523 dl_list_del(&dso->list);
524 os_free(dso);
525 }
526}
527#endif /* CONFIG_TESTING_OPTIONS */
528
529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700530static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
531{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700532 int i;
533
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700535 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700536 scard_deinit(wpa_s->scard);
537 wpa_s->scard = NULL;
538 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
539 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
540 l2_packet_deinit(wpa_s->l2);
541 wpa_s->l2 = NULL;
542 if (wpa_s->l2_br) {
543 l2_packet_deinit(wpa_s->l2_br);
544 wpa_s->l2_br = NULL;
545 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800546#ifdef CONFIG_TESTING_OPTIONS
547 l2_packet_deinit(wpa_s->l2_test);
548 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800549 os_free(wpa_s->get_pref_freq_list_override);
550 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700551 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
552 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800553 os_free(wpa_s->extra_sae_rejected_groups);
554 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700555 wpabuf_free(wpa_s->rsne_override_eapol);
556 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800557 wpabuf_free(wpa_s->rsnxe_override_assoc);
558 wpa_s->rsnxe_override_assoc = NULL;
559 wpabuf_free(wpa_s->rsnxe_override_eapol);
560 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700561 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800562#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564 if (wpa_s->conf != NULL) {
565 struct wpa_ssid *ssid;
566 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
567 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568 }
569
570 os_free(wpa_s->confname);
571 wpa_s->confname = NULL;
572
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700573 os_free(wpa_s->confanother);
574 wpa_s->confanother = NULL;
575
Hai Shalomce48b4a2018-09-05 11:41:35 -0700576 os_free(wpa_s->last_con_fail_realm);
577 wpa_s->last_con_fail_realm = NULL;
578 wpa_s->last_con_fail_realm_len = 0;
579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 wpa_sm_set_eapol(wpa_s->wpa, NULL);
581 eapol_sm_deinit(wpa_s->eapol);
582 wpa_s->eapol = NULL;
583
584 rsn_preauth_deinit(wpa_s->wpa);
585
586#ifdef CONFIG_TDLS
587 wpa_tdls_deinit(wpa_s->wpa);
588#endif /* CONFIG_TDLS */
589
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000590#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800591 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000592#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800594 ptksa_cache_deinit(wpa_s->ptksa);
595 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 wpa_sm_deinit(wpa_s->wpa);
597 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800598 wpa_bssid_ignore_clear(wpa_s);
599
600#ifdef CONFIG_PASN
601 wpas_pasn_auth_stop(wpa_s);
602#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603
604 wpa_bss_deinit(wpa_s);
605
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700606 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607 wpa_supplicant_cancel_scan(wpa_s);
608 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800609 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
610#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
611 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
612 wpa_s, NULL);
613#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700614
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700615 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700616 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Sunil Ravi7f769292024-07-23 22:21:32 +0000617 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619 wpas_wps_deinit(wpa_s);
620
621 wpabuf_free(wpa_s->pending_eapol_rx);
622 wpa_s->pending_eapol_rx = NULL;
623
624#ifdef CONFIG_IBSS_RSN
625 ibss_rsn_deinit(wpa_s->ibss_rsn);
626 wpa_s->ibss_rsn = NULL;
627#endif /* CONFIG_IBSS_RSN */
628
629 sme_deinit(wpa_s);
630
631#ifdef CONFIG_AP
632 wpa_supplicant_ap_deinit(wpa_s);
633#endif /* CONFIG_AP */
634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700635 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700636
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800637#ifdef CONFIG_OFFCHANNEL
638 offchannel_deinit(wpa_s);
639#endif /* CONFIG_OFFCHANNEL */
640
641 wpa_supplicant_cancel_sched_scan(wpa_s);
642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643 os_free(wpa_s->next_scan_freqs);
644 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800645
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800646 os_free(wpa_s->manual_scan_freqs);
647 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700648 os_free(wpa_s->select_network_scan_freqs);
649 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800650
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700651 os_free(wpa_s->manual_sched_scan_freqs);
652 wpa_s->manual_sched_scan_freqs = NULL;
653
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800654 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
655
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700656 /*
657 * Need to remove any pending gas-query radio work before the
658 * gas_query_deinit() call because gas_query::work has not yet been set
659 * for works that have not been started. gas_query_free() will be unable
660 * to cancel such pending radio works and once the pending gas-query
661 * radio work eventually gets removed, the deinit notification call to
662 * gas_query_start_cb() would result in dereferencing freed memory.
663 */
664 if (wpa_s->radio)
665 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800666 gas_query_deinit(wpa_s->gas);
667 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700668 gas_server_deinit(wpa_s->gas_server);
669 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800670
671 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700672
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700673 ieee802_1x_dealloc_kay_sm(wpa_s);
674
Dmitry Shmidt04949592012-07-19 12:16:46 -0700675 os_free(wpa_s->bssid_filter);
676 wpa_s->bssid_filter = NULL;
677
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800678 os_free(wpa_s->disallow_aps_bssid);
679 wpa_s->disallow_aps_bssid = NULL;
680 os_free(wpa_s->disallow_aps_ssid);
681 wpa_s->disallow_aps_ssid = NULL;
682
Dmitry Shmidt04949592012-07-19 12:16:46 -0700683 wnm_bss_keep_alive_deinit(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000684 wnm_btm_reset(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700685
686 ext_password_deinit(wpa_s->ext_pw);
687 wpa_s->ext_pw = NULL;
688
689 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800690 wpa_s->last_gas_resp = NULL;
691 wpabuf_free(wpa_s->prev_gas_resp);
692 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700693
694 os_free(wpa_s->last_scan_res);
695 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800696
697#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700698 if (wpa_s->drv_priv)
699 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700700 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800701#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700702
703 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
704 wpabuf_free(wpa_s->vendor_elem[i]);
705 wpa_s->vendor_elem[i] = NULL;
706 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800707
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000708#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800709 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000710#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800711
712 wpa_s->sched_scan_plans_num = 0;
713 os_free(wpa_s->sched_scan_plans);
714 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800715
716#ifdef CONFIG_MBO
717 wpa_s->non_pref_chan_num = 0;
718 os_free(wpa_s->non_pref_chan);
719 wpa_s->non_pref_chan = NULL;
720#endif /* CONFIG_MBO */
721
722 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700723
724 wpabuf_free(wpa_s->lci);
725 wpa_s->lci = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000726#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800727 wpas_clear_beacon_rep_data(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000728#endif /* CONFIG_NO_RRM */
Paul Stewart092955c2017-02-06 09:13:09 -0800729
730#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
731#ifdef CONFIG_MESH
732 {
733 struct external_pmksa_cache *entry;
734
735 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
736 struct external_pmksa_cache,
737 list)) != NULL) {
738 dl_list_del(&entry->list);
739 os_free(entry->pmksa_cache);
740 os_free(entry);
741 }
742 }
743#endif /* CONFIG_MESH */
744#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
745
746 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800747
748 wpabuf_free(wpa_s->ric_ies);
749 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700750
751#ifdef CONFIG_DPP
752 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700753 dpp_global_deinit(wpa_s->dpp);
754 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700755#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800756
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000757#ifdef CONFIG_NAN_USD
758 wpas_nan_usd_deinit(wpa_s);
759#endif /* CONFIG_NAN_USD */
760
Hai Shalom60840252021-02-19 19:02:11 -0800761#ifdef CONFIG_PASN
762 wpas_pasn_auth_stop(wpa_s);
763#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000764#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -0800765 wpas_scs_deinit(wpa_s);
766 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000767#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000768
769#ifdef CONFIG_OWE
770 os_free(wpa_s->owe_trans_scan_freq);
771 wpa_s->owe_trans_scan_freq = NULL;
772#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773}
774
775
776/**
777 * wpa_clear_keys - Clear keys configured for the driver
778 * @wpa_s: Pointer to wpa_supplicant data
779 * @addr: Previously used BSSID or %NULL if not available
780 *
781 * This function clears the encryption keys that has been previously configured
782 * for the driver.
783 */
784void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
785{
Hai Shalomc3565922019-10-28 11:58:20 -0700786 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787
788 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800789 for (i = 0; i < max; i++) {
790 if (wpa_s->keys_cleared & BIT(i))
791 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000792 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700793 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700795 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
796 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800797 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700798 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000799 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
800 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700801 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000802 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
803 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 /* MLME-SETPROTECTION.request(None) */
805 wpa_drv_mlme_setprotection(
806 wpa_s, addr,
807 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
808 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
809 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800810 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811}
812
813
814/**
815 * wpa_supplicant_state_txt - Get the connection state name as a text string
816 * @state: State (wpa_state; WPA_*)
817 * Returns: The state name as a printable text string
818 */
819const char * wpa_supplicant_state_txt(enum wpa_states state)
820{
821 switch (state) {
822 case WPA_DISCONNECTED:
823 return "DISCONNECTED";
824 case WPA_INACTIVE:
825 return "INACTIVE";
826 case WPA_INTERFACE_DISABLED:
827 return "INTERFACE_DISABLED";
828 case WPA_SCANNING:
829 return "SCANNING";
830 case WPA_AUTHENTICATING:
831 return "AUTHENTICATING";
832 case WPA_ASSOCIATING:
833 return "ASSOCIATING";
834 case WPA_ASSOCIATED:
835 return "ASSOCIATED";
836 case WPA_4WAY_HANDSHAKE:
837 return "4WAY_HANDSHAKE";
838 case WPA_GROUP_HANDSHAKE:
839 return "GROUP_HANDSHAKE";
840 case WPA_COMPLETED:
841 return "COMPLETED";
842 default:
843 return "UNKNOWN";
844 }
845}
846
847
848#ifdef CONFIG_BGSCAN
849
Hai Shalom899fcc72020-10-19 14:38:18 -0700850static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
851{
852 if (wpa_s->bgscan_ssid) {
853 bgscan_deinit(wpa_s);
854 wpa_s->bgscan_ssid = NULL;
855 }
856}
857
858
859/**
860 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
861 * @wpa_s: Pointer to the wpa_supplicant data
862 *
863 * Stop, start, or reconfigure the scan parameters depending on the method.
864 */
865void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800867 const char *name;
868
869 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
870 name = wpa_s->current_ssid->bgscan;
871 else
872 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700873 if (!name || name[0] == '\0') {
874 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800875 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700876 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800877 if (wpas_driver_bss_selection(wpa_s))
878 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800879#ifdef CONFIG_P2P
880 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
881 return;
882#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700883
884 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800885 if (wpa_s->current_ssid) {
886 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700887 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
888 "bgscan");
889 /*
890 * Live without bgscan; it is only used as a roaming
891 * optimization, so the initial connection is not
892 * affected.
893 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700894 } else {
895 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700896 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700897 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
Sunil Ravi99c035e2024-07-12 01:42:03 +0000898 0, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700899 if (scan_res) {
900 bgscan_notify_scan(wpa_s, scan_res);
901 wpa_scan_results_free(scan_res);
902 }
903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700904 } else
905 wpa_s->bgscan_ssid = NULL;
906}
907
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700908#endif /* CONFIG_BGSCAN */
909
910
Dmitry Shmidt04949592012-07-19 12:16:46 -0700911static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
912{
913 if (autoscan_init(wpa_s, 0))
914 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
915}
916
917
918static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
919{
920 autoscan_deinit(wpa_s);
921}
922
923
924void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
925{
926 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
927 wpa_s->wpa_state == WPA_SCANNING) {
928 autoscan_deinit(wpa_s);
929 wpa_supplicant_start_autoscan(wpa_s);
930 }
931}
932
933
Sunil Ravi7f769292024-07-23 22:21:32 +0000934static void wpas_verify_ssid_beacon(void *eloop_ctx, void *timeout_ctx)
935{
936 struct wpa_supplicant *wpa_s = eloop_ctx;
937 struct wpa_bss *bss;
938 const u8 *ssid;
939 size_t ssid_len;
940
941 if (!wpa_s->current_ssid || !wpa_s->current_bss)
942 return;
943
944 ssid = wpa_s->current_bss->ssid;
945 ssid_len = wpa_s->current_bss->ssid_len;
946
947 if (wpa_s->current_ssid->ssid_len &&
948 (wpa_s->current_ssid->ssid_len != ssid_len ||
949 os_memcmp(wpa_s->current_ssid->ssid, ssid, ssid_len) != 0))
950 return;
951
952 if (wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
953 !wpa_s->bigtk_set || wpa_s->ssid_verified)
954 return;
955
956 wpa_printf(MSG_DEBUG,
957 "SSID not yet verified; check if the driver has received a verified Beacon frame");
958 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
959 return;
960
961 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
962 if (!bss)
963 return;
964 wpa_printf(MSG_DEBUG, "The current beacon time stamp: 0x%llx",
965 (long long unsigned int) bss->tsf);
966 if (bss->tsf > wpa_s->first_beacon_tsf) {
967 const u8 *ie;
968
969 wpa_printf(MSG_DEBUG,
970 "Verified Beacon frame has been received");
971 wpa_s->beacons_checked++;
972
973 ie = wpa_bss_get_ie_beacon(bss, WLAN_EID_SSID);
974 if (ie && ie[1] == ssid_len &&
975 os_memcmp(&ie[2], ssid, ssid_len) == 0) {
976 wpa_printf(MSG_DEBUG,
977 "SSID verified based on a Beacon frame and beacon protection");
978 wpa_s->ssid_verified = true;
979 return;
980 }
981
982 /* TODO: Multiple BSSID element */
983 }
984
985 if (wpa_s->beacons_checked < 16) {
986 eloop_register_timeout(wpa_s->next_beacon_check, 0,
987 wpas_verify_ssid_beacon, wpa_s, NULL);
988 wpa_s->next_beacon_check++;
989 }
990}
991
992
993static void wpas_verify_ssid_beacon_prot(struct wpa_supplicant *wpa_s)
994{
995 struct wpa_bss *bss;
996
997 wpa_printf(MSG_DEBUG,
998 "SSID not yet verified; try to verify using beacon protection");
999 /* Fetch the current scan result which is likely based on not yet
1000 * verified payload since the current BIGTK was just received. Any
1001 * newer update in the future with a larger timestamp value is an
1002 * indication that a verified Beacon frame has been received. */
1003 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
1004 return;
1005
1006 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
1007 if (!bss)
1008 return;
1009 wpa_printf(MSG_DEBUG, "The initial beacon time stamp: 0x%llx",
1010 (long long unsigned int) bss->tsf);
1011 wpa_s->first_beacon_tsf = bss->tsf;
1012 wpa_s->beacons_checked = 0;
1013 wpa_s->next_beacon_check = 1;
1014 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
1015 eloop_register_timeout(1, 0, wpas_verify_ssid_beacon, wpa_s, NULL);
1016}
1017
1018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019/**
1020 * wpa_supplicant_set_state - Set current connection state
1021 * @wpa_s: Pointer to wpa_supplicant data
1022 * @state: The new connection state
1023 *
1024 * This function is called whenever the connection state changes, e.g.,
1025 * association is completed for WPA/WPA2 4-Way Handshake is started.
1026 */
1027void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
1028 enum wpa_states state)
1029{
1030 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -07001031#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -07001032 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001033#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034
1035 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
1036 wpa_supplicant_state_txt(wpa_s->wpa_state),
1037 wpa_supplicant_state_txt(state));
1038
Hai Shalom74f70d42019-02-11 14:42:39 -08001039 if (state == WPA_COMPLETED &&
1040 os_reltime_initialized(&wpa_s->roam_start)) {
1041 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
1042 wpa_s->roam_start.sec = 0;
1043 wpa_s->roam_start.usec = 0;
1044 wpas_notify_auth_changed(wpa_s);
1045 wpas_notify_roam_time(wpa_s);
1046 wpas_notify_roam_complete(wpa_s);
1047 } else if (state == WPA_DISCONNECTED &&
1048 os_reltime_initialized(&wpa_s->roam_start)) {
1049 wpa_s->roam_start.sec = 0;
1050 wpa_s->roam_start.usec = 0;
1051 wpa_s->roam_time.sec = 0;
1052 wpa_s->roam_time.usec = 0;
1053 wpas_notify_roam_complete(wpa_s);
1054 }
1055
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08001056 if (state == WPA_INTERFACE_DISABLED) {
1057 /* Assure normal scan when interface is restored */
1058 wpa_s->normal_scans = 0;
1059 }
1060
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001061 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001062 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001063 /* Reinitialize normal_scan counter */
1064 wpa_s->normal_scans = 0;
1065 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001066
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001067#ifdef CONFIG_P2P
1068 /*
1069 * P2PS client has to reply to Probe Request frames received on the
1070 * group operating channel. Enable Probe Request frame reporting for
1071 * P2P connected client in case p2p_cli_probe configuration property is
1072 * set to 1.
1073 */
1074 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
1075 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
1076 wpa_s->current_ssid->p2p_group) {
1077 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
1078 wpa_dbg(wpa_s, MSG_DEBUG,
1079 "P2P: Enable CLI Probe Request RX reporting");
1080 wpa_s->p2p_cli_probe =
1081 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
1082 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
1083 wpa_dbg(wpa_s, MSG_DEBUG,
1084 "P2P: Disable CLI Probe Request RX reporting");
1085 wpa_s->p2p_cli_probe = 0;
1086 wpa_drv_probe_req_report(wpa_s, 0);
1087 }
1088 }
1089#endif /* CONFIG_P2P */
1090
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091 if (state != WPA_SCANNING)
1092 wpa_supplicant_notify_scanning(wpa_s, 0);
1093
1094 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001096 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001097 char mld_addr[50];
1098
1099 mld_addr[0] = '\0';
1100 if (wpa_s->valid_links)
1101 os_snprintf(mld_addr, sizeof(mld_addr),
1102 " ap_mld_addr=" MACSTR,
1103 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001104
1105#ifdef CONFIG_SME
1106 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1107 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1108 fils_hlp_sent = 1;
1109#endif /* CONFIG_SME */
1110 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1111 wpa_auth_alg_fils(wpa_s->auth_alg))
1112 fils_hlp_sent = 1;
1113
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001114#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001115 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001116 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001117 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001119 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001120 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001122 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001123 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001124 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 wpa_drv_set_operstate(wpa_s, 1);
1126#ifndef IEEE8021X_EAPOL
1127 wpa_drv_set_supp_port(wpa_s, 1);
1128#endif /* IEEE8021X_EAPOL */
1129 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001130 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001131 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001132
1133 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134
1135#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1136 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001137 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001138#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001139#ifdef CONFIG_OWE
1140 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1141 wpas_update_owe_connect_params(wpa_s);
1142#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001143#ifdef CONFIG_HS20
1144 hs20_configure_frame_filters(wpa_s);
1145#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1147 state == WPA_ASSOCIATED) {
1148 wpa_s->new_connection = 1;
1149 wpa_drv_set_operstate(wpa_s, 0);
1150#ifndef IEEE8021X_EAPOL
1151 wpa_drv_set_supp_port(wpa_s, 0);
1152#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001153 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154 }
1155 wpa_s->wpa_state = state;
1156
1157#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001158 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1159 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001160 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001161 wpa_supplicant_stop_bgscan(wpa_s);
1162#endif /* CONFIG_BGSCAN */
1163
Hai Shalom5f92bc92019-04-18 11:54:11 -07001164 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001165 wpa_supplicant_stop_autoscan(wpa_s);
1166
1167 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1168 wpa_supplicant_start_autoscan(wpa_s);
1169
Sunil Ravi99c035e2024-07-12 01:42:03 +00001170 if (state == WPA_COMPLETED || state == WPA_INTERFACE_DISABLED ||
1171 state == WPA_INACTIVE)
1172 wnm_btm_reset(wpa_s);
1173
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001174#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001175 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1176 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001177#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001179 if (wpa_s->wpa_state != old_state) {
1180 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1181
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001182 /*
1183 * Notify the P2P Device interface about a state change in one
1184 * of the interfaces.
1185 */
1186 wpas_p2p_indicate_state_change(wpa_s);
1187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 if (wpa_s->wpa_state == WPA_COMPLETED ||
1189 old_state == WPA_COMPLETED)
1190 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001191#ifdef CONFIG_DPP2
1192 if (wpa_s->wpa_state == WPA_COMPLETED)
1193 wpas_dpp_connected(wpa_s);
1194#endif /* CONFIG_DPP2 */
Sunil Ravi7f769292024-07-23 22:21:32 +00001195
1196 if (wpa_s->wpa_state == WPA_COMPLETED &&
1197 wpa_s->bigtk_set && !wpa_s->ssid_verified)
1198 wpas_verify_ssid_beacon_prot(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 }
Hai Shalomc3565922019-10-28 11:58:20 -07001200#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1201 if (update_fils_connect_params)
1202 wpas_update_fils_connect_params(wpa_s);
1203#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204}
1205
1206
1207void wpa_supplicant_terminate_proc(struct wpa_global *global)
1208{
1209 int pending = 0;
1210#ifdef CONFIG_WPS
1211 struct wpa_supplicant *wpa_s = global->ifaces;
1212 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001213 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001214 if (wpas_wps_terminate_pending(wpa_s) == 1)
1215 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001216#ifdef CONFIG_P2P
1217 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1218 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1219 wpas_p2p_disconnect(wpa_s);
1220#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001221 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222 }
1223#endif /* CONFIG_WPS */
1224 if (pending)
1225 return;
1226 eloop_terminate();
1227}
1228
1229
1230static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1231{
1232 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001233 wpa_supplicant_terminate_proc(global);
1234}
1235
1236
1237void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1238{
1239 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001240 enum wpa_states new_state;
1241
1242 if (old_state == WPA_SCANNING)
1243 new_state = WPA_SCANNING;
1244 else
1245 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246
1247 wpa_s->pairwise_cipher = 0;
1248 wpa_s->group_cipher = 0;
1249 wpa_s->mgmt_group_cipher = 0;
1250 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001251 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001253 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254
1255 if (wpa_s->wpa_state != old_state)
1256 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1257}
1258
1259
1260/**
1261 * wpa_supplicant_reload_configuration - Reload configuration data
1262 * @wpa_s: Pointer to wpa_supplicant data
1263 * Returns: 0 on success or -1 if configuration parsing failed
1264 *
1265 * This function can be used to request that the configuration data is reloaded
1266 * (e.g., after configuration file change). This function is reloading
1267 * configuration only for one interface, so this may need to be called multiple
1268 * times if %wpa_supplicant is controlling multiple interfaces and all
1269 * interfaces need reconfiguration.
1270 */
1271int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1272{
1273 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 int reconf_ctrl;
1275 int old_ap_scan;
1276
1277 if (wpa_s->confname == NULL)
1278 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001279 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 if (conf == NULL) {
1281 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1282 "file '%s' - exiting", wpa_s->confname);
1283 return -1;
1284 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001285 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001286 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001287 wpa_msg(wpa_s, MSG_ERROR,
1288 "Failed to parse the configuration file '%s' - exiting",
1289 wpa_s->confanother);
1290 return -1;
1291 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293 conf->changed_parameters = (unsigned int) -1;
1294
1295 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1296 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1297 os_strcmp(conf->ctrl_interface,
1298 wpa_s->conf->ctrl_interface) != 0);
1299
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001300 if (reconf_ctrl) {
1301 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001302 wpa_s->ctrl_iface = NULL;
1303 }
1304
1305 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001306 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001307 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1308 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001309 wpa_supplicant_deauthenticate(wpa_s,
1310 WLAN_REASON_DEAUTH_LEAVING);
1311 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312
1313 /*
1314 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001315 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001317 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1318 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1319 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320 /*
1321 * Clear forced success to clear EAP state for next
1322 * authentication.
1323 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001324 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325 }
1326 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1327 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001328 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1330 rsn_preauth_deinit(wpa_s->wpa);
1331
1332 old_ap_scan = wpa_s->conf->ap_scan;
1333 wpa_config_free(wpa_s->conf);
1334 wpa_s->conf = conf;
1335 if (old_ap_scan != wpa_s->conf->ap_scan)
1336 wpas_notify_ap_scan_changed(wpa_s);
1337
1338 if (reconf_ctrl)
1339 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1340
1341 wpa_supplicant_update_config(wpa_s);
1342
1343 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001344 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345 wpa_s->reassociate = 1;
1346 wpa_supplicant_req_scan(wpa_s, 0, 0);
1347 }
Hai Shalom60840252021-02-19 19:02:11 -08001348 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1350 return 0;
1351}
1352
1353
1354static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1355{
1356 struct wpa_global *global = signal_ctx;
1357 struct wpa_supplicant *wpa_s;
1358 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1359 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1360 sig);
1361 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1362 wpa_supplicant_terminate_proc(global);
1363 }
1364 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001365
1366 if (wpa_debug_reopen_file() < 0) {
1367 /* Ignore errors since we cannot really do much to fix this */
1368 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1369 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370}
1371
1372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1374 struct wpa_ssid *ssid,
1375 struct wpa_ie_data *ie)
1376{
1377 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1378 if (ret) {
1379 if (ret == -2) {
1380 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1381 "from association info");
1382 }
1383 return -1;
1384 }
1385
1386 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1387 "cipher suites");
1388 if (!(ie->group_cipher & ssid->group_cipher)) {
1389 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1390 "cipher 0x%x (mask 0x%x) - reject",
1391 ie->group_cipher, ssid->group_cipher);
1392 return -1;
1393 }
1394 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1395 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1396 "cipher 0x%x (mask 0x%x) - reject",
1397 ie->pairwise_cipher, ssid->pairwise_cipher);
1398 return -1;
1399 }
1400 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1401 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1402 "management 0x%x (mask 0x%x) - reject",
1403 ie->key_mgmt, ssid->key_mgmt);
1404 return -1;
1405 }
1406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001408 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1410 "that does not support management frame protection - "
1411 "reject");
1412 return -1;
1413 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414
1415 return 0;
1416}
1417
1418
Hai Shalom021b0b52019-04-10 11:17:58 -07001419static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1420 int freq)
1421{
1422 if (!ie->has_group)
1423 ie->group_cipher = wpa_default_rsn_cipher(freq);
1424 if (!ie->has_pairwise)
1425 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1426 return (ie->group_cipher & ssid->group_cipher) &&
1427 (ie->pairwise_cipher & ssid->pairwise_cipher);
1428}
1429
1430
Hai Shalomc1a21442022-02-04 13:43:00 -08001431void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1432 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1433{
1434 int sel;
1435
1436 sel = ie->mgmt_group_cipher;
1437 if (ssid->group_mgmt_cipher)
1438 sel &= ssid->group_mgmt_cipher;
1439 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1440 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1441 sel = 0;
1442 wpa_dbg(wpa_s, MSG_DEBUG,
1443 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1444 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1445 if (sel & WPA_CIPHER_AES_128_CMAC) {
1446 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1447 wpa_dbg(wpa_s, MSG_DEBUG,
1448 "WPA: using MGMT group cipher AES-128-CMAC");
1449 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1450 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1451 wpa_dbg(wpa_s, MSG_DEBUG,
1452 "WPA: using MGMT group cipher BIP-GMAC-128");
1453 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1454 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1455 wpa_dbg(wpa_s, MSG_DEBUG,
1456 "WPA: using MGMT group cipher BIP-GMAC-256");
1457 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1458 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1459 wpa_dbg(wpa_s, MSG_DEBUG,
1460 "WPA: using MGMT group cipher BIP-CMAC-256");
1461 } else {
1462 wpa_s->mgmt_group_cipher = 0;
1463 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1464 }
1465 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1466 wpa_s->mgmt_group_cipher);
1467 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1468 wpas_get_ssid_pmf(wpa_s, ssid));
1469}
1470
Sunil Ravi77d572f2023-01-17 23:58:31 +00001471/**
1472 * wpa_supplicant_get_psk - Get PSK from config or external database
1473 * @wpa_s: Pointer to wpa_supplicant data
1474 * @bss: Scan results for the selected BSS, or %NULL if not available
1475 * @ssid: Configuration data for the selected network
1476 * @psk: Buffer for the PSK
1477 * Returns: 0 on success or -1 if configuration parsing failed
1478 *
1479 * This function obtains the PSK for a network, either included inline in the
1480 * config or retrieved from an external database.
1481 */
1482static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1483 struct wpa_bss *bss, struct wpa_ssid *ssid,
1484 u8 *psk)
1485{
1486 if (ssid->psk_set) {
1487 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1488 ssid->psk, PMK_LEN);
1489 os_memcpy(psk, ssid->psk, PMK_LEN);
1490 return 0;
1491 }
1492
1493#ifndef CONFIG_NO_PBKDF2
1494 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1495 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1496 4096, psk, PMK_LEN) != 0) {
1497 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1498 return -1;
1499 }
1500 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1501 psk, PMK_LEN);
1502 return 0;
1503 }
1504#endif /* CONFIG_NO_PBKDF2 */
1505
1506#ifdef CONFIG_EXT_PASSWORD
1507 if (ssid->ext_psk) {
1508 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1509 ssid->ext_psk);
1510 char pw_str[64 + 1];
1511
1512 if (!pw) {
1513 wpa_msg(wpa_s, MSG_INFO,
1514 "EXT PW: No PSK found from external storage");
1515 return -1;
1516 }
1517
1518 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1519 wpa_msg(wpa_s, MSG_INFO,
1520 "EXT PW: Unexpected PSK length %d in external storage",
1521 (int) wpabuf_len(pw));
1522 ext_password_free(pw);
1523 return -1;
1524 }
1525
1526 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1527 pw_str[wpabuf_len(pw)] = '\0';
1528
1529#ifndef CONFIG_NO_PBKDF2
1530 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1531 {
1532 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1533 4096, psk, PMK_LEN) != 0) {
1534 wpa_msg(wpa_s, MSG_WARNING,
1535 "Error in pbkdf2_sha1()");
1536 forced_memzero(pw_str, sizeof(pw_str));
1537 ext_password_free(pw);
1538 return -1;
1539 }
1540 wpa_hexdump_key(MSG_MSGDUMP,
1541 "PSK (from external passphrase)",
1542 psk, PMK_LEN);
1543 } else
1544#endif /* CONFIG_NO_PBKDF2 */
1545 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1546 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1547 wpa_msg(wpa_s, MSG_INFO,
1548 "EXT PW: Invalid PSK hex string");
1549 forced_memzero(pw_str, sizeof(pw_str));
1550 ext_password_free(pw);
1551 return -1;
1552 }
1553 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1554 psk, PMK_LEN);
1555 } else {
1556 wpa_msg(wpa_s, MSG_INFO,
1557 "EXT PW: No suitable PSK available");
1558 forced_memzero(pw_str, sizeof(pw_str));
1559 ext_password_free(pw);
1560 return -1;
1561 }
1562
1563 forced_memzero(pw_str, sizeof(pw_str));
1564 ext_password_free(pw);
1565
1566 return 0;
1567 }
1568#endif /* CONFIG_EXT_PASSWORD */
1569
1570 return -1;
1571}
1572
Hai Shalomc1a21442022-02-04 13:43:00 -08001573
Sunil Ravi89eba102022-09-13 21:04:37 -07001574static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1575 struct wpa_ssid *ssid)
1576{
1577 int akm_count = wpa_s->max_num_akms;
1578 u8 capab = 0;
1579
1580 if (akm_count < 2)
1581 return;
1582
1583 akm_count--;
1584 wpa_s->allowed_key_mgmts = 0;
1585 switch (wpa_s->key_mgmt) {
1586 case WPA_KEY_MGMT_PSK:
1587 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1588 akm_count--;
1589 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1590 }
1591 if (!akm_count)
1592 break;
1593 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1594 akm_count--;
1595 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1596 }
1597 if (!akm_count)
1598 break;
1599 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1600 wpa_s->allowed_key_mgmts |=
1601 WPA_KEY_MGMT_PSK_SHA256;
1602 break;
1603 case WPA_KEY_MGMT_PSK_SHA256:
1604 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1605 akm_count--;
1606 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1607 }
1608 if (!akm_count)
1609 break;
1610 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1611 akm_count--;
1612 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1613 }
1614 if (!akm_count)
1615 break;
1616 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1617 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1618 break;
1619 case WPA_KEY_MGMT_SAE:
1620 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1621 akm_count--;
1622 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1623 }
1624 if (!akm_count)
1625 break;
1626 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1627 akm_count--;
1628 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1629 }
1630 if (!akm_count)
1631 break;
1632 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1633 wpa_s->allowed_key_mgmts |=
1634 WPA_KEY_MGMT_PSK_SHA256;
1635 break;
1636 case WPA_KEY_MGMT_SAE_EXT_KEY:
1637 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1638 akm_count--;
1639 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1640 }
1641 if (!akm_count)
1642 break;
1643 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1644 akm_count--;
1645 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1646 }
1647 if (!akm_count)
1648 break;
1649 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1650 wpa_s->allowed_key_mgmts |=
1651 WPA_KEY_MGMT_PSK_SHA256;
1652 break;
1653 default:
1654 return;
1655 }
1656
Sunil Ravi77d572f2023-01-17 23:58:31 +00001657 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1658 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001659 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1660#ifdef CONFIG_SAE_PK
1661 if (ssid->sae_pk)
1662 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1663#endif /* CONFIG_SAE_PK */
1664
1665 if (!((wpa_s->allowed_key_mgmts &
1666 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1667 return;
1668
1669 if (!wpa_s->rsnxe_len) {
1670 wpa_s->rsnxe_len = 3;
1671 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1672 wpa_s->rsnxe[1] = 1;
1673 wpa_s->rsnxe[2] = 0;
1674 }
1675
1676 wpa_s->rsnxe[2] |= capab;
1677}
1678
1679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680/**
1681 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1682 * @wpa_s: Pointer to wpa_supplicant data
1683 * @bss: Scan results for the selected BSS, or %NULL if not available
1684 * @ssid: Configuration data for the selected network
1685 * @wpa_ie: Buffer for the WPA/RSN IE
1686 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1687 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001688 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001689 * Returns: 0 on success or -1 on failure
1690 *
1691 * This function is used to configure authentication and encryption parameters
1692 * based on the network configuration and scan result for the selected BSS (if
1693 * available).
1694 */
1695int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1696 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001697 u8 *wpa_ie, size_t *wpa_ie_len,
1698 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001699{
1700 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001701 int sel, proto;
1702 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001703 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001704 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705
1706 if (bss) {
1707 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
Sunil Ravi7f769292024-07-23 22:21:32 +00001708 bss_rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
1709 bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001710 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001711 } else {
1712 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1713 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714
1715 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1716 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001717 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718 (ie.key_mgmt & ssid->key_mgmt)) {
1719 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1720 proto = WPA_PROTO_RSN;
1721 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001722 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 (ie.group_cipher & ssid->group_cipher) &&
1724 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1725 (ie.key_mgmt & ssid->key_mgmt)) {
1726 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1727 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001728#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001729 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1730 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1731 (ie.group_cipher & ssid->group_cipher) &&
1732 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1733 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001734 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001735 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001736 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1737 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1738 (ie.group_cipher & ssid->group_cipher) &&
1739 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1740 (ie.key_mgmt & ssid->key_mgmt)) {
1741 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1742 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001743#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 } else if (bss) {
1745 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001746 wpa_dbg(wpa_s, MSG_DEBUG,
1747 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1748 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1749 ssid->key_mgmt);
1750 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1751 MAC2STR(bss->bssid),
1752 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1753 bss_wpa ? " WPA" : "",
1754 bss_rsn ? " RSN" : "",
1755 bss_osen ? " OSEN" : "");
1756 if (bss_rsn) {
1757 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1758 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1759 wpa_dbg(wpa_s, MSG_DEBUG,
1760 "Could not parse RSN element");
1761 } else {
1762 wpa_dbg(wpa_s, MSG_DEBUG,
1763 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1764 ie.pairwise_cipher, ie.group_cipher,
1765 ie.key_mgmt);
1766 }
1767 }
1768 if (bss_wpa) {
1769 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1770 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1771 wpa_dbg(wpa_s, MSG_DEBUG,
1772 "Could not parse WPA element");
1773 } else {
1774 wpa_dbg(wpa_s, MSG_DEBUG,
1775 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1776 ie.pairwise_cipher, ie.group_cipher,
1777 ie.key_mgmt);
1778 }
1779 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 return -1;
1781 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001782 if (ssid->proto & WPA_PROTO_OSEN)
1783 proto = WPA_PROTO_OSEN;
1784 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 proto = WPA_PROTO_RSN;
1786 else
1787 proto = WPA_PROTO_WPA;
1788 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1789 os_memset(&ie, 0, sizeof(ie));
1790 ie.group_cipher = ssid->group_cipher;
1791 ie.pairwise_cipher = ssid->pairwise_cipher;
1792 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001793 ie.mgmt_group_cipher = 0;
1794 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1795 if (ssid->group_mgmt_cipher &
1796 WPA_CIPHER_BIP_GMAC_256)
1797 ie.mgmt_group_cipher =
1798 WPA_CIPHER_BIP_GMAC_256;
1799 else if (ssid->group_mgmt_cipher &
1800 WPA_CIPHER_BIP_CMAC_256)
1801 ie.mgmt_group_cipher =
1802 WPA_CIPHER_BIP_CMAC_256;
1803 else if (ssid->group_mgmt_cipher &
1804 WPA_CIPHER_BIP_GMAC_128)
1805 ie.mgmt_group_cipher =
1806 WPA_CIPHER_BIP_GMAC_128;
1807 else
1808 ie.mgmt_group_cipher =
1809 WPA_CIPHER_AES_128_CMAC;
1810 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001811#ifdef CONFIG_OWE
1812 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1813 !ssid->owe_only &&
1814 !bss_wpa && !bss_rsn && !bss_osen) {
1815 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1816 wpa_s->wpa_proto = 0;
1817 *wpa_ie_len = 0;
1818 return 0;
1819 }
1820#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001821 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1822 "based on configuration");
1823 } else
1824 proto = ie.proto;
1825 }
1826
1827 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1828 "pairwise %d key_mgmt %d proto %d",
1829 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830 if (ssid->ieee80211w) {
1831 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1832 ie.mgmt_group_cipher);
1833 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001835 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1837 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001838 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839
1840 if (bss || !wpa_s->ap_ies_from_associnfo) {
1841 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1842 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1843 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001844 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1845 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1846 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847 return -1;
1848 }
1849
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001850#ifdef CONFIG_NO_WPA
1851 wpa_s->group_cipher = WPA_CIPHER_NONE;
1852 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1853#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001855 wpa_dbg(wpa_s, MSG_DEBUG,
1856 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1857 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001858 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1859 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1861 "cipher");
1862 return -1;
1863 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001864 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1865 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866
1867 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001868 wpa_dbg(wpa_s, MSG_DEBUG,
1869 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1870 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001871 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1872 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001873 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1874 "cipher");
1875 return -1;
1876 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001877 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1878 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001879#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880
1881 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001882#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001883 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1884 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001885 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001886 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1887 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001888#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001889#ifdef CONFIG_IEEE80211R
1890 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1891 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1892 sel &= ~WPA_KEY_MGMT_FT;
1893#endif /* CONFIG_IEEE80211R */
1894 wpa_dbg(wpa_s, MSG_DEBUG,
1895 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1896 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001898#ifdef CONFIG_IEEE80211R
1899#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001900 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1901 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001902 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1903 wpa_dbg(wpa_s, MSG_DEBUG,
1904 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001905 if (!ssid->ft_eap_pmksa_caching &&
1906 pmksa_cache_get_current(wpa_s->wpa)) {
1907 /* PMKSA caching with FT may have interoperability
1908 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001909 wpa_dbg(wpa_s, MSG_DEBUG,
1910 "WPA: Disable PMKSA caching for FT/802.1X connection");
1911 pmksa_cache_clear_current(wpa_s->wpa);
1912 }
1913#endif /* CONFIG_SHA384 */
1914#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001915#ifdef CONFIG_SUITEB192
1916 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1917 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1918 wpa_dbg(wpa_s, MSG_DEBUG,
1919 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1920#endif /* CONFIG_SUITEB192 */
1921#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001922 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1923 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1924 wpa_dbg(wpa_s, MSG_DEBUG,
1925 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001926#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001927#ifdef CONFIG_SHA384
1928 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1929 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1930 wpa_dbg(wpa_s, MSG_DEBUG,
1931 "WPA: using KEY_MGMT 802.1X with SHA384");
1932#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001933#ifdef CONFIG_FILS
1934#ifdef CONFIG_IEEE80211R
1935 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1936 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1937 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001938#endif /* CONFIG_IEEE80211R */
1939 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1940 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1941 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001942#ifdef CONFIG_IEEE80211R
1943 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1944 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1945 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1946#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001947 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1948 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1949 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1950#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001951#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001952 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1953 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001954 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1955 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001956 if (!ssid->ft_eap_pmksa_caching &&
1957 pmksa_cache_get_current(wpa_s->wpa)) {
1958 /* PMKSA caching with FT may have interoperability
1959 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001960 wpa_dbg(wpa_s, MSG_DEBUG,
1961 "WPA: Disable PMKSA caching for FT/802.1X connection");
1962 pmksa_cache_clear_current(wpa_s->wpa);
1963 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001964#endif /* CONFIG_IEEE80211R */
1965#ifdef CONFIG_DPP
1966 } else if (sel & WPA_KEY_MGMT_DPP) {
1967 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1968 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1969#endif /* CONFIG_DPP */
1970#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001971 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1972 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1973 wpa_dbg(wpa_s, MSG_DEBUG,
1974 "RSN: using KEY_MGMT FT/SAE (ext key)");
1975 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1976 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1977 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001978 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1979 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1980 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1981 } else if (sel & WPA_KEY_MGMT_SAE) {
1982 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1983 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1984#endif /* CONFIG_SAE */
1985#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001986 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1987 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1988 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1989#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1991 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1992 wpa_dbg(wpa_s, MSG_DEBUG,
1993 "WPA: using KEY_MGMT 802.1X with SHA256");
1994 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1995 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1996 wpa_dbg(wpa_s, MSG_DEBUG,
1997 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1999 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
2000 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
2001 } else if (sel & WPA_KEY_MGMT_PSK) {
2002 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
2003 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
2004 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
2005 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
2006 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002007#ifdef CONFIG_HS20
2008 } else if (sel & WPA_KEY_MGMT_OSEN) {
2009 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
2010 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
2011#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002012#ifdef CONFIG_OWE
2013 } else if (sel & WPA_KEY_MGMT_OWE) {
2014 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
2015 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
2016#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017 } else {
2018 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
2019 "authenticated key management type");
2020 return -1;
2021 }
2022
2023 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
2024 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
2025 wpa_s->pairwise_cipher);
2026 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
2027
Hai Shalomc3565922019-10-28 11:58:20 -07002028 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002029 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
2030 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07002031 wpa_msg(wpa_s, MSG_INFO,
2032 "RSN: Management frame protection required but the selected AP does not enable it");
2033 return -1;
2034 }
2035
Hai Shalomc1a21442022-02-04 13:43:00 -08002036 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08002037#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08002038 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
2039 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
2040 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08002041#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07002042 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07002043 if ((ssid->sae_password_id ||
2044 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002045 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
2046 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
2047 if (bss && is_6ghz_freq(bss->freq) &&
2048 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
2049 wpa_dbg(wpa_s, MSG_DEBUG,
2050 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
2051 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08002052 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002053 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07002054#ifdef CONFIG_SAE_PK
2055 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
2056 wpa_key_mgmt_sae(ssid->key_mgmt) &&
2057 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
2058 ((ssid->sae_password &&
2059 sae_pk_valid_password(ssid->sae_password)) ||
2060 (!ssid->sae_password && ssid->passphrase &&
2061 sae_pk_valid_password(ssid->passphrase))));
2062#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002063 if (bss && is_6ghz_freq(bss->freq) &&
2064 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
2065 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
2066 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
2067 MGMT_FRAME_PROTECTION_REQUIRED);
2068 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07002069#ifdef CONFIG_TESTING_OPTIONS
2070 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
2071 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07002072 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
2073 wpa_s->oci_freq_override_eapol);
2074 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
2075 wpa_s->oci_freq_override_eapol_g2);
2076 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
2077 wpa_s->oci_freq_override_ft_assoc);
2078 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
2079 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07002080 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
2081 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07002082#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07002083
2084 /* Extended Key ID is only supported in infrastructure BSS so far */
2085 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
2086 (ssid->proto & WPA_PROTO_RSN) &&
2087 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
2088 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
2089 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
2090 int use_ext_key_id = 0;
2091
2092 wpa_msg(wpa_s, MSG_DEBUG,
2093 "WPA: Enable Extended Key ID support");
2094 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
2095 wpa_s->conf->extended_key_id);
2096 if (bss_rsn &&
2097 wpa_s->conf->extended_key_id &&
2098 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
2099 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
2100 use_ext_key_id = 1;
2101 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
2102 use_ext_key_id);
2103 } else {
2104 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
2105 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
2106 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107
Sunil Ravi640215c2023-06-28 23:08:09 +00002108 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2109 * appropriate advertisement of the supported number of PTKSA receive
2110 * counters. In theory, this could be based on a driver capability, but
2111 * in practice all cases using WMM support at least eight replay
2112 * counters, so use a hardcoded value for now since there is no explicit
2113 * driver capability indication for this.
2114 *
2115 * In addition, claim WMM to be enabled if the AP supports it since it
2116 * is far more likely for any current device to support WMM. */
2117 wmm = wpa_s->connection_set &&
2118 (wpa_s->connection_ht || wpa_s->connection_vht ||
2119 wpa_s->connection_he || wpa_s->connection_eht);
2120 if (!wmm && bss)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002121 wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002122 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2123
Sunil Ravi7f769292024-07-23 22:21:32 +00002124 if (ssid->ssid_protection && proto == WPA_PROTO_RSN) {
2125 bool ssid_prot;
2126
2127 /* Enable SSID protection based on the AP advertising support
2128 * for it to avoid potential interoperability issues with
2129 * incorrect AP behavior if we were to send an "unexpected"
2130 * RSNXE with multiple octets of payload. */
2131 ssid_prot = ieee802_11_rsnx_capab(
2132 bss_rsnx, WLAN_RSNX_CAPAB_SSID_PROTECTION);
2133 if (!skip_default_rsne)
2134 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION,
2135 proto == WPA_PROTO_RSN && ssid_prot);
2136 } else {
2137 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, false);
2138 }
2139
Sunil Ravi77d572f2023-01-17 23:58:31 +00002140 if (!skip_default_rsne) {
2141 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2142 wpa_ie_len)) {
2143 wpa_msg(wpa_s, MSG_WARNING,
2144 "RSN: Failed to generate RSNE/WPA IE");
2145 return -1;
2146 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147
Sunil Ravi77d572f2023-01-17 23:58:31 +00002148 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2149 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2150 &wpa_s->rsnxe_len)) {
2151 wpa_msg(wpa_s, MSG_WARNING,
2152 "RSN: Failed to generate RSNXE");
2153 return -1;
2154 }
Hai Shalomc3565922019-10-28 11:58:20 -07002155 }
2156
Hai Shalom021b0b52019-04-10 11:17:58 -07002157 if (0) {
2158#ifdef CONFIG_DPP
2159 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2160 /* Use PMK from DPP network introduction (PMKSA entry) */
2161 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002162#ifdef CONFIG_DPP2
2163 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2164#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002165#endif /* CONFIG_DPP */
2166 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002167 int psk_set = 0;
2168
Sunil Ravi77d572f2023-01-17 23:58:31 +00002169 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2170 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002171
Sunil Ravi77d572f2023-01-17 23:58:31 +00002172 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2173 psk) == 0) {
2174 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2175 NULL);
2176 psk_set = 1;
2177 }
2178 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002179 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002180
Roshan Pius3a1667e2018-07-03 15:17:14 -07002181 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002182 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002183 psk_set = 1;
2184
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002185 if (!psk_set) {
2186 wpa_msg(wpa_s, MSG_INFO,
2187 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002188 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002189 return -1;
2190 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002191#ifdef CONFIG_OWE
2192 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2193 /* OWE Diffie-Hellman exchange in (Re)Association
2194 * Request/Response frames set the PMK, so do not override it
2195 * here. */
2196#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002197 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002198 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2199
Hai Shalomfdcde762020-04-02 11:19:20 -07002200 if (ssid->mode != WPAS_MODE_IBSS &&
2201 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2202 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2203 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2204 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2205 wpa_msg(wpa_s, MSG_INFO,
2206 "Disable PTK0 rekey support - replaced with reconnect");
2207 wpa_s->deny_ptk0_rekey = 1;
2208 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2209 } else {
2210 wpa_s->deny_ptk0_rekey = 0;
2211 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2212 }
2213
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002214#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2215 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302216 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002217 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2218 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002219 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2220 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302221 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2222 wpa_dbg(wpa_s, MSG_INFO,
2223 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2224 }
Sunil Ravif42be322022-11-04 03:31:21 +00002225#else
2226 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2227 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2228 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002229#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2230 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232 return 0;
2233}
2234
2235
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002236static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2237 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002238{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002239#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002240 bool scs = true, mscs = true;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002241#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08002242
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002243 *pos = 0x00;
2244
2245 switch (idx) {
2246 case 0: /* Bits 0-7 */
2247 break;
2248 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002249 if (wpa_s->conf->coloc_intf_reporting) {
2250 /* Bit 13 - Collocated Interference Reporting */
2251 *pos |= 0x20;
2252 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002253 break;
2254 case 2: /* Bits 16-23 */
2255#ifdef CONFIG_WNM
2256 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002257 if ((wpas_driver_bss_selection(wpa_s) ||
2258 !wpa_s->disable_mbo_oce) &&
2259 !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002260 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002261#endif /* CONFIG_WNM */
2262 break;
2263 case 3: /* Bits 24-31 */
2264#ifdef CONFIG_WNM
2265 *pos |= 0x02; /* Bit 25 - SSID List */
2266#endif /* CONFIG_WNM */
2267#ifdef CONFIG_INTERWORKING
2268 if (wpa_s->conf->interworking)
2269 *pos |= 0x80; /* Bit 31 - Interworking */
2270#endif /* CONFIG_INTERWORKING */
2271 break;
2272 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002273#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002274 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002275 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002276#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002277 break;
2278 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002279#ifdef CONFIG_HS20
2280 if (wpa_s->conf->hs20)
2281 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2282#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002283#ifdef CONFIG_MBO
2284 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2285#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002286 break;
2287 case 6: /* Bits 48-55 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002288#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002289#ifdef CONFIG_TESTING_OPTIONS
2290 if (wpa_s->disable_scs_support)
2291 scs = false;
2292#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002293 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2294 /* Drop own SCS capability indication since the AP does
2295 * not support it. This is needed to avoid
2296 * interoperability issues with APs that get confused
2297 * with Extended Capabilities element. */
2298 scs = false;
2299 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002300 if (scs)
2301 *pos |= 0x40; /* Bit 54 - SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002302#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002303 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002304 case 7: /* Bits 56-63 */
2305 break;
2306 case 8: /* Bits 64-71 */
2307 if (wpa_s->conf->ftm_responder)
2308 *pos |= 0x40; /* Bit 70 - FTM responder */
2309 if (wpa_s->conf->ftm_initiator)
2310 *pos |= 0x80; /* Bit 71 - FTM initiator */
2311 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002312 case 9: /* Bits 72-79 */
2313#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002314 if (!wpa_s->disable_fils)
2315 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002316#endif /* CONFIG_FILS */
2317 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002318 case 10: /* Bits 80-87 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002319#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002320#ifdef CONFIG_TESTING_OPTIONS
2321 if (wpa_s->disable_mscs_support)
2322 mscs = false;
2323#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002324 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2325 /* Drop own MSCS capability indication since the AP does
2326 * not support it. This is needed to avoid
2327 * interoperability issues with APs that get confused
2328 * with Extended Capabilities element. */
2329 mscs = false;
2330 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002331 if (mscs)
2332 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002333#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002334 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002335 }
2336}
2337
2338
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002339int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2340 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002341{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002342 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002343 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002344
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002345 if (len < wpa_s->extended_capa_len)
2346 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002347 if (buflen < (size_t) len + 2) {
2348 wpa_printf(MSG_INFO,
2349 "Not enough room for building extended capabilities element");
2350 return -1;
2351 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002352
2353 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002354 *pos++ = len;
2355 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002356 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002357
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002358 if (i < wpa_s->extended_capa_len) {
2359 *pos &= ~wpa_s->extended_capa_mask[i];
2360 *pos |= wpa_s->extended_capa[i];
2361 }
2362 }
2363
2364 while (len > 0 && buf[1 + len] == 0) {
2365 len--;
2366 buf[1] = len;
2367 }
2368 if (len == 0)
2369 return 0;
2370
2371 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002372}
2373
2374
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002375static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2376 struct wpa_bss *test_bss)
2377{
2378 struct wpa_bss *bss;
2379
2380 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2381 if (bss == test_bss)
2382 return 1;
2383 }
2384
2385 return 0;
2386}
2387
2388
2389static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2390 struct wpa_ssid *test_ssid)
2391{
2392 struct wpa_ssid *ssid;
2393
2394 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2395 if (ssid == test_ssid)
2396 return 1;
2397 }
2398
2399 return 0;
2400}
2401
2402
2403int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2404 struct wpa_ssid *test_ssid)
2405{
2406 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2407 return 0;
2408
2409 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2410}
2411
2412
2413void wpas_connect_work_free(struct wpa_connect_work *cwork)
2414{
2415 if (cwork == NULL)
2416 return;
2417 os_free(cwork);
2418}
2419
2420
2421void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2422{
2423 struct wpa_connect_work *cwork;
2424 struct wpa_radio_work *work = wpa_s->connect_work;
2425
2426 if (!work)
2427 return;
2428
2429 wpa_s->connect_work = NULL;
2430 cwork = work->ctx;
2431 work->ctx = NULL;
2432 wpas_connect_work_free(cwork);
2433 radio_work_done(work);
2434}
2435
2436
Sunil Ravi77d572f2023-01-17 23:58:31 +00002437int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2438 enum wpas_mac_addr_style style,
2439 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002440{
2441 struct os_reltime now;
2442 u8 addr[ETH_ALEN];
2443
2444 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002445 /* Random addresses are valid within a given ESS so check
2446 * expiration/value only when continuing to use the same ESS. */
2447 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2448 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2449 /* Pregenerated addresses do not expire but their value
2450 * might have changed, so let's check that. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002451 if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
Sunil Ravi77d572f2023-01-17 23:58:31 +00002452 return 0;
2453 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2454 wpa_s->last_mac_addr_change.usec != 0) &&
2455 !os_reltime_expired(
2456 &now,
2457 &wpa_s->last_mac_addr_change,
2458 wpa_s->conf->rand_addr_lifetime)) {
2459 wpa_msg(wpa_s, MSG_DEBUG,
2460 "Previously selected random MAC address has not yet expired");
2461 return 0;
2462 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002463 }
2464
2465 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002466 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002467 if (random_mac_addr(addr) < 0)
2468 return -1;
2469 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002470 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002471 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2472 if (random_mac_addr_keep_oui(addr) < 0)
2473 return -1;
2474 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002475 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2476 if (!ssid) {
2477 wpa_msg(wpa_s, MSG_INFO,
2478 "Invalid 'ssid' for address policy 3");
2479 return -1;
2480 }
2481 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2482 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002483 default:
2484 return -1;
2485 }
2486
2487 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2488 wpa_msg(wpa_s, MSG_INFO,
2489 "Failed to set random MAC address");
2490 return -1;
2491 }
2492
2493 os_get_reltime(&wpa_s->last_mac_addr_change);
2494 wpa_s->mac_addr_changed = 1;
2495 wpa_s->last_mac_addr_style = style;
2496
2497 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2498 wpa_msg(wpa_s, MSG_INFO,
2499 "Could not update MAC address information");
2500 return -1;
2501 }
2502
2503 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2504 MAC2STR(addr));
2505
Sunil Ravi77d572f2023-01-17 23:58:31 +00002506 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002507}
2508
2509
2510int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2511{
2512 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2513 !wpa_s->conf->preassoc_mac_addr)
2514 return 0;
2515
Sunil Ravi77d572f2023-01-17 23:58:31 +00002516 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2517 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002518}
2519
2520
Sunil Ravi036cec52023-03-29 11:35:17 -07002521void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2522 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002523{
2524#ifdef CONFIG_SAE
2525 int *groups = conf->sae_groups;
2526 int default_groups[] = { 19, 20, 21, 0 };
2527 const char *password;
2528
2529 if (!groups || groups[0] <= 0)
2530 groups = default_groups;
2531
2532 password = ssid->sae_password;
2533 if (!password)
2534 password = ssid->passphrase;
2535
Hai Shalom899fcc72020-10-19 14:38:18 -07002536 if (!password ||
Sunil Ravi7f769292024-07-23 22:21:32 +00002537 !wpa_key_mgmt_sae(ssid->key_mgmt) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002538 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002539 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002540 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002541 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002542 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002543 /* PT derivation not needed */
2544 sae_deinit_pt(ssid->pt);
2545 ssid->pt = NULL;
2546 return;
2547 }
2548
2549 if (ssid->pt)
2550 return; /* PT already derived */
2551 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2552 (const u8 *) password, os_strlen(password),
2553 ssid->sae_password_id);
2554#endif /* CONFIG_SAE */
2555}
2556
2557
Sunil Ravi7f769292024-07-23 22:21:32 +00002558void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002559{
2560#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2561 os_free(wpa_s->sme.sae_rejected_groups);
2562 wpa_s->sme.sae_rejected_groups = NULL;
2563#ifdef CONFIG_TESTING_OPTIONS
2564 if (wpa_s->extra_sae_rejected_groups) {
2565 int i, *groups = wpa_s->extra_sae_rejected_groups;
2566
2567 for (i = 0; groups[i]; i++) {
2568 wpa_printf(MSG_DEBUG,
2569 "TESTING: Indicate rejection of an extra SAE group %d",
2570 groups[i]);
2571 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2572 groups[i]);
2573 }
2574 }
2575#endif /* CONFIG_TESTING_OPTIONS */
2576#endif /* CONFIG_SAE && CONFIG_SME */
2577}
2578
2579
Hai Shalom60840252021-02-19 19:02:11 -08002580int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2581{
2582 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2583 wpa_msg(wpa_s, MSG_INFO,
2584 "Could not restore permanent MAC address");
2585 return -1;
2586 }
2587 wpa_s->mac_addr_changed = 0;
2588 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2589 wpa_msg(wpa_s, MSG_INFO,
2590 "Could not update MAC address information");
2591 return -1;
2592 }
2593 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2594 return 0;
2595}
2596
2597
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002598static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2599
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600/**
2601 * wpa_supplicant_associate - Request association
2602 * @wpa_s: Pointer to wpa_supplicant data
2603 * @bss: Scan results for the selected BSS, or %NULL if not available
2604 * @ssid: Configuration data for the selected network
2605 *
2606 * This function is used to request %wpa_supplicant to associate with a BSS.
2607 */
2608void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2609 struct wpa_bss *bss, struct wpa_ssid *ssid)
2610{
Sunil Ravi7f769292024-07-23 22:21:32 +00002611 bool clear_rejected = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002612 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002613 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002614
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002615 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002616 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002617
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002618 /*
2619 * If we are starting a new connection, any previously pending EAPOL
2620 * RX cannot be valid anymore.
2621 */
2622 wpabuf_free(wpa_s->pending_eapol_rx);
2623 wpa_s->pending_eapol_rx = NULL;
2624
Sunil Ravi77d572f2023-01-17 23:58:31 +00002625 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002626 rand_style = wpa_s->conf->mac_addr;
2627 else
2628 rand_style = ssid->mac_addr;
2629
Sunil Ravia04bd252022-05-02 22:54:18 -07002630 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002631 wpa_s->multi_ap_ie = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002632#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002633 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002634#endif /* CONFIG_NO_WMM_AC */
2635#ifdef CONFIG_WNM
2636 wpa_s->wnm_mode = 0;
Sunil Ravi99c035e2024-07-12 01:42:03 +00002637 wpa_s->wnm_target_bss = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002638#endif /* CONFIG_WNM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002639 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002640 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002641#ifdef CONFIG_TESTING_OPTIONS
2642 wpa_s->testing_resend_assoc = 0;
2643#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002644
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002645 if (wpa_s->last_ssid == ssid) {
2646 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002647 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002648 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002649#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002650 wmm_ac_save_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002651#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002652 wpa_s->reassoc_same_bss = 1;
Sunil Ravi7f769292024-07-23 22:21:32 +00002653 clear_rejected = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08002654 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2655 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002656 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002657 }
Sunil Ravi7f769292024-07-23 22:21:32 +00002658
2659 if (clear_rejected)
2660 wpa_s_clear_sae_rejected(wpa_s);
2661
Hai Shalomc1a21442022-02-04 13:43:00 -08002662#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002663 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002664#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002665
Sunil Ravi77d572f2023-01-17 23:58:31 +00002666 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2667 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2668
2669 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002670 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002671 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2672 status > 0) /* MAC changed */
2673 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2674 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2675 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002676 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002677 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002678 }
2679 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680
2681#ifdef CONFIG_IBSS_RSN
2682 ibss_rsn_deinit(wpa_s->ibss_rsn);
2683 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002684#else /* CONFIG_IBSS_RSN */
2685 if (ssid->mode == WPAS_MODE_IBSS &&
2686 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2687 wpa_msg(wpa_s, MSG_INFO,
2688 "IBSS RSN not supported in the build");
2689 return;
2690 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691#endif /* CONFIG_IBSS_RSN */
2692
2693 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2694 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2695#ifdef CONFIG_AP
2696 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2697 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2698 "mode");
2699 return;
2700 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002701 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2702 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302703 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2704 ssid->mode == WPAS_MODE_P2P_GO) {
2705 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002706 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302707 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002708 return;
2709 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 wpa_s->current_bss = bss;
2711#else /* CONFIG_AP */
2712 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2713 "the build");
2714#endif /* CONFIG_AP */
2715 return;
2716 }
2717
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002718 if (ssid->mode == WPAS_MODE_MESH) {
2719#ifdef CONFIG_MESH
2720 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2721 wpa_msg(wpa_s, MSG_INFO,
2722 "Driver does not support mesh mode");
2723 return;
2724 }
2725 if (bss)
2726 ssid->frequency = bss->freq;
2727 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002728 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002729 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2730 return;
2731 }
2732 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002733#else /* CONFIG_MESH */
2734 wpa_msg(wpa_s, MSG_ERROR,
2735 "mesh mode support not included in the build");
2736#endif /* CONFIG_MESH */
2737 return;
2738 }
2739
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002740 /*
2741 * Set WPA state machine configuration to match the selected network now
2742 * so that the information is available before wpas_start_assoc_cb()
2743 * gets called. This is needed at least for RSN pre-authentication where
2744 * candidate APs are added to a list based on scan result processing
2745 * before completion of the first association.
2746 */
2747 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2748
2749#ifdef CONFIG_DPP
2750 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2751 return;
2752#endif /* CONFIG_DPP */
2753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754#ifdef CONFIG_TDLS
2755 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002756 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757#endif /* CONFIG_TDLS */
2758
Hai Shalomc3565922019-10-28 11:58:20 -07002759#ifdef CONFIG_MBO
2760 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2761#endif /* CONFIG_MBO */
2762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002764 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 sme_authenticate(wpa_s, bss, ssid);
2766 return;
2767 }
2768
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002769 if (wpa_s->connect_work) {
2770 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2771 return;
2772 }
2773
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002774 if (radio_work_pending(wpa_s, "connect")) {
2775 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2776 return;
2777 }
2778
Dmitry Shmidt29333592017-01-09 12:27:11 -08002779#ifdef CONFIG_SME
2780 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2781 /* Clear possibly set auth_alg, if any, from last attempt. */
2782 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2783 }
2784#endif /* CONFIG_SME */
2785
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002786 wpas_abort_ongoing_scan(wpa_s);
2787
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002788 cwork = os_zalloc(sizeof(*cwork));
2789 if (cwork == NULL)
2790 return;
2791
2792 cwork->bss = bss;
2793 cwork->ssid = ssid;
2794
2795 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2796 wpas_start_assoc_cb, cwork) < 0) {
2797 os_free(cwork);
2798 }
2799}
2800
2801
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002802static int bss_is_ibss(struct wpa_bss *bss)
2803{
2804 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2805 IEEE80211_CAP_IBSS;
2806}
2807
2808
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002809static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2810 const struct wpa_ssid *ssid)
2811{
2812 enum hostapd_hw_mode hw_mode;
2813 struct hostapd_hw_modes *mode = NULL;
2814 u8 channel;
2815 int i;
2816
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002817 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2818 if (hw_mode == NUM_HOSTAPD_MODES)
2819 return 0;
2820 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2821 if (wpa_s->hw.modes[i].mode == hw_mode) {
2822 mode = &wpa_s->hw.modes[i];
2823 break;
2824 }
2825 }
2826
2827 if (!mode)
2828 return 0;
2829
2830 return mode->vht_capab != 0;
2831}
2832
2833
Hai Shalomc1a21442022-02-04 13:43:00 -08002834static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2835{
2836 int i;
2837
2838 for (i = channel; i < channel + 16; i += 4) {
2839 struct hostapd_channel_data *chan;
2840
2841 chan = hw_get_channel_chan(mode, i, NULL);
2842 if (!chan ||
2843 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2844 return false;
2845 }
2846
2847 return true;
2848}
2849
2850
Sunil Ravi036cec52023-03-29 11:35:17 -07002851static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2852 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002853{
Sunil Ravi036cec52023-03-29 11:35:17 -07002854 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002855
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002856 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2857 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2858
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002859 if (!bss_is_ibss(bss))
2860 continue;
2861
2862 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002863 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2864 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002865 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002866 return NULL;
2867}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002868
Sunil Ravi036cec52023-03-29 11:35:17 -07002869
2870static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2871 const struct wpa_ssid *ssid,
2872 struct hostapd_hw_modes *mode)
2873{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002874 /* For IBSS check HT_IBSS flag */
2875 if (ssid->mode == WPAS_MODE_IBSS &&
2876 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002877 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002878
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002879 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2880 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2881 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2882 wpa_printf(MSG_DEBUG,
2883 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002884 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002885 }
2886
Sunil Ravi036cec52023-03-29 11:35:17 -07002887 if (!ht_supported(mode))
2888 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002889
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002890#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002891 if (ssid->disable_ht)
2892 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002893#endif /* CONFIG_HT_OVERRIDES */
2894
Sunil Ravi036cec52023-03-29 11:35:17 -07002895 return true;
2896}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002897
Sunil Ravi036cec52023-03-29 11:35:17 -07002898
2899static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2900 const struct wpa_ssid *ssid,
2901 struct hostapd_hw_modes *mode)
2902{
2903 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2904 return false;
2905
2906 if (!drv_supports_vht(wpa_s, ssid))
2907 return false;
2908
2909 /* For IBSS check VHT_IBSS flag */
2910 if (ssid->mode == WPAS_MODE_IBSS &&
2911 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2912 return false;
2913
2914 if (!vht_supported(mode))
2915 return false;
2916
2917#ifdef CONFIG_VHT_OVERRIDES
2918 if (ssid->disable_vht)
2919 return false;
2920#endif /* CONFIG_VHT_OVERRIDES */
2921
2922 return true;
2923}
2924
2925
2926static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2927 const struct wpa_ssid *ssid,
2928 const struct hostapd_hw_modes *mode,
2929 int ieee80211_mode)
2930{
Hai Shalomfdcde762020-04-02 11:19:20 -07002931#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002932 if (ssid->disable_he)
2933 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002934#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002935
Sunil Ravi036cec52023-03-29 11:35:17 -07002936 switch (mode->mode) {
2937 case HOSTAPD_MODE_IEEE80211G:
2938 case HOSTAPD_MODE_IEEE80211B:
2939 case HOSTAPD_MODE_IEEE80211A:
2940 return mode->he_capab[ieee80211_mode].he_supported;
2941 default:
2942 return false;
2943 }
2944}
2945
2946
2947static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2948 const struct wpa_ssid *ssid,
2949 const struct hostapd_hw_modes *mode,
2950 int ieee80211_mode)
2951{
2952 if (ssid->disable_eht)
2953 return false;
2954
2955 switch(mode->mode) {
2956 case HOSTAPD_MODE_IEEE80211G:
2957 case HOSTAPD_MODE_IEEE80211B:
2958 case HOSTAPD_MODE_IEEE80211A:
2959 return mode->eht_capab[ieee80211_mode].eht_supported;
2960 default:
2961 return false;
2962 }
2963}
2964
2965
2966static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2967 const struct wpa_ssid *ssid,
2968 struct hostapd_hw_modes *mode,
2969 struct hostapd_freq_params *freq,
2970 int obss_scan) {
2971 int chan_idx;
2972 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2973 int i, res;
2974 unsigned int j;
2975 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002976 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2977 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002978 };
2979 int ht40 = -1;
2980
2981 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002982 return;
2983
2984 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2985 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002986 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002987 break;
2988 pri_chan = NULL;
2989 }
2990 if (!pri_chan)
2991 return;
2992
2993 /* Check primary channel flags */
2994 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2995 return;
2996
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002997#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002998 if (ssid->disable_ht40)
2999 return;
3000#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003001
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003002 /* Check/setup HT40+/HT40- */
3003 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07003004 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003005 ht40 = 1;
3006 break;
3007 }
3008 }
3009
3010 /* Find secondary channel */
3011 for (i = 0; i < mode->num_channels; i++) {
3012 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07003013 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003014 break;
3015 sec_chan = NULL;
3016 }
3017 if (!sec_chan)
3018 return;
3019
3020 /* Check secondary channel flags */
3021 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
3022 return;
3023
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003024 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003025 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
3026 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003027 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003028 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
3029 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003030 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003031 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003032
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003033 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003034 struct wpa_scan_results *scan_res;
3035
Sunil Ravi99c035e2024-07-12 01:42:03 +00003036 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
3037 NULL);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003038 if (scan_res == NULL) {
3039 /* Back to HT20 */
3040 freq->sec_channel_offset = 0;
3041 return;
3042 }
3043
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003044 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003045 switch (res) {
3046 case 0:
3047 /* Back to HT20 */
3048 freq->sec_channel_offset = 0;
3049 break;
3050 case 1:
3051 /* Configuration allowed */
3052 break;
3053 case 2:
3054 /* Switch pri/sec channels */
3055 freq->freq = hw_get_freq(mode, sec_chan->chan);
3056 freq->sec_channel_offset = -freq->sec_channel_offset;
3057 freq->channel = sec_chan->chan;
3058 break;
3059 default:
3060 freq->sec_channel_offset = 0;
3061 break;
3062 }
3063
3064 wpa_scan_results_free(scan_res);
3065 }
3066
3067 wpa_printf(MSG_DEBUG,
3068 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
3069 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07003070}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003071
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003072
Sunil Ravi036cec52023-03-29 11:35:17 -07003073static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
3074 const struct wpa_ssid *ssid,
3075 struct hostapd_hw_modes *mode,
3076 struct hostapd_freq_params *freq,
3077 int ieee80211_mode, bool is_6ghz) {
3078 static const int bw80[] = {
3079 5180, 5260, 5500, 5580, 5660, 5745, 5825,
3080 5955, 6035, 6115, 6195, 6275, 6355, 6435,
3081 6515, 6595, 6675, 6755, 6835, 6915, 6995
3082 };
3083 static const int bw160[] = {
3084 5955, 6115, 6275, 6435, 6595, 6755, 6915
3085 };
3086 struct hostapd_freq_params vht_freq;
3087 int i;
3088 unsigned int j, k;
3089 int chwidth, seg0, seg1;
3090 u32 vht_caps = 0;
3091 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003092
Sunil Ravi036cec52023-03-29 11:35:17 -07003093 if (!freq->vht_enabled && !freq->he_enabled)
3094 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08003095
Hai Shalomc1a21442022-02-04 13:43:00 -08003096 vht_freq = *freq;
3097
Sunil Ravi036cec52023-03-29 11:35:17 -07003098 chwidth = CONF_OPER_CHWIDTH_USE_HT;
3099 seg0 = freq->channel + 2 * freq->sec_channel_offset;
3100 seg1 = 0;
3101 if (freq->sec_channel_offset == 0) {
3102 seg0 = 0;
3103 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
3104 if (freq->ht_enabled && !is_6ghz)
3105 goto skip_80mhz;
3106 }
3107 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
3108 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07003109
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003110 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003111 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
3112 if (freq->freq >= bw80[j] &&
3113 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003114 break;
3115 }
3116
Hai Shalomc1a21442022-02-04 13:43:00 -08003117 if (j == ARRAY_SIZE(bw80) ||
3118 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003119 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003120
Sunil Ravi036cec52023-03-29 11:35:17 -07003121 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08003122 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07003123 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003124
Sunil8cd6f4d2022-06-28 18:40:46 +00003125 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003126 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003127 seg1 = 0;
3128
Sunil Ravi036cec52023-03-29 11:35:17 -07003129 /* In 160 MHz, the initial four 20 MHz channels were validated
3130 * above. If 160 MHz is supported, check the remaining four 20 MHz
3131 * channels for the total of 160 MHz bandwidth for 6 GHz.
3132 */
Hai Shalomc1a21442022-02-04 13:43:00 -08003133 if ((mode->he_capab[ieee80211_mode].phy_cap[
3134 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07003135 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
3136 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003137 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
3138 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003139 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003140 seg0 = channel + 14;
3141 break;
3142 }
3143 }
3144 }
3145
Sunil8cd6f4d2022-06-28 18:40:46 +00003146 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003147 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003148 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003149 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003150 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003151 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003152
3153 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3154 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003155 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003156
3157 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003158 struct hostapd_channel_data *chan;
3159
3160 chan = hw_get_channel_chan(mode, i, NULL);
3161 if (!chan)
3162 continue;
3163
3164 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3165 HOSTAPD_CHAN_NO_IR |
3166 HOSTAPD_CHAN_RADAR))
3167 continue;
3168
3169 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003170 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003171 if (!is_6ghz)
3172 vht_caps |=
3173 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3174 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003175 }
3176
Sunil8cd6f4d2022-06-28 18:40:46 +00003177 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003178 break;
3179 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003180 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003181 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003182 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003183 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3184 seg0 = 50;
3185 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003186 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003187 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3188 seg0 = 114;
3189 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003190 }
3191
Sunil Ravi036cec52023-03-29 11:35:17 -07003192skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003193 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003194 freq->channel, ssid->enable_edmg,
3195 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003196 freq->vht_enabled, freq->he_enabled,
3197 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003198 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003199 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003200 &mode->he_capab[ieee80211_mode],
Sunil Ravi99c035e2024-07-12 01:42:03 +00003201 &mode->eht_capab[ieee80211_mode], 0) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003202 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003203
3204 *freq = vht_freq;
3205
3206 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3207 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003208 return true;
3209}
3210
3211
3212void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3213 const struct wpa_ssid *ssid,
3214 struct hostapd_freq_params *freq)
3215{
3216 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3217 enum hostapd_hw_mode hw_mode;
3218 struct hostapd_hw_modes *mode = NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +00003219 int obss_scan = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -07003220 u8 channel;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003221 bool is_6ghz, is_24ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003222
3223 freq->freq = ssid->frequency;
3224
3225 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3226 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3227
3228 if (bss) {
3229 wpa_printf(MSG_DEBUG,
3230 "IBSS already found in scan results, adjust control freq: %d",
3231 bss->freq);
3232 freq->freq = bss->freq;
3233 obss_scan = 0;
3234 }
3235 }
3236
3237 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Sunil Ravi7f769292024-07-23 22:21:32 +00003238 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3239 hw_mode, is_6ghz_freq(ssid->frequency));
Sunil Ravi036cec52023-03-29 11:35:17 -07003240
3241 if (!mode)
3242 return;
3243
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003244 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
3245 hw_mode == HOSTAPD_MODE_IEEE80211B;
3246
Sunil Ravi036cec52023-03-29 11:35:17 -07003247 is_6ghz = is_6ghz_freq(freq->freq);
3248
3249 freq->ht_enabled = 0;
3250 freq->vht_enabled = 0;
3251 freq->he_enabled = 0;
3252 freq->eht_enabled = 0;
3253
3254 if (!is_6ghz)
3255 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3256 if (freq->ht_enabled)
3257 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003258 if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003259 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3260 ieee80211_mode);
3261 freq->channel = channel;
3262 /* Setup higher BW only for 5 GHz */
3263 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3264 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3265 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3266 ieee80211_mode, is_6ghz))
3267 freq->he_enabled = freq->vht_enabled = false;
3268 }
3269
3270 if (freq->he_enabled)
3271 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3272 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003273}
3274
3275
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003276#ifdef CONFIG_FILS
3277static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3278 size_t ie_buf_len)
3279{
3280 struct fils_hlp_req *req;
3281 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3282 const u8 *pos;
3283 u8 *buf = ie_buf;
3284
3285 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3286 list) {
3287 rem_len = ie_buf_len - ie_len;
3288 pos = wpabuf_head(req->pkt);
3289 hdr_len = 1 + 2 * ETH_ALEN + 6;
3290 hlp_len = wpabuf_len(req->pkt);
3291
3292 if (rem_len < 2 + hdr_len + hlp_len) {
3293 wpa_printf(MSG_ERROR,
3294 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3295 (unsigned long) rem_len,
3296 (unsigned long) (2 + hdr_len + hlp_len));
3297 break;
3298 }
3299
3300 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3301 /* Element ID */
3302 *buf++ = WLAN_EID_EXTENSION;
3303 /* Length */
3304 *buf++ = len;
3305 /* Element ID Extension */
3306 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3307 /* Destination MAC address */
3308 os_memcpy(buf, req->dst, ETH_ALEN);
3309 buf += ETH_ALEN;
3310 /* Source MAC address */
3311 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3312 buf += ETH_ALEN;
3313 /* LLC/SNAP Header */
3314 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3315 buf += 6;
3316 /* HLP Packet */
3317 os_memcpy(buf, pos, len - hdr_len);
3318 buf += len - hdr_len;
3319 pos += len - hdr_len;
3320
3321 hlp_len -= len - hdr_len;
3322 ie_len += 2 + len;
3323 rem_len -= 2 + len;
3324
3325 while (hlp_len) {
3326 len = (hlp_len > 255) ? 255 : hlp_len;
3327 if (rem_len < 2 + len)
3328 break;
3329 *buf++ = WLAN_EID_FRAGMENT;
3330 *buf++ = len;
3331 os_memcpy(buf, pos, len);
3332 buf += len;
3333 pos += len;
3334
3335 hlp_len -= len;
3336 ie_len += 2 + len;
3337 rem_len -= 2 + len;
3338 }
3339 }
3340
3341 return ie_len;
3342}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003343
3344
3345int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3346{
3347 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3348 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3349 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3350 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3351}
3352
3353
3354int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3355{
3356#ifdef CONFIG_FILS_SK_PFS
3357 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3358 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3359#else /* CONFIG_FILS_SK_PFS */
3360 return 0;
3361#endif /* CONFIG_FILS_SK_PFS */
3362}
3363
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003364#endif /* CONFIG_FILS */
3365
3366
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003367bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3368{
3369 const u8 *wfa_capa;
3370
3371 if (!bss)
3372 return false;
3373
3374 /* Get WFA capability from Beacon or Probe Response frame elements */
3375 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3376 if (!wfa_capa)
3377 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3378 bss, WFA_CAPA_IE_VENDOR_TYPE);
3379
3380 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3381 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3382 /* AP does not enable QM non EHT traffic description policy */
3383 return false;
3384 }
3385
3386 return true;
3387}
3388
3389
Hai Shalomc1a21442022-02-04 13:43:00 -08003390static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3391 struct wpa_bss *bss,
3392 u8 *wpa_ie, size_t wpa_ie_len,
3393 size_t max_wpa_ie_len)
3394{
3395 struct wpabuf *wfa_ie = NULL;
3396 u8 wfa_capa[1];
3397 size_t wfa_ie_len, buf_len;
3398
3399 os_memset(wfa_capa, 0, sizeof(wfa_capa));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003400#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003401 if (wpa_s->enable_dscp_policy_capa)
3402 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003403#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003404
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003405 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3406 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3407
Hai Shalomc1a21442022-02-04 13:43:00 -08003408 if (!wfa_capa[0])
3409 return wpa_ie_len;
3410
3411 /* Wi-Fi Alliance element */
3412 buf_len = 1 + /* Element ID */
3413 1 + /* Length */
3414 3 + /* OUI */
3415 1 + /* OUI Type */
3416 1 + /* Capabilities Length */
3417 sizeof(wfa_capa); /* Capabilities */
3418 wfa_ie = wpabuf_alloc(buf_len);
3419 if (!wfa_ie)
3420 return wpa_ie_len;
3421
3422 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3423 wpabuf_put_u8(wfa_ie, buf_len - 2);
3424 wpabuf_put_be24(wfa_ie, OUI_WFA);
3425 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3426 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3427 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3428
3429 wfa_ie_len = wpabuf_len(wfa_ie);
3430 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3431 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3432 wfa_ie);
3433 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3434 wfa_ie_len);
3435 wpa_ie_len += wfa_ie_len;
3436 }
3437
3438 wpabuf_free(wfa_ie);
3439 return wpa_ie_len;
3440}
3441
3442
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003443static u8 * wpas_populate_assoc_ies(
3444 struct wpa_supplicant *wpa_s,
3445 struct wpa_bss *bss, struct wpa_ssid *ssid,
3446 struct wpa_driver_associate_params *params,
3447 enum wpa_drv_update_connect_params_mask *mask)
3448{
3449 u8 *wpa_ie;
3450 size_t max_wpa_ie_len = 500;
3451 size_t wpa_ie_len;
3452 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003453#ifdef CONFIG_MBO
3454 const u8 *mbo_ie;
3455#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303456#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3457 int pmksa_cached = 0;
3458#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003459#ifdef CONFIG_FILS
3460 const u8 *realm, *username, *rrk;
3461 size_t realm_len, username_len, rrk_len;
3462 u16 next_seq_num;
3463 struct fils_hlp_req *req;
3464
3465 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3466 list) {
3467 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3468 2 + 2 * wpabuf_len(req->pkt) / 255;
3469 }
3470#endif /* CONFIG_FILS */
3471
3472 wpa_ie = os_malloc(max_wpa_ie_len);
3473 if (!wpa_ie) {
3474 wpa_printf(MSG_ERROR,
3475 "Failed to allocate connect IE buffer for %lu bytes",
3476 (unsigned long) max_wpa_ie_len);
3477 return NULL;
3478 }
3479
3480 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
Sunil Ravi7f769292024-07-23 22:21:32 +00003481 wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003482 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3483 int try_opportunistic;
3484 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003485 const u8 *addr = bss->bssid;
3486
Sunil Ravi036cec52023-03-29 11:35:17 -07003487 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3488 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3489 !is_zero_ether_addr(bss->mld_addr))
3490 addr = bss->mld_addr;
3491
3492 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3493 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003494 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003495
3496 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3497 wpa_s->conf->okc :
3498 ssid->proactive_key_caching) &&
3499 (ssid->proto & WPA_PROTO_RSN);
3500#ifdef CONFIG_FILS
3501 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3502 cache_id = wpa_bss_get_fils_cache_id(bss);
3503#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003504 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003505 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003506 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003507 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303508#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3509 pmksa_cached = 1;
3510#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003511 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003512 wpa_ie_len = max_wpa_ie_len;
3513 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003514 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003515 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3516 "key management and encryption suites");
3517 os_free(wpa_ie);
3518 return NULL;
3519 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003520#ifdef CONFIG_HS20
3521 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3522 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3523 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3524 wpa_ie_len = max_wpa_ie_len;
3525 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003526 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003527 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3528 "key management and encryption suites");
3529 os_free(wpa_ie);
3530 return NULL;
3531 }
3532#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003533 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3534 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3535 /*
3536 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3537 * use non-WPA since the scan results did not indicate that the
3538 * AP is using WPA or WPA2.
3539 */
3540 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3541 wpa_ie_len = 0;
3542 wpa_s->wpa_proto = 0;
3543 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3544 wpa_ie_len = max_wpa_ie_len;
3545 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003546 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003547 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3548 "key management and encryption suites (no "
3549 "scan results)");
3550 os_free(wpa_ie);
3551 return NULL;
3552 }
3553#ifdef CONFIG_WPS
3554 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3555 struct wpabuf *wps_ie;
3556 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3557 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3558 wpa_ie_len = wpabuf_len(wps_ie);
3559 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3560 } else
3561 wpa_ie_len = 0;
3562 wpabuf_free(wps_ie);
3563 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3564 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3565 params->wps = WPS_MODE_PRIVACY;
3566 else
3567 params->wps = WPS_MODE_OPEN;
3568 wpa_s->wpa_proto = 0;
3569#endif /* CONFIG_WPS */
3570 } else {
3571 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3572 wpa_ie_len = 0;
3573 wpa_s->wpa_proto = 0;
3574 }
3575
3576#ifdef IEEE8021X_EAPOL
3577 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3578 if (ssid->leap) {
3579 if (ssid->non_leap == 0)
3580 algs = WPA_AUTH_ALG_LEAP;
3581 else
3582 algs |= WPA_AUTH_ALG_LEAP;
3583 }
3584 }
3585
3586#ifdef CONFIG_FILS
3587 /* Clear FILS association */
3588 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3589
3590 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3591 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3592 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3593 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003594 &next_seq_num, &rrk, &rrk_len) == 0 &&
3595 (!wpa_s->last_con_fail_realm ||
3596 wpa_s->last_con_fail_realm_len != realm_len ||
3597 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003598 algs = WPA_AUTH_ALG_FILS;
3599 params->fils_erp_username = username;
3600 params->fils_erp_username_len = username_len;
3601 params->fils_erp_realm = realm;
3602 params->fils_erp_realm_len = realm_len;
3603 params->fils_erp_next_seq_num = next_seq_num;
3604 params->fils_erp_rrk = rrk;
3605 params->fils_erp_rrk_len = rrk_len;
3606
3607 if (mask)
3608 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303609 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3610 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3611 pmksa_cached) {
3612 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003613 }
3614#endif /* CONFIG_FILS */
3615#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003616#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003617 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003618 algs = WPA_AUTH_ALG_SAE;
3619#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620
3621 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3622 if (ssid->auth_alg) {
3623 algs = ssid->auth_alg;
3624 wpa_dbg(wpa_s, MSG_DEBUG,
3625 "Overriding auth_alg selection: 0x%x", algs);
3626 }
3627
Hai Shalom5f92bc92019-04-18 11:54:11 -07003628#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303629 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003630 wpa_dbg(wpa_s, MSG_DEBUG,
3631 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3632 algs = WPA_AUTH_ALG_OPEN;
3633 }
3634#endif /* CONFIG_SAE */
3635
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003636#ifdef CONFIG_P2P
3637 if (wpa_s->global->p2p) {
3638 u8 *pos;
3639 size_t len;
3640 int res;
3641 pos = wpa_ie + wpa_ie_len;
3642 len = max_wpa_ie_len - wpa_ie_len;
3643 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3644 ssid->p2p_group);
3645 if (res >= 0)
3646 wpa_ie_len += res;
3647 }
3648
3649 wpa_s->cross_connect_disallowed = 0;
3650 if (bss) {
3651 struct wpabuf *p2p;
3652 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3653 if (p2p) {
3654 wpa_s->cross_connect_disallowed =
3655 p2p_get_cross_connect_disallowed(p2p);
3656 wpabuf_free(p2p);
3657 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3658 "connection",
3659 wpa_s->cross_connect_disallowed ?
3660 "disallows" : "allows");
3661 }
3662 }
3663
3664 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3665#endif /* CONFIG_P2P */
3666
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003667#ifndef CONFIG_NO_RRM
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003668 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003669 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003670 wpa_ie + wpa_ie_len,
3671 max_wpa_ie_len -
3672 wpa_ie_len);
3673 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003674#endif /* CONFIG_NO_RRM */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003675
3676 /*
3677 * Workaround: Add Extended Capabilities element only if the AP
3678 * included this element in Beacon/Probe Response frames. Some older
3679 * APs seem to have interoperability issues if this element is
3680 * included, so while the standard may require us to include the
3681 * element in all cases, it is justifiable to skip it to avoid
3682 * interoperability issues.
3683 */
3684 if (ssid->p2p_group)
3685 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3686 else
3687 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3688
3689 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3690 u8 ext_capab[18];
3691 int ext_capab_len;
3692 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003693 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003694 if (ext_capab_len > 0 &&
3695 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3696 u8 *pos = wpa_ie;
3697 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3698 pos += 2 + pos[1];
3699 os_memmove(pos + ext_capab_len, pos,
3700 wpa_ie_len - (pos - wpa_ie));
3701 wpa_ie_len += ext_capab_len;
3702 os_memcpy(pos, ext_capab, ext_capab_len);
3703 }
3704 }
3705
Sunil Ravi7f769292024-07-23 22:21:32 +00003706 if (ssid->max_idle && wpa_ie_len + 5 <= max_wpa_ie_len) {
3707 u8 *pos = wpa_ie;
3708
3709 *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
3710 *pos++ = 3;
3711 WPA_PUT_LE16(pos, ssid->max_idle);
3712 pos += 2;
3713 *pos = 0; /* Idle Options */
3714 wpa_ie_len += 5;
3715 }
3716
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003717#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003718 if (is_hs20_network(wpa_s, ssid, bss)
3719#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3720 && is_hs20_config(wpa_s)
3721#endif /* ANDROID */
3722 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003723 struct wpabuf *hs20;
3724
Roshan Pius3a1667e2018-07-03 15:17:14 -07003725 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003726 if (hs20) {
3727 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3728 size_t len;
3729
Hai Shalom74f70d42019-02-11 14:42:39 -08003730 wpas_hs20_add_indication(hs20, pps_mo_id,
3731 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003732 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003733 len = max_wpa_ie_len - wpa_ie_len;
3734 if (wpabuf_len(hs20) <= len) {
3735 os_memcpy(wpa_ie + wpa_ie_len,
3736 wpabuf_head(hs20), wpabuf_len(hs20));
3737 wpa_ie_len += wpabuf_len(hs20);
3738 }
3739 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003740 }
3741 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003742 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003743#endif /* CONFIG_HS20 */
3744
3745 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3746 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3747 size_t len;
3748
3749 len = max_wpa_ie_len - wpa_ie_len;
3750 if (wpabuf_len(buf) <= len) {
3751 os_memcpy(wpa_ie + wpa_ie_len,
3752 wpabuf_head(buf), wpabuf_len(buf));
3753 wpa_ie_len += wpabuf_len(buf);
3754 }
3755 }
3756
3757#ifdef CONFIG_FST
3758 if (wpa_s->fst_ies) {
3759 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3760
3761 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3762 os_memcpy(wpa_ie + wpa_ie_len,
3763 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3764 wpa_ie_len += fst_ies_len;
3765 }
3766 }
3767#endif /* CONFIG_FST */
3768
3769#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003770 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003771 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003772 int len;
3773
3774 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003775 max_wpa_ie_len - wpa_ie_len,
3776 !!mbo_attr_from_mbo_ie(mbo_ie,
3777 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003778 if (len >= 0)
3779 wpa_ie_len += len;
3780 }
3781#endif /* CONFIG_MBO */
3782
3783#ifdef CONFIG_FILS
3784 if (algs == WPA_AUTH_ALG_FILS) {
3785 size_t len;
3786
3787 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3788 max_wpa_ie_len - wpa_ie_len);
3789 wpa_ie_len += len;
3790 }
3791#endif /* CONFIG_FILS */
3792
3793#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003794#ifdef CONFIG_TESTING_OPTIONS
3795 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3796 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3797 } else
3798#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003799 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003800 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3801 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003802 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003803 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003804
Roshan Pius3a1667e2018-07-03 15:17:14 -07003805 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003806 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003807 } else if (wpa_s->assoc_status_code ==
3808 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003809 if (wpa_s->last_owe_group == 19)
3810 group = 20;
3811 else if (wpa_s->last_owe_group == 20)
3812 group = 21;
3813 else
3814 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003815 } else {
3816 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003817 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003818
Roshan Pius3a1667e2018-07-03 15:17:14 -07003819 wpa_s->last_owe_group = group;
3820 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003821 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3822 if (owe_ie &&
3823 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3824 os_memcpy(wpa_ie + wpa_ie_len,
3825 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3826 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003827 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003828 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003829 }
3830#endif /* CONFIG_OWE */
3831
Hai Shalom021b0b52019-04-10 11:17:58 -07003832#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003833 if (DPP_VERSION > 1 &&
3834 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003835 ssid->dpp_netaccesskey &&
3836 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003837 struct rsn_pmksa_cache_entry *pmksa;
3838
3839 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3840 if (!pmksa || !pmksa->dpp_pfs)
3841 goto pfs_fail;
3842
Hai Shalom021b0b52019-04-10 11:17:58 -07003843 dpp_pfs_free(wpa_s->dpp_pfs);
3844 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3845 ssid->dpp_netaccesskey_len);
3846 if (!wpa_s->dpp_pfs) {
3847 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3848 /* Try to continue without PFS */
3849 goto pfs_fail;
3850 }
3851 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3852 max_wpa_ie_len - wpa_ie_len) {
3853 os_memcpy(wpa_ie + wpa_ie_len,
3854 wpabuf_head(wpa_s->dpp_pfs->ie),
3855 wpabuf_len(wpa_s->dpp_pfs->ie));
3856 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3857 }
3858 }
3859pfs_fail:
3860#endif /* CONFIG_DPP2 */
3861
Roshan Pius3a1667e2018-07-03 15:17:14 -07003862#ifdef CONFIG_IEEE80211R
3863 /*
3864 * Add MDIE under these conditions: the network profile allows FT,
3865 * the AP supports FT, and the mobility domain ID matches.
3866 */
3867 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3868 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3869
3870 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3871 size_t len = 0;
3872 const u8 *md = mdie + 2;
3873 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3874
3875 if (os_memcmp(md, wpa_md,
3876 MOBILITY_DOMAIN_ID_LEN) == 0) {
3877 /* Add mobility domain IE */
3878 len = wpa_ft_add_mdie(
3879 wpa_s->wpa, wpa_ie + wpa_ie_len,
3880 max_wpa_ie_len - wpa_ie_len, mdie);
3881 wpa_ie_len += len;
3882 }
3883#ifdef CONFIG_SME
3884 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003885 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003886 wpa_dbg(wpa_s, MSG_DEBUG,
3887 "SME: Trying to use FT over-the-air");
3888 algs |= WPA_AUTH_ALG_FT;
3889 }
3890#endif /* CONFIG_SME */
3891 }
3892 }
3893#endif /* CONFIG_IEEE80211R */
3894
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003895#ifdef CONFIG_TESTING_OPTIONS
3896 if (wpa_s->rsnxe_override_assoc &&
3897 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3898 max_wpa_ie_len - wpa_ie_len) {
3899 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3900 os_memcpy(wpa_ie + wpa_ie_len,
3901 wpabuf_head(wpa_s->rsnxe_override_assoc),
3902 wpabuf_len(wpa_s->rsnxe_override_assoc));
3903 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3904 } else
3905#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003906 if (wpa_s->rsnxe_len > 0 &&
3907 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3908 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3909 wpa_ie_len += wpa_s->rsnxe_len;
3910 }
3911
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003912#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003913#ifdef CONFIG_TESTING_OPTIONS
3914 if (wpa_s->disable_mscs_support)
3915 goto mscs_end;
3916#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003917 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3918 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003919 struct wpabuf *mscs_ie;
3920 size_t mscs_ie_len, buf_len;
3921
Hai Shalom899fcc72020-10-19 14:38:18 -07003922 buf_len = 3 + /* MSCS descriptor IE header */
3923 1 + /* Request type */
3924 2 + /* User priority control */
3925 4 + /* Stream timeout */
3926 3 + /* TCLAS Mask IE header */
3927 wpa_s->robust_av.frame_classifier_len;
3928 mscs_ie = wpabuf_alloc(buf_len);
3929 if (!mscs_ie) {
3930 wpa_printf(MSG_INFO,
3931 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003932 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003933 }
3934
3935 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3936 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3937 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3938 mscs_ie_len = wpabuf_len(mscs_ie);
3939 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3940 mscs_ie_len);
3941 wpa_ie_len += mscs_ie_len;
3942 }
3943
3944 wpabuf_free(mscs_ie);
3945 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003946mscs_end:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003947#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003948
3949 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3950 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003951
Hai Shalom74f70d42019-02-11 14:42:39 -08003952 if (ssid->multi_ap_backhaul_sta) {
3953 size_t multi_ap_ie_len;
Sunil Ravi99c035e2024-07-12 01:42:03 +00003954 struct multi_ap_params multi_ap = { 0 };
3955
3956 multi_ap.capability = MULTI_AP_BACKHAUL_STA;
3957 multi_ap.profile = ssid->multi_ap_profile;
Hai Shalom74f70d42019-02-11 14:42:39 -08003958
3959 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3960 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi99c035e2024-07-12 01:42:03 +00003961 &multi_ap);
Hai Shalom74f70d42019-02-11 14:42:39 -08003962 if (multi_ap_ie_len == 0) {
3963 wpa_printf(MSG_ERROR,
3964 "Multi-AP: Failed to build Multi-AP IE");
3965 os_free(wpa_ie);
3966 return NULL;
3967 }
3968 wpa_ie_len += multi_ap_ie_len;
3969 }
3970
Sunil Ravi7f769292024-07-23 22:21:32 +00003971 if (!wpas_driver_bss_selection(wpa_s) &&
3972 wpas_rsn_overriding(wpa_s) &&
3973 wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
3974 wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
3975 u8 *pos = wpa_ie + wpa_ie_len;
3976 u32 type = 0;
3977 const u8 *ie;
3978
3979 ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
3980 if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
3981 type = WPA_GET_BE32(&ie[2]);
3982
3983 if (type) {
3984 /* Indicate support for RSN overriding */
3985 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
3986 *pos++ = 4;
3987 WPA_PUT_BE32(pos, type);
3988 pos += 4;
3989 wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
3990 pos - wpa_ie);
3991 wpa_ie_len += 2 + 4;
3992 }
3993 }
3994
3995 if (wpas_driver_bss_selection(wpa_s) &&
3996 wpas_rsn_overriding(wpa_s)) {
3997 if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
3998 u8 *pos = wpa_ie + wpa_ie_len;
3999
4000 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4001 *pos++ = 4;
4002 WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
4003 pos += 4;
4004 wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
4005 pos - wpa_ie);
4006 wpa_ie_len += 2 + 4;
4007 }
4008
4009 if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
4010 u8 *pos = wpa_ie + wpa_ie_len;
4011
4012 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4013 *pos++ = 4;
4014 WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
4015 pos += 4;
4016 wpa_hexdump(MSG_MSGDUMP, "RSNE Override 2",
4017 wpa_ie, pos - wpa_ie);
4018 wpa_ie_len += 2 + 4;
4019 }
4020 }
4021
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004022 params->wpa_ie = wpa_ie;
4023 params->wpa_ie_len = wpa_ie_len;
4024 params->auth_alg = algs;
4025 if (mask)
4026 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
4027
4028 return wpa_ie;
4029}
4030
4031
Hai Shalomc3565922019-10-28 11:58:20 -07004032#ifdef CONFIG_OWE
4033static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
4034{
4035 struct wpa_driver_associate_params params;
4036 u8 *wpa_ie;
4037
4038 os_memset(&params, 0, sizeof(params));
4039 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4040 wpa_s->current_ssid, &params, NULL);
4041 if (!wpa_ie)
4042 return;
4043
4044 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4045 os_free(wpa_ie);
4046}
4047#endif /* CONFIG_OWE */
4048
4049
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004050#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
4051static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
4052{
4053 struct wpa_driver_associate_params params;
4054 enum wpa_drv_update_connect_params_mask mask = 0;
4055 u8 *wpa_ie;
4056
4057 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
4058 return; /* nothing to do */
4059
4060 os_memset(&params, 0, sizeof(params));
4061 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4062 wpa_s->current_ssid, &params, &mask);
4063 if (!wpa_ie)
4064 return;
4065
Hai Shalomc1a21442022-02-04 13:43:00 -08004066 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
4067 wpa_s->auth_alg = params.auth_alg;
4068 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004069 }
4070
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004071 os_free(wpa_ie);
4072}
4073#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
4074
4075
Hai Shalomc3565922019-10-28 11:58:20 -07004076static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
4077{
4078 if (!edmg_ie || edmg_ie[1] < 6)
4079 return 0;
4080 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
4081}
4082
4083
4084static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
4085{
4086 if (!edmg_ie || edmg_ie[1] < 6)
4087 return 0;
4088 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
4089}
4090
4091
4092/* Returns the intersection of two EDMG configurations.
4093 * Note: The current implementation is limited to CB2 only (CB1 included),
4094 * i.e., the implementation supports up to 2 contiguous channels.
4095 * For supporting non-contiguous (aggregated) channels and for supporting
4096 * CB3 and above, this function will need to be extended.
4097 */
4098static struct ieee80211_edmg_config
4099get_edmg_intersection(struct ieee80211_edmg_config a,
4100 struct ieee80211_edmg_config b,
4101 u8 primary_channel)
4102{
4103 struct ieee80211_edmg_config result;
4104 int i, contiguous = 0;
4105 int max_contiguous = 0;
4106
4107 result.channels = b.channels & a.channels;
4108 if (!result.channels) {
4109 wpa_printf(MSG_DEBUG,
4110 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
4111 a.channels, b.channels);
4112 goto fail;
4113 }
4114
4115 if (!(result.channels & BIT(primary_channel - 1))) {
4116 wpa_printf(MSG_DEBUG,
4117 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
4118 primary_channel, result.channels);
4119 goto fail;
4120 }
4121
4122 /* Find max contiguous channels */
4123 for (i = 0; i < 6; i++) {
4124 if (result.channels & BIT(i))
4125 contiguous++;
4126 else
4127 contiguous = 0;
4128
4129 if (contiguous > max_contiguous)
4130 max_contiguous = contiguous;
4131 }
4132
4133 /* Assuming AP and STA supports ONLY contiguous channels,
4134 * bw configuration can have value between 4-7.
4135 */
4136 if ((b.bw_config < a.bw_config))
4137 result.bw_config = b.bw_config;
4138 else
4139 result.bw_config = a.bw_config;
4140
4141 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
4142 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
4143 wpa_printf(MSG_DEBUG,
4144 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
4145 max_contiguous);
4146 goto fail;
4147 }
4148
4149 return result;
4150
4151fail:
4152 result.channels = 0;
4153 result.bw_config = 0;
4154 return result;
4155}
4156
4157
4158static struct ieee80211_edmg_config
4159get_supported_edmg(struct wpa_supplicant *wpa_s,
4160 struct hostapd_freq_params *freq,
4161 struct ieee80211_edmg_config request_edmg)
4162{
4163 enum hostapd_hw_mode hw_mode;
4164 struct hostapd_hw_modes *mode = NULL;
4165 u8 primary_channel;
4166
4167 if (!wpa_s->hw.modes)
4168 goto fail;
4169
4170 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
4171 if (hw_mode == NUM_HOSTAPD_MODES)
4172 goto fail;
4173
Hai Shalom60840252021-02-19 19:02:11 -08004174 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004175 if (!mode)
4176 goto fail;
4177
4178 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
4179
4180fail:
4181 request_edmg.channels = 0;
4182 request_edmg.bw_config = 0;
4183 return request_edmg;
4184}
4185
4186
Hai Shalom021b0b52019-04-10 11:17:58 -07004187#ifdef CONFIG_MBO
4188void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
4189{
4190 struct wpa_driver_associate_params params;
4191 u8 *wpa_ie;
4192
4193 /*
4194 * Update MBO connect params only in case of change of MBO attributes
4195 * when connected, if the AP support MBO.
4196 */
4197
4198 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
4199 !wpa_s->current_bss ||
4200 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
4201 return;
4202
4203 os_memset(&params, 0, sizeof(params));
4204 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4205 wpa_s->current_ssid, &params, NULL);
4206 if (!wpa_ie)
4207 return;
4208
4209 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4210 os_free(wpa_ie);
4211}
4212#endif /* CONFIG_MBO */
4213
4214
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004215static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4216{
4217 struct wpa_connect_work *cwork = work->ctx;
4218 struct wpa_bss *bss = cwork->bss;
4219 struct wpa_ssid *ssid = cwork->ssid;
4220 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004221 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004222 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004223 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004224 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004225 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004226 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004227#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004228 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004229#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004230 int assoc_failed = 0;
4231 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004232 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004233#ifdef CONFIG_HT_OVERRIDES
4234 struct ieee80211_ht_capabilities htcaps;
4235 struct ieee80211_ht_capabilities htcaps_mask;
4236#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004237#ifdef CONFIG_VHT_OVERRIDES
4238 struct ieee80211_vht_capabilities vhtcaps;
4239 struct ieee80211_vht_capabilities vhtcaps_mask;
4240#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004241
Hai Shalomc1a21442022-02-04 13:43:00 -08004242 wpa_s->roam_in_progress = false;
4243#ifdef CONFIG_WNM
4244 wpa_s->bss_trans_mgmt_in_progress = false;
4245#endif /* CONFIG_WNM */
Sunil Ravi7f769292024-07-23 22:21:32 +00004246 wpa_s->no_suitable_network = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08004247
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004248 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004249 if (work->started) {
4250 wpa_s->connect_work = NULL;
4251
4252 /* cancel possible auth. timeout */
4253 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4254 NULL);
4255 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004256 wpas_connect_work_free(cwork);
4257 return;
4258 }
4259
4260 wpa_s->connect_work = work;
4261
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004262 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4263 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004264 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4265 wpas_connect_work_done(wpa_s);
4266 return;
4267 }
4268
Sunil Ravi640215c2023-06-28 23:08:09 +00004269 /*
4270 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4271 * (for MLO connection) as the previous BSSID for reassociation requests
4272 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4273 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4274 * will be zero.
4275 */
4276 os_memcpy(prev_bssid,
4277 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4278 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004279 os_memset(&params, 0, sizeof(params));
4280 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004281 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004282
4283 /* Starting new association, so clear the possibly used WPA IE from the
4284 * previous association. */
4285 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4286 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4287 wpa_s->rsnxe_len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004288#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom60840252021-02-19 19:02:11 -08004289 wpa_s->mscs_setup_done = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004290#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08004291
4292 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4293 if (!wpa_ie) {
4294 wpas_connect_work_done(wpa_s);
4295 return;
4296 }
4297
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004298 if (bss &&
4299 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300#ifdef CONFIG_IEEE80211R
4301 const u8 *ie, *md = NULL;
4302#endif /* CONFIG_IEEE80211R */
4303 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4304 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4305 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4306 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4307 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4308 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4309 if (bssid_changed)
4310 wpas_notify_bssid_changed(wpa_s);
4311#ifdef CONFIG_IEEE80211R
4312 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4313 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4314 md = ie + 2;
4315 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4316 if (md) {
4317 /* Prepare for the next transition */
4318 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4319 }
4320#endif /* CONFIG_IEEE80211R */
4321#ifdef CONFIG_WPS
4322 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4323 wpa_s->conf->ap_scan == 2 &&
4324 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4325 /* Use ap_scan==1 style network selection to find the network
4326 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004327 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004328 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004329 wpa_s->reassociate = 1;
4330 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004331 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 return;
4333#endif /* CONFIG_WPS */
4334 } else {
4335 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4336 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004337 if (bss)
4338 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4339 else
4340 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004341 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004342 if (!wpa_s->pno)
4343 wpa_supplicant_cancel_sched_scan(wpa_s);
4344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 wpa_supplicant_cancel_scan(wpa_s);
4346
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4348 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004349 cipher_pairwise = wpa_s->pairwise_cipher;
4350 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004352 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4353 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4354 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4355 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004356#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004357 if (wpa_set_wep_keys(wpa_s, ssid)) {
4358 use_crypt = 1;
4359 wep_keys_set = 1;
4360 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004361#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 }
4363 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4364 use_crypt = 0;
4365
4366#ifdef IEEE8021X_EAPOL
4367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4368 if ((ssid->eapol_flags &
4369 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4370 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4371 !wep_keys_set) {
4372 use_crypt = 0;
4373 } else {
4374 /* Assume that dynamic WEP-104 keys will be used and
4375 * set cipher suites in order for drivers to expect
4376 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004377 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378 }
4379 }
4380#endif /* IEEE8021X_EAPOL */
4381
4382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4383 /* Set the key before (and later after) association */
4384 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4385 }
4386
Sunil8cd6f4d2022-06-28 18:40:46 +00004387 /* Set current_ssid before changing state to ASSOCIATING, so that the
4388 * selected SSID is available to wpas_notify_state_changed(). */
4389 old_ssid = wpa_s->current_ssid;
4390 wpa_s->current_ssid = ssid;
4391
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4393 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 params.ssid = bss->ssid;
4395 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004396 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4397 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004398 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4399 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004400 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004401 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004402 ssid->bssid_set,
4403 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004404 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004405 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004406 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004407 params.bssid_hint = bss->bssid;
4408 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004409 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004411 if (ssid->bssid_hint_set)
4412 params.bssid_hint = ssid->bssid_hint;
4413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414 params.ssid = ssid->ssid;
4415 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004416 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004417 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004418
4419 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4420 wpa_s->conf->ap_scan == 2) {
4421 params.bssid = ssid->bssid;
4422 params.fixed_bssid = 1;
4423 }
4424
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004425 /* Initial frequency for IBSS/mesh */
4426 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004427 ssid->frequency > 0 && params.freq.freq == 0)
4428 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004429
4430 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004431 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004432 if (ssid->beacon_int)
4433 params.beacon_int = ssid->beacon_int;
4434 else
4435 params.beacon_int = wpa_s->conf->beacon_int;
4436 }
4437
Hai Shalomc3565922019-10-28 11:58:20 -07004438 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004439 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4440 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004441 else
4442 edmg_ie_oper = NULL;
4443
4444 if (edmg_ie_oper) {
4445 params.freq.edmg.channels =
4446 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4447 params.freq.edmg.bw_config =
4448 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4449 wpa_printf(MSG_DEBUG,
4450 "AP supports EDMG channels 0x%x, bw_config %d",
4451 params.freq.edmg.channels,
4452 params.freq.edmg.bw_config);
4453
4454 /* User may ask for specific EDMG channel for EDMG connection
4455 * (must be supported by AP)
4456 */
4457 if (ssid->edmg_channel) {
4458 struct ieee80211_edmg_config configured_edmg;
4459 enum hostapd_hw_mode hw_mode;
4460 u8 primary_channel;
4461
4462 hw_mode = ieee80211_freq_to_chan(bss->freq,
4463 &primary_channel);
4464 if (hw_mode == NUM_HOSTAPD_MODES)
4465 goto edmg_fail;
4466
4467 hostapd_encode_edmg_chan(ssid->enable_edmg,
4468 ssid->edmg_channel,
4469 primary_channel,
4470 &configured_edmg);
4471
4472 if (ieee802_edmg_is_allowed(params.freq.edmg,
4473 configured_edmg)) {
4474 params.freq.edmg = configured_edmg;
4475 wpa_printf(MSG_DEBUG,
4476 "Use EDMG channel %d for connection",
4477 ssid->edmg_channel);
4478 } else {
4479 edmg_fail:
4480 params.freq.edmg.channels = 0;
4481 params.freq.edmg.bw_config = 0;
4482 wpa_printf(MSG_WARNING,
4483 "EDMG channel %d not supported by AP, fallback to DMG",
4484 ssid->edmg_channel);
4485 }
4486 }
4487
4488 if (params.freq.edmg.channels) {
4489 wpa_printf(MSG_DEBUG,
4490 "EDMG before: channels 0x%x, bw_config %d",
4491 params.freq.edmg.channels,
4492 params.freq.edmg.bw_config);
4493 params.freq.edmg = get_supported_edmg(wpa_s,
4494 &params.freq,
4495 params.freq.edmg);
4496 wpa_printf(MSG_DEBUG,
4497 "EDMG after: channels 0x%x, bw_config %d",
4498 params.freq.edmg.channels,
4499 params.freq.edmg.bw_config);
4500 }
4501 }
4502
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503 params.pairwise_suite = cipher_pairwise;
4504 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004505 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004506 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004507 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004508 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004509 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004510 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004511 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004512#ifdef CONFIG_WEP
4513 {
4514 int i;
4515
4516 for (i = 0; i < NUM_WEP_KEYS; i++) {
4517 if (ssid->wep_key_len[i])
4518 params.wep_key[i] = ssid->wep_key[i];
4519 params.wep_key_len[i] = ssid->wep_key_len[i];
4520 }
4521 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004523#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524
Hai Shalom74f70d42019-02-11 14:42:39 -08004525 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004526#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4527 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004528 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4529 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004530#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4531 defined(CONFIG_DRIVER_NL80211_SYNA)
4532 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4533 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4534 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4535 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304536#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004537 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4538 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4539 (params.allowed_key_mgmts &
4540 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004541#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4542 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004543 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004544 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4545 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546 }
4547
Hai Shalom74f70d42019-02-11 14:42:39 -08004548 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4549 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4550 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4551 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004552 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4553 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004554 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004555
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004556 if (wpa_s->conf->key_mgmt_offload) {
4557 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4558 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004559 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004560 params.key_mgmt_suite ==
4561 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4562 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004563 params.req_key_mgmt_offload =
4564 ssid->proactive_key_caching < 0 ?
4565 wpa_s->conf->okc : ssid->proactive_key_caching;
4566 else
4567 params.req_key_mgmt_offload = 1;
4568
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004569#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4570 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004571 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004572 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4573 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004574#else
4575 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4576 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004577#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4578 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004579 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4580 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004581 }
4582
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004583 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4584 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4585 params.auth_alg = WPA_AUTH_ALG_SAE;
4586 if (ssid->sae_password) {
4587 params.sae_password = ssid->sae_password;
4588 params.sae_password_id = ssid->sae_password_id;
4589 } else if (ssid->passphrase) {
4590 params.passphrase = ssid->passphrase;
4591 }
4592 }
4593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004594 params.drop_unencrypted = use_crypt;
4595
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004596 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004597 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004598 const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004600 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4601 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004602 ie.capabilities &
4603 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4604 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4605 "MFP: require MFP");
4606 params.mgmt_frame_protection =
4607 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004608#ifdef CONFIG_OWE
4609 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4610 !ssid->owe_only) {
4611 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4612#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 }
4614 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004616 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004617
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004618 if (wpa_s->p2pdev->set_sta_uapsd)
4619 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004620 else
4621 params.uapsd = -1;
4622
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004623#ifdef CONFIG_HT_OVERRIDES
4624 os_memset(&htcaps, 0, sizeof(htcaps));
4625 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4626 params.htcaps = (u8 *) &htcaps;
4627 params.htcaps_mask = (u8 *) &htcaps_mask;
4628 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4629#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004630#ifdef CONFIG_VHT_OVERRIDES
4631 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4632 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4633 params.vhtcaps = &vhtcaps;
4634 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004635 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004636#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004637#ifdef CONFIG_HE_OVERRIDES
4638 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4639#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004640 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004641
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004642#ifdef CONFIG_P2P
4643 /*
4644 * If multi-channel concurrency is not supported, check for any
4645 * frequency conflict. In case of any frequency conflict, remove the
4646 * least prioritized connection.
4647 */
4648 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004649 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004650 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004651 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004652 wpa_printf(MSG_DEBUG,
4653 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004654 freq, params.freq.freq);
4655 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004656 wpa_s, params.freq.freq, ssid) < 0) {
4657 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004658 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004659 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004660 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004661 }
4662 }
4663#endif /* CONFIG_P2P */
4664
Dmitry Shmidte4663042016-04-04 10:07:49 -07004665 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004666 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004667 params.prev_bssid = prev_bssid;
4668
Hai Shalom60840252021-02-19 19:02:11 -08004669#ifdef CONFIG_SAE
4670 params.sae_pwe = wpa_s->conf->sae_pwe;
4671#endif /* CONFIG_SAE */
4672
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004673 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004674 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004675 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 if (ret < 0) {
4677 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4678 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004679 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004680 /*
4681 * The driver is known to mean what is saying, so we
4682 * can stop right here; the association will not
4683 * succeed.
4684 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004685 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
4686 NULL);
Roger Wang4c09cc92020-11-05 18:57:12 +08004687 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004688 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004689 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004690 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4691 return;
4692 }
4693 /* try to continue anyway; new association will be tried again
4694 * after timeout */
4695 assoc_failed = 1;
4696 }
4697
4698 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4699 /* Set the key after the association just in case association
4700 * cleared the previously configured key. */
4701 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4702 /* No need to timeout authentication since there is no key
4703 * management. */
4704 wpa_supplicant_cancel_auth_timeout(wpa_s);
4705 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4706#ifdef CONFIG_IBSS_RSN
4707 } else if (ssid->mode == WPAS_MODE_IBSS &&
4708 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4709 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4710 /*
4711 * RSN IBSS authentication is per-STA and we can disable the
4712 * per-BSSID authentication.
4713 */
4714 wpa_supplicant_cancel_auth_timeout(wpa_s);
4715#endif /* CONFIG_IBSS_RSN */
4716 } else {
4717 /* Timeout for IEEE 802.11 authentication and association */
4718 int timeout = 60;
4719
4720 if (assoc_failed) {
4721 /* give IBSS a bit more time */
4722 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4723 } else if (wpa_s->conf->ap_scan == 1) {
4724 /* give IBSS a bit more time */
4725 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4726 }
4727 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4728 }
4729
Hai Shalomfdcde762020-04-02 11:19:20 -07004730#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004731 if (wep_keys_set &&
4732 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004733 /* Set static WEP keys again */
4734 wpa_set_wep_keys(wpa_s, ssid);
4735 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004736#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004737
Sunil8cd6f4d2022-06-28 18:40:46 +00004738 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004739 /*
4740 * Do not allow EAP session resumption between different
4741 * network configurations.
4742 */
4743 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4744 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004745
mtk30479d7f89782024-01-24 11:51:43 +08004746 if (!wpas_driver_bss_selection(wpa_s) ||
4747#ifdef CONFIG_P2P
4748 wpa_s->p2p_in_invitation ||
4749#endif /* CONFIG_P2P */
4750 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004751 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004752#ifdef CONFIG_HS20
4753 hs20_configure_frame_filters(wpa_s);
4754#endif /* CONFIG_HS20 */
4755 }
4756
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
Sunil Ravi7f769292024-07-23 22:21:32 +00004758 if (bss)
4759 wpa_sm_set_ssid(wpa_s->wpa, bss->ssid, bss->ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004760 wpa_supplicant_initiate_eapol(wpa_s);
4761 if (old_ssid != wpa_s->current_ssid)
4762 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004763 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4764 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004765}
4766
4767
4768static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4769 const u8 *addr)
4770{
4771 struct wpa_ssid *old_ssid;
4772
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004773 wpa_s->ml_connect_probe_ssid = NULL;
4774 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004775 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004776 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004777 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004778 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004779 wpa_sm_set_config(wpa_s->wpa, NULL);
4780 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4781 if (old_ssid != wpa_s->current_ssid)
4782 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004783
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004784#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08004785 wpas_scs_deinit(wpa_s);
4786 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004787#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004788 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4789}
4790
4791
4792/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004793 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4794 * @wpa_s: Pointer to wpa_supplicant data
4795 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4796 *
4797 * This function is used to request %wpa_supplicant to deauthenticate from the
4798 * current AP.
4799 */
4800void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004801 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004802{
4803 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004804 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004805 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004807 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Sunil Ravi7f769292024-07-23 22:21:32 +00004808 " pending_bssid=" MACSTR
4809 " reason=%d (%s) state=%s valid_links=0x%x ap_mld_addr=" MACSTR,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004810 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004811 reason_code, reason2str(reason_code),
Sunil Ravi7f769292024-07-23 22:21:32 +00004812 wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_s->valid_links,
4813 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004814
Sunil Ravi7f769292024-07-23 22:21:32 +00004815 if (wpa_s->valid_links && !is_zero_ether_addr(wpa_s->ap_mld_addr))
4816 addr = wpa_s->ap_mld_addr;
4817 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4818 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4819 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004820 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004821 else if (!is_zero_ether_addr(wpa_s->bssid))
4822 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004823 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4824 /*
4825 * When using driver-based BSS selection, we may not know the
4826 * BSSID with which we are currently trying to associate. We
4827 * need to notify the driver of this disconnection even in such
4828 * a case, so use the all zeros address here.
4829 */
4830 addr = wpa_s->bssid;
4831 zero_addr = 1;
4832 }
4833
Hai Shalom74f70d42019-02-11 14:42:39 -08004834 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4835 wpa_s->enabled_4addr_mode = 0;
4836
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004837#ifdef CONFIG_TDLS
4838 wpa_tdls_teardown_peers(wpa_s->wpa);
4839#endif /* CONFIG_TDLS */
4840
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004841#ifdef CONFIG_MESH
4842 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004843 struct mesh_conf *mconf;
4844
4845 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004846 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4847 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004848 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4849 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004850 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004851 }
4852#endif /* CONFIG_MESH */
4853
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004854 if (addr) {
4855 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004856 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004857 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004858 event.deauth_info.locally_generated = 1;
4859 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004860 if (zero_addr)
4861 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004862 }
4863
4864 wpa_supplicant_clear_connection(wpa_s, addr);
4865}
4866
Hai Shalomfdcde762020-04-02 11:19:20 -07004867
4868void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4869{
4870 wpa_s->own_reconnect_req = 1;
4871 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4872
4873}
4874
4875
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004876static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4877 struct wpa_ssid *ssid)
4878{
4879 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4880 return;
4881
4882 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004883 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004884 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4885 wpas_notify_network_enabled_changed(wpa_s, ssid);
4886
4887 /*
4888 * Try to reassociate since there is no current configuration and a new
4889 * network was made available.
4890 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004891 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004892 wpa_s->reassociate = 1;
4893}
4894
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004895
Roshan Pius950bec92016-07-19 09:49:24 -07004896/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004897 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004898 * @wpa_s: wpa_supplicant structure for a network interface
4899 * Returns: The new network configuration or %NULL if operation failed
4900 *
4901 * This function performs the following operations:
4902 * 1. Adds a new network.
4903 * 2. Send network addition notification.
4904 * 3. Marks the network disabled.
4905 * 4. Set network default parameters.
4906 */
4907struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4908{
4909 struct wpa_ssid *ssid;
4910
4911 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004912 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004913 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004914 wpas_notify_network_added(wpa_s, ssid);
4915 ssid->disabled = 1;
4916 wpa_config_set_network_defaults(ssid);
4917
4918 return ssid;
4919}
4920
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004921
Roshan Pius950bec92016-07-19 09:49:24 -07004922/**
4923 * wpa_supplicant_remove_network - Remove a configured network based on id
4924 * @wpa_s: wpa_supplicant structure for a network interface
4925 * @id: Unique network id to search for
4926 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4927 * could not be removed
4928 *
4929 * This function performs the following operations:
4930 * 1. Removes the network.
4931 * 2. Send network removal notification.
4932 * 3. Update internal state machines.
4933 * 4. Stop any running sched scans.
4934 */
4935int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4936{
Sunil Ravia04bd252022-05-02 22:54:18 -07004937 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004938 int was_disabled;
4939
4940 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004941 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004942 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004943 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004944
Sunil Ravia04bd252022-05-02 22:54:18 -07004945 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004946#ifdef CONFIG_SME
4947 wpa_s->sme.prev_bssid_set = 0;
4948#endif /* CONFIG_SME */
4949 /*
4950 * Invalidate the EAP session cache if the current or
4951 * previously used network is removed.
4952 */
4953 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4954 }
4955
Sunil Ravia04bd252022-05-02 22:54:18 -07004956 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004957 wpa_sm_set_config(wpa_s->wpa, NULL);
4958 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4959
4960 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4961 wpa_s->own_disconnect_req = 1;
4962 wpa_supplicant_deauthenticate(wpa_s,
4963 WLAN_REASON_DEAUTH_LEAVING);
4964 }
4965
4966 was_disabled = ssid->disabled;
4967
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004968 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004969 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004970
4971 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004972 wpa_printf(MSG_DEBUG,
4973 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004974 wpa_supplicant_cancel_sched_scan(wpa_s);
4975 wpa_supplicant_req_scan(wpa_s, 0, 0);
4976 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004977
Roshan Pius950bec92016-07-19 09:49:24 -07004978 return 0;
4979}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004980
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004982/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004983 * wpa_supplicant_remove_all_networks - Remove all configured networks
4984 * @wpa_s: wpa_supplicant structure for a network interface
4985 * Returns: 0 on success (errors are currently ignored)
4986 *
4987 * This function performs the following operations:
4988 * 1. Remove all networks.
4989 * 2. Send network removal notifications.
4990 * 3. Update internal state machines.
4991 * 4. Stop any running sched scans.
4992 */
4993int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4994{
4995 struct wpa_ssid *ssid;
4996
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304997 if (wpa_s->drv_flags2 &
4998 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4999 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
5000 wpa_drv_flush_pmkid(wpa_s);
5001
Hai Shalom899fcc72020-10-19 14:38:18 -07005002 if (wpa_s->sched_scanning)
5003 wpa_supplicant_cancel_sched_scan(wpa_s);
5004
5005 eapol_sm_invalidate_cached_session(wpa_s->eapol);
5006 if (wpa_s->current_ssid) {
5007#ifdef CONFIG_SME
5008 wpa_s->sme.prev_bssid_set = 0;
5009#endif /* CONFIG_SME */
5010 wpa_sm_set_config(wpa_s->wpa, NULL);
5011 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
5012 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5013 wpa_s->own_disconnect_req = 1;
5014 wpa_supplicant_deauthenticate(
5015 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5016 }
5017 ssid = wpa_s->conf->ssid;
5018 while (ssid) {
5019 struct wpa_ssid *remove_ssid = ssid;
5020 int id;
5021
5022 id = ssid->id;
5023 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07005024 wpas_notify_network_removed(wpa_s, remove_ssid);
5025 wpa_config_remove_network(wpa_s->conf, id);
5026 }
5027 return 0;
5028}
5029
5030
5031/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005032 * wpa_supplicant_enable_network - Mark a configured network as enabled
5033 * @wpa_s: wpa_supplicant structure for a network interface
5034 * @ssid: wpa_ssid structure for a configured network or %NULL
5035 *
5036 * Enables the specified network or all networks if no network specified.
5037 */
5038void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
5039 struct wpa_ssid *ssid)
5040{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005041 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005042 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5043 wpa_supplicant_enable_one_network(wpa_s, ssid);
5044 } else
5045 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005046
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005047 if (wpa_s->reassociate && !wpa_s->disconnected &&
5048 (!wpa_s->current_ssid ||
5049 wpa_s->wpa_state == WPA_DISCONNECTED ||
5050 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005051 if (wpa_s->sched_scanning) {
5052 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
5053 "new network to scan filters");
5054 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005055 }
5056
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005057 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
5058 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07005059 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005060 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005061 }
5062}
5063
5064
5065/**
5066 * wpa_supplicant_disable_network - Mark a configured network as disabled
5067 * @wpa_s: wpa_supplicant structure for a network interface
5068 * @ssid: wpa_ssid structure for a configured network or %NULL
5069 *
5070 * Disables the specified network or all networks if no network specified.
5071 */
5072void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
5073 struct wpa_ssid *ssid)
5074{
5075 struct wpa_ssid *other_ssid;
5076 int was_disabled;
5077
5078 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005079 if (wpa_s->sched_scanning)
5080 wpa_supplicant_cancel_sched_scan(wpa_s);
5081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005082 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5083 other_ssid = other_ssid->next) {
5084 was_disabled = other_ssid->disabled;
5085 if (was_disabled == 2)
5086 continue; /* do not change persistent P2P group
5087 * data */
5088
5089 other_ssid->disabled = 1;
5090
5091 if (was_disabled != other_ssid->disabled)
5092 wpas_notify_network_enabled_changed(
5093 wpa_s, other_ssid);
5094 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005095 if (wpa_s->current_ssid) {
5096 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5097 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005098 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005099 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005100 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005101 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005102 if (ssid == wpa_s->current_ssid) {
5103 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5104 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005105 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005107 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108
5109 was_disabled = ssid->disabled;
5110
5111 ssid->disabled = 1;
5112
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005113 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005115 if (wpa_s->sched_scanning) {
5116 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
5117 "to remove network from filters");
5118 wpa_supplicant_cancel_sched_scan(wpa_s);
5119 wpa_supplicant_req_scan(wpa_s, 0, 0);
5120 }
5121 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122 }
5123}
5124
5125
5126/**
5127 * wpa_supplicant_select_network - Attempt association with a network
5128 * @wpa_s: wpa_supplicant structure for a network interface
5129 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
5130 */
5131void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
5132 struct wpa_ssid *ssid)
5133{
5134
5135 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005136 int disconnected = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00005137 bool request_new_scan = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005138
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005139 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005140 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5141 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005142 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005143 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005144 disconnected = 1;
5145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005146
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005147 if (ssid)
5148 wpas_clear_temp_disabled(wpa_s, ssid, 1);
5149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005150 /*
5151 * Mark all other networks disabled or mark all networks enabled if no
5152 * network specified.
5153 */
5154 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5155 other_ssid = other_ssid->next) {
5156 int was_disabled = other_ssid->disabled;
5157 if (was_disabled == 2)
5158 continue; /* do not change persistent P2P group data */
5159
5160 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005161 if (was_disabled && !other_ssid->disabled)
5162 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005163
5164 if (was_disabled != other_ssid->disabled)
5165 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
5166 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005167
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005168 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
5169 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005170 /* We are already associated with the selected network */
5171 wpa_printf(MSG_DEBUG, "Already associated with the "
5172 "selected network - do nothing");
5173 return;
5174 }
5175
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005176 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005177 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005178 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005179 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00005180 (ssid->mode == WPAS_MODE_MESH ||
5181 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005182
Sunil Ravi7f769292024-07-23 22:21:32 +00005183 if (ssid->scan_ssid &&
5184 (wpa_s->no_suitable_network || wpa_s->last_scan_external)) {
5185 wpa_printf(MSG_DEBUG,
5186 "Request a new scan for hidden network");
5187 request_new_scan = true;
5188 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
5189 !ssid->owe_only) {
5190 wpa_printf(MSG_DEBUG,
5191 "Request a new scan for OWE transition SSID");
5192 request_new_scan = true;
5193 }
5194
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005195 /*
5196 * Don't optimize next scan freqs since a new ESS has been
5197 * selected.
5198 */
5199 os_free(wpa_s->next_scan_freqs);
5200 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005201 } else {
5202 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005203 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005204
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005205 wpa_s->disconnected = 0;
5206 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005207 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005208 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005209 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005210 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07005211 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07005212 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005213
Sunil Ravi7f769292024-07-23 22:21:32 +00005214 if (wpa_s->connect_without_scan || request_new_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005215 wpa_supplicant_fast_associate(wpa_s) != 1) {
5216 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005217 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005218 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005219 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220
5221 if (ssid)
5222 wpas_notify_network_selected(wpa_s, ssid);
5223}
5224
5225
5226/**
Hai Shalomc1a21442022-02-04 13:43:00 -08005227 * wpas_remove_cred - Remove the specified credential and all the network
5228 * entries created based on the removed credential
5229 * @wpa_s: wpa_supplicant structure for a network interface
5230 * @cred: The credential to remove
5231 * Returns: 0 on success, -1 on failure
5232 */
5233int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
5234{
5235 struct wpa_ssid *ssid, *next;
5236 int id;
5237
5238 if (!cred) {
5239 wpa_printf(MSG_DEBUG, "Could not find cred");
5240 return -1;
5241 }
5242
5243 id = cred->id;
5244 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5245 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5246 return -1;
5247 }
5248
5249 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5250
5251 /* Remove any network entry created based on the removed credential */
5252 ssid = wpa_s->conf->ssid;
5253 while (ssid) {
5254 next = ssid->next;
5255
5256 if (ssid->parent_cred == cred) {
5257 wpa_printf(MSG_DEBUG,
5258 "Remove network id %d since it used the removed credential",
5259 ssid->id);
5260 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5261 -1) {
5262 wpa_printf(MSG_DEBUG,
5263 "Could not find network id=%d",
5264 ssid->id);
5265 }
5266 }
5267
5268 ssid = next;
5269 }
5270
5271 return 0;
5272}
5273
5274
5275/**
5276 * wpas_remove_cred - Remove all the Interworking credentials
5277 * @wpa_s: wpa_supplicant structure for a network interface
5278 * Returns: 0 on success, -1 on failure
5279 */
5280int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5281{
5282 int res, ret = 0;
5283 struct wpa_cred *cred, *prev;
5284
5285 cred = wpa_s->conf->cred;
5286 while (cred) {
5287 prev = cred;
5288 cred = cred->next;
5289 res = wpas_remove_cred(wpa_s, prev);
5290 if (res < 0) {
5291 wpa_printf(MSG_DEBUG,
5292 "Removal of all credentials failed - failed to remove credential id=%d",
5293 prev->id);
5294 ret = -1;
5295 }
5296 }
5297
5298 return ret;
5299}
5300
5301
5302/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005303 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5304 * @wpa_s: wpa_supplicant structure for a network interface
5305 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5306 * @pkcs11_module_path: PKCS #11 module path or NULL
5307 * Returns: 0 on success; -1 on failure
5308 *
5309 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5310 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5311 * module path fails the paths will be reset to the default value (NULL).
5312 */
5313int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5314 const char *pkcs11_engine_path,
5315 const char *pkcs11_module_path)
5316{
5317 char *pkcs11_engine_path_copy = NULL;
5318 char *pkcs11_module_path_copy = NULL;
5319
5320 if (pkcs11_engine_path != NULL) {
5321 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5322 if (pkcs11_engine_path_copy == NULL)
5323 return -1;
5324 }
5325 if (pkcs11_module_path != NULL) {
5326 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005327 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005328 os_free(pkcs11_engine_path_copy);
5329 return -1;
5330 }
5331 }
5332
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005333#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005334 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005335 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005336#endif /* CONFIG_PKCS11_ENGINE_PATH */
5337#ifndef CONFIG_PKCS11_MODULE_PATH
5338 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005339 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005340#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005341
5342 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5343 eapol_sm_deinit(wpa_s->eapol);
5344 wpa_s->eapol = NULL;
5345 if (wpa_supplicant_init_eapol(wpa_s)) {
5346 /* Error -> Reset paths to the default value (NULL) once. */
5347 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5348 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5349 NULL);
5350
5351 return -1;
5352 }
5353 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5354
5355 return 0;
5356}
5357
5358
5359/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5361 * @wpa_s: wpa_supplicant structure for a network interface
5362 * @ap_scan: AP scan mode
5363 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5364 *
5365 */
5366int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5367{
5368
5369 int old_ap_scan;
5370
5371 if (ap_scan < 0 || ap_scan > 2)
5372 return -1;
5373
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005374 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5375 wpa_printf(MSG_INFO,
5376 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5377 }
5378
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005379#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005380 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5381 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5382 wpa_s->wpa_state < WPA_COMPLETED) {
5383 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5384 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005385 return 0;
5386 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005387#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005389 old_ap_scan = wpa_s->conf->ap_scan;
5390 wpa_s->conf->ap_scan = ap_scan;
5391
5392 if (old_ap_scan != wpa_s->conf->ap_scan)
5393 wpas_notify_ap_scan_changed(wpa_s);
5394
5395 return 0;
5396}
5397
5398
5399/**
5400 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5401 * @wpa_s: wpa_supplicant structure for a network interface
5402 * @expire_age: Expiration age in seconds
5403 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5404 *
5405 */
5406int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5407 unsigned int bss_expire_age)
5408{
5409 if (bss_expire_age < 10) {
5410 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5411 bss_expire_age);
5412 return -1;
5413 }
5414 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5415 bss_expire_age);
5416 wpa_s->conf->bss_expiration_age = bss_expire_age;
5417
5418 return 0;
5419}
5420
5421
5422/**
5423 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5424 * @wpa_s: wpa_supplicant structure for a network interface
5425 * @expire_count: number of scans after which an unseen BSS is reclaimed
5426 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5427 *
5428 */
5429int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5430 unsigned int bss_expire_count)
5431{
5432 if (bss_expire_count < 1) {
5433 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5434 bss_expire_count);
5435 return -1;
5436 }
5437 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5438 bss_expire_count);
5439 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5440
5441 return 0;
5442}
5443
5444
5445/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005446 * wpa_supplicant_set_scan_interval - Set scan interval
5447 * @wpa_s: wpa_supplicant structure for a network interface
5448 * @scan_interval: scan interval in seconds
5449 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5450 *
5451 */
5452int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5453 int scan_interval)
5454{
5455 if (scan_interval < 0) {
5456 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5457 scan_interval);
5458 return -1;
5459 }
5460 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5461 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005462 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005463
5464 return 0;
5465}
5466
5467
5468/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005469 * wpa_supplicant_set_debug_params - Set global debug params
5470 * @global: wpa_global structure
5471 * @debug_level: debug level
5472 * @debug_timestamp: determines if show timestamp in debug data
5473 * @debug_show_keys: determines if show keys in debug data
5474 * Returns: 0 if succeed or -1 if debug_level has wrong value
5475 */
5476int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5477 int debug_timestamp, int debug_show_keys)
5478{
5479
5480 int old_level, old_timestamp, old_show_keys;
5481
5482 /* check for allowed debuglevels */
5483 if (debug_level != MSG_EXCESSIVE &&
5484 debug_level != MSG_MSGDUMP &&
5485 debug_level != MSG_DEBUG &&
5486 debug_level != MSG_INFO &&
5487 debug_level != MSG_WARNING &&
5488 debug_level != MSG_ERROR)
5489 return -1;
5490
5491 old_level = wpa_debug_level;
5492 old_timestamp = wpa_debug_timestamp;
5493 old_show_keys = wpa_debug_show_keys;
5494
5495 wpa_debug_level = debug_level;
5496 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5497 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5498
5499 if (wpa_debug_level != old_level)
5500 wpas_notify_debug_level_changed(global);
5501 if (wpa_debug_timestamp != old_timestamp)
5502 wpas_notify_debug_timestamp_changed(global);
5503 if (wpa_debug_show_keys != old_show_keys)
5504 wpas_notify_debug_show_keys_changed(global);
5505
5506 return 0;
5507}
5508
5509
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005510#ifdef CONFIG_OWE
5511static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5512 const u8 *entry_ssid, size_t entry_ssid_len)
5513{
5514 const u8 *owe, *pos, *end;
5515 u8 ssid_len;
5516 struct wpa_bss *bss;
5517
5518 /* Check network profile SSID aganst the SSID in the
5519 * OWE Transition Mode element. */
5520
5521 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5522 if (!bss)
5523 return 0;
5524
5525 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5526 if (!owe)
5527 return 0;
5528
5529 pos = owe + 6;
5530 end = owe + 2 + owe[1];
5531
5532 if (end - pos < ETH_ALEN + 1)
5533 return 0;
5534 pos += ETH_ALEN;
5535 ssid_len = *pos++;
5536 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5537 return 0;
5538
5539 return entry_ssid_len == ssid_len &&
5540 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5541}
5542#endif /* CONFIG_OWE */
5543
5544
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005545/**
5546 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5547 * @wpa_s: Pointer to wpa_supplicant data
5548 * Returns: A pointer to the current network structure or %NULL on failure
5549 */
5550struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5551{
5552 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005553 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005554 int res;
5555 size_t ssid_len;
5556 u8 bssid[ETH_ALEN];
5557 int wired;
5558
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005559 res = wpa_drv_get_ssid(wpa_s, ssid);
5560 if (res < 0) {
5561 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5562 "driver");
5563 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005564 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005565 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005567 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5569 "driver");
5570 return NULL;
5571 }
5572
5573 wired = wpa_s->conf->ap_scan == 0 &&
5574 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5575
5576 entry = wpa_s->conf->ssid;
5577 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005578 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005580 (!entry->ssid ||
5581 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5582 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005584 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005585 return entry;
5586#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005587 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005588 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5589 (entry->ssid == NULL || entry->ssid_len == 0) &&
5590 (!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#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005594
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005595#ifdef CONFIG_OWE
5596 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005597 (entry->ssid &&
5598 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5599 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005600 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005601 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005602 return entry;
5603#endif /* CONFIG_OWE */
5604
Dmitry Shmidt04949592012-07-19 12:16:46 -07005605 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005606 entry->ssid_len == 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005607 ether_addr_equal(bssid, entry->bssid))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005608 return entry;
5609
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610 entry = entry->next;
5611 }
5612
5613 return NULL;
5614}
5615
5616
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005617static int select_driver(struct wpa_supplicant *wpa_s, int i)
5618{
5619 struct wpa_global *global = wpa_s->global;
5620
5621 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005622 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005623 if (global->drv_priv[i] == NULL) {
5624 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5625 "'%s'", wpa_drivers[i]->name);
5626 return -1;
5627 }
5628 }
5629
5630 wpa_s->driver = wpa_drivers[i];
5631 wpa_s->global_drv_priv = global->drv_priv[i];
5632
5633 return 0;
5634}
5635
5636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5638 const char *name)
5639{
5640 int i;
5641 size_t len;
5642 const char *pos, *driver = name;
5643
5644 if (wpa_s == NULL)
5645 return -1;
5646
5647 if (wpa_drivers[0] == NULL) {
5648 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5649 "wpa_supplicant");
5650 return -1;
5651 }
5652
5653 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005654 /* Default to first successful driver in the list */
5655 for (i = 0; wpa_drivers[i]; i++) {
5656 if (select_driver(wpa_s, i) == 0)
5657 return 0;
5658 }
5659 /* Drivers have each reported failure, so no wpa_msg() here. */
5660 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005661 }
5662
5663 do {
5664 pos = os_strchr(driver, ',');
5665 if (pos)
5666 len = pos - driver;
5667 else
5668 len = os_strlen(driver);
5669
5670 for (i = 0; wpa_drivers[i]; i++) {
5671 if (os_strlen(wpa_drivers[i]->name) == len &&
5672 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005673 0) {
5674 /* First driver that succeeds wins */
5675 if (select_driver(wpa_s, i) == 0)
5676 return 0;
5677 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005678 }
5679
5680 driver = pos + 1;
5681 } while (pos);
5682
5683 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5684 return -1;
5685}
5686
5687
5688/**
5689 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5690 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5691 * with struct wpa_driver_ops::init()
5692 * @src_addr: Source address of the EAPOL frame
5693 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5694 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005695 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696 *
5697 * This function is called for each received EAPOL frame. Most driver
5698 * interfaces rely on more generic OS mechanism for receiving frames through
5699 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5700 * take care of received EAPOL frames and deliver them to the core supplicant
5701 * code by calling this function.
5702 */
5703void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005704 const u8 *buf, size_t len,
5705 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005706{
5707 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005708 const u8 *connected_addr = wpa_s->valid_links ?
5709 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005710
Sunil8cd6f4d2022-06-28 18:40:46 +00005711 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5712 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5714
Hai Shalomc1a21442022-02-04 13:43:00 -08005715 if (wpa_s->own_disconnect_req) {
5716 wpa_printf(MSG_DEBUG,
5717 "Drop received EAPOL frame as we are disconnecting");
5718 return;
5719 }
5720
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005721#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005722 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5723 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005724 if (wpa_s->ignore_auth_resp) {
5725 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5726 return;
5727 }
5728#endif /* CONFIG_TESTING_OPTIONS */
5729
Jouni Malinena05074c2012-12-21 21:35:35 +02005730 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5731 (wpa_s->last_eapol_matches_bssid &&
5732#ifdef CONFIG_AP
5733 !wpa_s->ap_iface &&
5734#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005735 !ether_addr_equal(src_addr, connected_addr))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005736 /*
5737 * There is possible race condition between receiving the
5738 * association event and the EAPOL frame since they are coming
5739 * through different paths from the driver. In order to avoid
5740 * issues in trying to process the EAPOL frame before receiving
5741 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005742 * the association event is received. This may also be needed in
5743 * driver-based roaming case, so also use src_addr != BSSID as a
5744 * trigger if we have previously confirmed that the
5745 * Authenticator uses BSSID as the src_addr (which is not the
5746 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005747 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005748 wpa_dbg(wpa_s, MSG_DEBUG,
5749 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5750 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005751 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005752 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005753 wpabuf_free(wpa_s->pending_eapol_rx);
5754 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5755 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005756 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005757 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5758 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005759 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005760 }
5761 return;
5762 }
5763
Jouni Malinena05074c2012-12-21 21:35:35 +02005764 wpa_s->last_eapol_matches_bssid =
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005765 ether_addr_equal(src_addr, connected_addr);
Jouni Malinena05074c2012-12-21 21:35:35 +02005766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005767#ifdef CONFIG_AP
5768 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005769 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5770 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005771 return;
5772 }
5773#endif /* CONFIG_AP */
5774
5775 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5776 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5777 "no key management is configured");
5778 return;
5779 }
5780
5781 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005782 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005783 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5784 wpa_s->wpa_state != WPA_COMPLETED) &&
5785 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005786 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005787 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005788 int timeout = 10;
5789
5790 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5791 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5792 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5793 /* Use longer timeout for IEEE 802.1X/EAP */
5794 timeout = 70;
5795 }
5796
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005797#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005798 if (wpa_s->current_ssid && wpa_s->current_bss &&
5799 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5800 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5801 /*
5802 * Use shorter timeout if going through WPS AP iteration
5803 * for PIN config method with an AP that does not
5804 * advertise Selected Registrar.
5805 */
5806 struct wpabuf *wps_ie;
5807
5808 wps_ie = wpa_bss_get_vendor_ie_multi(
5809 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5810 if (wps_ie &&
5811 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5812 timeout = 10;
5813 wpabuf_free(wps_ie);
5814 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005815#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005816
5817 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005818 }
5819 wpa_s->eapol_received++;
5820
5821 if (wpa_s->countermeasures) {
5822 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5823 "EAPOL packet");
5824 return;
5825 }
5826
5827#ifdef CONFIG_IBSS_RSN
5828 if (wpa_s->current_ssid &&
5829 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005830 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5831 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005832 return;
5833 }
5834#endif /* CONFIG_IBSS_RSN */
5835
5836 /* Source address of the incoming EAPOL frame could be compared to the
5837 * current BSSID. However, it is possible that a centralized
5838 * Authenticator could be using another MAC address than the BSSID of
5839 * an AP, so just allow any address to be used for now. The replies are
5840 * still sent to the current BSSID (if available), though. */
5841
5842 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5843 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005844 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5845 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005846 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5847 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005848 return;
5849 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005850 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005851 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005852 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5853 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005854 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005855 * handshake processing which would normally set portValid. We
5856 * need this to allow the EAPOL state machines to be completed
5857 * without going through EAPOL-Key handshake.
5858 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005859 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005860 }
5861}
5862
5863
Sunil8cd6f4d2022-06-28 18:40:46 +00005864static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5865 const u8 *buf, size_t len)
5866{
5867 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5868 FRAME_ENCRYPTION_UNKNOWN);
5869}
5870
5871
Hai Shalomb755a2a2020-04-23 21:49:02 -07005872static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5873{
5874 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5875 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5876}
5877
5878
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005879int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005881 u8 prev_mac_addr[ETH_ALEN];
5882
5883 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5884
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005885 if ((!wpa_s->p2p_mgmt ||
5886 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5887 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005888 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005889 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5890 wpa_drv_get_mac_addr(wpa_s),
5891 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005892 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005893 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005894 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005895 if (wpa_s->l2 == NULL)
5896 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005897
5898 if (l2_packet_set_packet_filter(wpa_s->l2,
5899 L2_PACKET_FILTER_PKTTYPE))
5900 wpa_dbg(wpa_s, MSG_DEBUG,
5901 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005902
5903 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5904 wpa_msg(wpa_s, MSG_ERROR,
5905 "Failed to get own L2 address");
5906 return -1;
5907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908 } else {
5909 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5910 if (addr)
5911 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5912 }
5913
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005914 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005915 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005916
Hai Shalomc3565922019-10-28 11:58:20 -07005917#ifdef CONFIG_FST
5918 if (wpa_s->fst)
5919 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5920#endif /* CONFIG_FST */
5921
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005922 if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00005923 wpas_notify_mac_address_changed(wpa_s);
5924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005925 return 0;
5926}
5927
5928
Dmitry Shmidt04949592012-07-19 12:16:46 -07005929static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5930 const u8 *buf, size_t len)
5931{
5932 struct wpa_supplicant *wpa_s = ctx;
5933 const struct l2_ethhdr *eth;
5934
5935 if (len < sizeof(*eth))
5936 return;
5937 eth = (const struct l2_ethhdr *) buf;
5938
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005939 if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005940 !(eth->h_dest[0] & 0x01)) {
5941 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5942 " (bridge - not for this interface - ignore)",
5943 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5944 return;
5945 }
5946
5947 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5948 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5949 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005950 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005951}
5952
5953
Hai Shalom899fcc72020-10-19 14:38:18 -07005954int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5955 const char *bridge_ifname)
5956{
5957 if (wpa_s->wpa_state > WPA_SCANNING)
5958 return -EBUSY;
5959
5960 if (bridge_ifname &&
5961 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5962 return -EINVAL;
5963
5964 if (!bridge_ifname)
5965 bridge_ifname = "";
5966
5967 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5968 return 0;
5969
5970 if (wpa_s->l2_br) {
5971 l2_packet_deinit(wpa_s->l2_br);
5972 wpa_s->l2_br = NULL;
5973 }
5974
5975 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5976 sizeof(wpa_s->bridge_ifname));
5977
5978 if (wpa_s->bridge_ifname[0]) {
5979 wpa_dbg(wpa_s, MSG_DEBUG,
5980 "Receiving packets from bridge interface '%s'",
5981 wpa_s->bridge_ifname);
5982 wpa_s->l2_br = l2_packet_init_bridge(
5983 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5984 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5985 if (!wpa_s->l2_br) {
5986 wpa_msg(wpa_s, MSG_ERROR,
5987 "Failed to open l2_packet connection for the bridge interface '%s'",
5988 wpa_s->bridge_ifname);
5989 goto fail;
5990 }
5991 }
5992
5993#ifdef CONFIG_TDLS
5994 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5995 goto fail;
5996#endif /* CONFIG_TDLS */
5997
5998 return 0;
5999fail:
6000 wpa_s->bridge_ifname[0] = 0;
6001 if (wpa_s->l2_br) {
6002 l2_packet_deinit(wpa_s->l2_br);
6003 wpa_s->l2_br = NULL;
6004 }
6005#ifdef CONFIG_TDLS
6006 if (!wpa_s->p2p_mgmt)
6007 wpa_tdls_init(wpa_s->wpa);
6008#endif /* CONFIG_TDLS */
6009 return -EIO;
6010}
6011
6012
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006013/**
6014 * wpa_supplicant_driver_init - Initialize driver interface parameters
6015 * @wpa_s: Pointer to wpa_supplicant data
6016 * Returns: 0 on success, -1 on failure
6017 *
6018 * This function is called to initialize driver interface parameters.
6019 * wpa_drv_init() must have been called before this function to initialize the
6020 * driver interface.
6021 */
6022int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
6023{
6024 static int interface_count = 0;
6025
6026 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
6027 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006028
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006029 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
6030 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006031 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006032 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
6033
Hai Shalomb755a2a2020-04-23 21:49:02 -07006034 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
6036 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006037 wpa_s->l2_br = l2_packet_init_bridge(
6038 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
6039 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006040 if (wpa_s->l2_br == NULL) {
6041 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
6042 "connection for the bridge interface '%s'",
6043 wpa_s->bridge_ifname);
6044 return -1;
6045 }
6046 }
6047
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006048 if (wpa_s->conf->ap_scan == 2 &&
6049 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
6050 wpa_printf(MSG_INFO,
6051 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
6052 }
6053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006054 wpa_clear_keys(wpa_s, NULL);
6055
6056 /* Make sure that TKIP countermeasures are not left enabled (could
6057 * happen if wpa_supplicant is killed during countermeasures. */
6058 wpa_drv_set_countermeasures(wpa_s, 0);
6059
6060 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
6061 wpa_drv_flush_pmkid(wpa_s);
6062
6063 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006064 wpa_s->prev_scan_wildcard = 0;
6065
Dmitry Shmidt04949592012-07-19 12:16:46 -07006066 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08006067 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6068 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
6069 interface_count = 0;
6070 }
Keith Mok4389c282022-11-23 21:36:48 +00006071#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08006072 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07006073 wpa_supplicant_delayed_sched_scan(wpa_s,
6074 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006075 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07006076 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006077 100000);
Keith Mok4389c282022-11-23 21:36:48 +00006078#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006079 interface_count++;
6080 } else
6081 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
6082
6083 return 0;
6084}
6085
6086
6087static int wpa_supplicant_daemon(const char *pid_file)
6088{
6089 wpa_printf(MSG_DEBUG, "Daemonize..");
6090 return os_daemonize(pid_file);
6091}
6092
6093
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006094static struct wpa_supplicant *
6095wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006096{
6097 struct wpa_supplicant *wpa_s;
6098
6099 wpa_s = os_zalloc(sizeof(*wpa_s));
6100 if (wpa_s == NULL)
6101 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006102 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006103 wpa_s->scan_interval = 5;
6104 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006105 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006106 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006107 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08006108 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006109
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006110 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08006111 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07006112#ifdef CONFIG_TESTING_OPTIONS
6113 dl_list_init(&wpa_s->drv_signal_override);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006114 wpa_s->test_assoc_comeback_type = -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07006115#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006116#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08006117 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006118#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00006119 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006121 return wpa_s;
6122}
6123
6124
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006125#ifdef CONFIG_HT_OVERRIDES
6126
6127static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
6128 struct ieee80211_ht_capabilities *htcaps,
6129 struct ieee80211_ht_capabilities *htcaps_mask,
6130 const char *ht_mcs)
6131{
6132 /* parse ht_mcs into hex array */
6133 int i;
6134 const char *tmp = ht_mcs;
6135 char *end = NULL;
6136
6137 /* If ht_mcs is null, do not set anything */
6138 if (!ht_mcs)
6139 return 0;
6140
6141 /* This is what we are setting in the kernel */
6142 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
6143
6144 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
6145
6146 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08006147 long v;
6148
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006149 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08006150 v = strtol(tmp, &end, 16);
6151
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006152 if (errno == 0) {
6153 wpa_msg(wpa_s, MSG_DEBUG,
6154 "htcap value[%i]: %ld end: %p tmp: %p",
6155 i, v, end, tmp);
6156 if (end == tmp)
6157 break;
6158
6159 htcaps->supported_mcs_set[i] = v;
6160 tmp = end;
6161 } else {
6162 wpa_msg(wpa_s, MSG_ERROR,
6163 "Failed to parse ht-mcs: %s, error: %s\n",
6164 ht_mcs, strerror(errno));
6165 return -1;
6166 }
6167 }
6168
6169 /*
6170 * If we were able to parse any values, then set mask for the MCS set.
6171 */
6172 if (i) {
6173 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
6174 IEEE80211_HT_MCS_MASK_LEN - 1);
6175 /* skip the 3 reserved bits */
6176 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
6177 0x1f;
6178 }
6179
6180 return 0;
6181}
6182
6183
6184static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
6185 struct ieee80211_ht_capabilities *htcaps,
6186 struct ieee80211_ht_capabilities *htcaps_mask,
6187 int disabled)
6188{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006189 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006190
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006191 if (disabled == -1)
6192 return 0;
6193
Hai Shalom74f70d42019-02-11 14:42:39 -08006194 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
6195
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006196 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
6197 htcaps_mask->ht_capabilities_info |= msk;
6198 if (disabled)
6199 htcaps->ht_capabilities_info &= msk;
6200 else
6201 htcaps->ht_capabilities_info |= msk;
6202
6203 return 0;
6204}
6205
6206
6207static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
6208 struct ieee80211_ht_capabilities *htcaps,
6209 struct ieee80211_ht_capabilities *htcaps_mask,
6210 int factor)
6211{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006212 if (factor == -1)
6213 return 0;
6214
Hai Shalom74f70d42019-02-11 14:42:39 -08006215 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
6216
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006217 if (factor < 0 || factor > 3) {
6218 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
6219 "Must be 0-3 or -1", factor);
6220 return -EINVAL;
6221 }
6222
6223 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
6224 htcaps->a_mpdu_params &= ~0x3;
6225 htcaps->a_mpdu_params |= factor & 0x3;
6226
6227 return 0;
6228}
6229
6230
6231static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
6232 struct ieee80211_ht_capabilities *htcaps,
6233 struct ieee80211_ht_capabilities *htcaps_mask,
6234 int density)
6235{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006236 if (density == -1)
6237 return 0;
6238
Hai Shalom74f70d42019-02-11 14:42:39 -08006239 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
6240
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006241 if (density < 0 || density > 7) {
6242 wpa_msg(wpa_s, MSG_ERROR,
6243 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6244 density);
6245 return -EINVAL;
6246 }
6247
6248 htcaps_mask->a_mpdu_params |= 0x1C;
6249 htcaps->a_mpdu_params &= ~(0x1C);
6250 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6251
6252 return 0;
6253}
6254
6255
6256static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6257 struct ieee80211_ht_capabilities *htcaps,
6258 struct ieee80211_ht_capabilities *htcaps_mask,
6259 int disabled)
6260{
Hai Shalom74f70d42019-02-11 14:42:39 -08006261 if (disabled)
6262 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006263
Paul Stewart092955c2017-02-06 09:13:09 -08006264 set_disable_ht40(htcaps, disabled);
6265 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006266
6267 return 0;
6268}
6269
6270
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006271static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6272 struct ieee80211_ht_capabilities *htcaps,
6273 struct ieee80211_ht_capabilities *htcaps_mask,
6274 int disabled)
6275{
6276 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006277 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6278 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006279
Hai Shalom74f70d42019-02-11 14:42:39 -08006280 if (disabled)
6281 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006282
6283 if (disabled)
6284 htcaps->ht_capabilities_info &= ~msk;
6285 else
6286 htcaps->ht_capabilities_info |= msk;
6287
6288 htcaps_mask->ht_capabilities_info |= msk;
6289
6290 return 0;
6291}
6292
6293
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006294static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6295 struct ieee80211_ht_capabilities *htcaps,
6296 struct ieee80211_ht_capabilities *htcaps_mask,
6297 int disabled)
6298{
6299 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006300 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006301
Hai Shalom74f70d42019-02-11 14:42:39 -08006302 if (disabled)
6303 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006304
6305 if (disabled)
6306 htcaps->ht_capabilities_info &= ~msk;
6307 else
6308 htcaps->ht_capabilities_info |= msk;
6309
6310 htcaps_mask->ht_capabilities_info |= msk;
6311
6312 return 0;
6313}
6314
6315
Hai Shalom74f70d42019-02-11 14:42:39 -08006316static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6317 struct ieee80211_ht_capabilities *htcaps,
6318 struct ieee80211_ht_capabilities *htcaps_mask,
6319 int tx_stbc)
6320{
6321 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6322
6323 if (tx_stbc == -1)
6324 return 0;
6325
6326 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6327
6328 if (tx_stbc < 0 || tx_stbc > 1) {
6329 wpa_msg(wpa_s, MSG_ERROR,
6330 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6331 return -EINVAL;
6332 }
6333
6334 htcaps_mask->ht_capabilities_info |= msk;
6335 htcaps->ht_capabilities_info &= ~msk;
6336 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6337
6338 return 0;
6339}
6340
6341
6342static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6343 struct ieee80211_ht_capabilities *htcaps,
6344 struct ieee80211_ht_capabilities *htcaps_mask,
6345 int rx_stbc)
6346{
6347 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6348
6349 if (rx_stbc == -1)
6350 return 0;
6351
6352 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6353
6354 if (rx_stbc < 0 || rx_stbc > 3) {
6355 wpa_msg(wpa_s, MSG_ERROR,
6356 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6357 return -EINVAL;
6358 }
6359
6360 htcaps_mask->ht_capabilities_info |= msk;
6361 htcaps->ht_capabilities_info &= ~msk;
6362 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6363
6364 return 0;
6365}
6366
6367
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006368void wpa_supplicant_apply_ht_overrides(
6369 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6370 struct wpa_driver_associate_params *params)
6371{
6372 struct ieee80211_ht_capabilities *htcaps;
6373 struct ieee80211_ht_capabilities *htcaps_mask;
6374
6375 if (!ssid)
6376 return;
6377
6378 params->disable_ht = ssid->disable_ht;
6379 if (!params->htcaps || !params->htcaps_mask)
6380 return;
6381
6382 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6383 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6384 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6385 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6386 ssid->disable_max_amsdu);
6387 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6388 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6389 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006390 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006391 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006392 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6393 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006394
6395 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006396 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006397 htcaps->ht_capabilities_info |= bit;
6398 htcaps_mask->ht_capabilities_info |= bit;
6399 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006400}
6401
6402#endif /* CONFIG_HT_OVERRIDES */
6403
6404
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006405#ifdef CONFIG_VHT_OVERRIDES
6406void wpa_supplicant_apply_vht_overrides(
6407 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6408 struct wpa_driver_associate_params *params)
6409{
6410 struct ieee80211_vht_capabilities *vhtcaps;
6411 struct ieee80211_vht_capabilities *vhtcaps_mask;
6412
6413 if (!ssid)
6414 return;
6415
6416 params->disable_vht = ssid->disable_vht;
6417
6418 vhtcaps = (void *) params->vhtcaps;
6419 vhtcaps_mask = (void *) params->vhtcaps_mask;
6420
6421 if (!vhtcaps || !vhtcaps_mask)
6422 return;
6423
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006424 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6425 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006426
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006427#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006428 if (ssid->disable_sgi) {
6429 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6430 VHT_CAP_SHORT_GI_160);
6431 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6432 VHT_CAP_SHORT_GI_160);
6433 wpa_msg(wpa_s, MSG_DEBUG,
6434 "disable-sgi override specified, vht-caps: 0x%x",
6435 vhtcaps->vht_capabilities_info);
6436 }
6437
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006438 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006439 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6440 int max_ampdu;
6441
6442 max_ampdu = (ssid->vht_capa &
6443 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6444 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006445
6446 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6447 wpa_set_ampdu_factor(wpa_s,
6448 (void *) params->htcaps,
6449 (void *) params->htcaps_mask,
6450 max_ampdu);
6451 }
6452#endif /* CONFIG_HT_OVERRIDES */
6453
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006454#define OVERRIDE_MCS(i) \
6455 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6456 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006457 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006458 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006459 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6460 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006461 } \
6462 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6463 vhtcaps_mask->vht_supported_mcs_set.rx_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.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006466 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6467 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006468 }
6469
6470 OVERRIDE_MCS(1);
6471 OVERRIDE_MCS(2);
6472 OVERRIDE_MCS(3);
6473 OVERRIDE_MCS(4);
6474 OVERRIDE_MCS(5);
6475 OVERRIDE_MCS(6);
6476 OVERRIDE_MCS(7);
6477 OVERRIDE_MCS(8);
6478}
6479#endif /* CONFIG_VHT_OVERRIDES */
6480
6481
Hai Shalomfdcde762020-04-02 11:19:20 -07006482#ifdef CONFIG_HE_OVERRIDES
6483void wpa_supplicant_apply_he_overrides(
6484 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6485 struct wpa_driver_associate_params *params)
6486{
6487 if (!ssid)
6488 return;
6489
6490 params->disable_he = ssid->disable_he;
6491}
6492#endif /* CONFIG_HE_OVERRIDES */
6493
6494
Sunil Ravi77d572f2023-01-17 23:58:31 +00006495void wpa_supplicant_apply_eht_overrides(
6496 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6497 struct wpa_driver_associate_params *params)
6498{
6499 if (!ssid)
6500 return;
6501
6502 params->disable_eht = ssid->disable_eht;
6503}
6504
6505
Dmitry Shmidt04949592012-07-19 12:16:46 -07006506static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6507{
6508#ifdef PCSC_FUNCS
6509 size_t len;
6510
6511 if (!wpa_s->conf->pcsc_reader)
6512 return 0;
6513
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006514 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006515 if (!wpa_s->scard)
6516 return 1;
6517
6518 if (wpa_s->conf->pcsc_pin &&
6519 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6520 scard_deinit(wpa_s->scard);
6521 wpa_s->scard = NULL;
6522 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6523 return -1;
6524 }
6525
6526 len = sizeof(wpa_s->imsi) - 1;
6527 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6528 scard_deinit(wpa_s->scard);
6529 wpa_s->scard = NULL;
6530 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6531 return -1;
6532 }
6533 wpa_s->imsi[len] = '\0';
6534
6535 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6536
6537 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6538 wpa_s->imsi, wpa_s->mnc_len);
6539
6540 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6541 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6542#endif /* PCSC_FUNCS */
6543
6544 return 0;
6545}
6546
6547
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006548int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6549{
6550 char *val, *pos;
6551
6552 ext_password_deinit(wpa_s->ext_pw);
6553 wpa_s->ext_pw = NULL;
6554 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6555
6556 if (!wpa_s->conf->ext_password_backend)
6557 return 0;
6558
6559 val = os_strdup(wpa_s->conf->ext_password_backend);
6560 if (val == NULL)
6561 return -1;
6562 pos = os_strchr(val, ':');
6563 if (pos)
6564 *pos++ = '\0';
6565
6566 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6567
6568 wpa_s->ext_pw = ext_password_init(val, pos);
6569 os_free(val);
6570 if (wpa_s->ext_pw == NULL) {
6571 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6572 return -1;
6573 }
6574 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6575
6576 return 0;
6577}
6578
6579
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006580#ifdef CONFIG_FST
6581
6582static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6583{
6584 struct wpa_supplicant *wpa_s = ctx;
6585
6586 return (is_zero_ether_addr(wpa_s->bssid) ||
6587 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6588}
6589
6590
6591static void wpas_fst_get_channel_info_cb(void *ctx,
6592 enum hostapd_hw_mode *hw_mode,
6593 u8 *channel)
6594{
6595 struct wpa_supplicant *wpa_s = ctx;
6596
6597 if (wpa_s->current_bss) {
6598 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6599 channel);
6600 } else if (wpa_s->hw.num_modes) {
6601 *hw_mode = wpa_s->hw.modes[0].mode;
6602 } else {
6603 WPA_ASSERT(0);
6604 *hw_mode = 0;
6605 }
6606}
6607
6608
6609static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6610{
6611 struct wpa_supplicant *wpa_s = ctx;
6612
6613 *modes = wpa_s->hw.modes;
6614 return wpa_s->hw.num_modes;
6615}
6616
6617
6618static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6619{
6620 struct wpa_supplicant *wpa_s = ctx;
6621
6622 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6623 wpa_s->fst_ies = fst_ies;
6624}
6625
6626
6627static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6628{
6629 struct wpa_supplicant *wpa_s = ctx;
6630
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006631 if (!ether_addr_equal(wpa_s->bssid, da)) {
Paul Stewart092955c2017-02-06 09:13:09 -08006632 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6633 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6634 return -1;
6635 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006636 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006637 wpa_s->own_addr, wpa_s->bssid,
6638 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006639 0);
6640}
6641
6642
6643static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6644{
6645 struct wpa_supplicant *wpa_s = ctx;
6646
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006647 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006648 return wpa_s->received_mb_ies;
6649}
6650
6651
6652static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6653 const u8 *buf, size_t size)
6654{
6655 struct wpa_supplicant *wpa_s = ctx;
6656 struct mb_ies_info info;
6657
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006658 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006659
6660 if (!mb_ies_info_by_ies(&info, buf, size)) {
6661 wpabuf_free(wpa_s->received_mb_ies);
6662 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6663 }
6664}
6665
6666
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006667static const u8 * wpas_fst_get_peer_first(void *ctx,
6668 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006669 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006670{
6671 struct wpa_supplicant *wpa_s = ctx;
6672
6673 *get_ctx = NULL;
6674 if (!is_zero_ether_addr(wpa_s->bssid))
6675 return (wpa_s->received_mb_ies || !mb_only) ?
6676 wpa_s->bssid : NULL;
6677 return NULL;
6678}
6679
6680
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006681static const u8 * wpas_fst_get_peer_next(void *ctx,
6682 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006683 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006684{
6685 return NULL;
6686}
6687
6688void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6689 struct fst_wpa_obj *iface_obj)
6690{
Sunil8cd6f4d2022-06-28 18:40:46 +00006691 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006692 iface_obj->ctx = wpa_s;
6693 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6694 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6695 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6696 iface_obj->set_ies = wpas_fst_set_ies_cb;
6697 iface_obj->send_action = wpas_fst_send_action_cb;
6698 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6699 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6700 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6701 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6702}
6703#endif /* CONFIG_FST */
6704
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006705static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006706 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006707{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006708 struct wowlan_triggers *triggers;
6709 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006710
6711 if (!wpa_s->conf->wowlan_triggers)
6712 return 0;
6713
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006714 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6715 if (triggers) {
6716 ret = wpa_drv_wowlan(wpa_s, triggers);
6717 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006718 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006719 return ret;
6720}
6721
6722
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006723enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006724{
6725 if (freq < 3000)
6726 return BAND_2_4_GHZ;
6727 if (freq > 50000)
6728 return BAND_60_GHZ;
6729 return BAND_5_GHZ;
6730}
6731
6732
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006733unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006734{
6735 int i;
6736 unsigned int band = 0;
6737
6738 if (freqs) {
6739 /* freqs are specified for the radio work */
6740 for (i = 0; freqs[i]; i++)
6741 band |= wpas_freq_to_band(freqs[i]);
6742 } else {
6743 /*
6744 * freqs are not specified, implies all
6745 * the supported freqs by HW
6746 */
6747 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6748 if (wpa_s->hw.modes[i].num_channels != 0) {
6749 if (wpa_s->hw.modes[i].mode ==
6750 HOSTAPD_MODE_IEEE80211B ||
6751 wpa_s->hw.modes[i].mode ==
6752 HOSTAPD_MODE_IEEE80211G)
6753 band |= BAND_2_4_GHZ;
6754 else if (wpa_s->hw.modes[i].mode ==
6755 HOSTAPD_MODE_IEEE80211A)
6756 band |= BAND_5_GHZ;
6757 else if (wpa_s->hw.modes[i].mode ==
6758 HOSTAPD_MODE_IEEE80211AD)
6759 band |= BAND_60_GHZ;
6760 else if (wpa_s->hw.modes[i].mode ==
6761 HOSTAPD_MODE_IEEE80211ANY)
6762 band = BAND_2_4_GHZ | BAND_5_GHZ |
6763 BAND_60_GHZ;
6764 }
6765 }
6766 }
6767
6768 return band;
6769}
6770
6771
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006772static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6773 const char *rn)
6774{
6775 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6776 struct wpa_radio *radio;
6777
6778 while (rn && iface) {
6779 radio = iface->radio;
6780 if (radio && os_strcmp(rn, radio->name) == 0) {
6781 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6782 wpa_s->ifname, rn);
6783 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6784 return radio;
6785 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006786
6787 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006788 }
6789
6790 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6791 wpa_s->ifname, rn ? rn : "N/A");
6792 radio = os_zalloc(sizeof(*radio));
6793 if (radio == NULL)
6794 return NULL;
6795
6796 if (rn)
6797 os_strlcpy(radio->name, rn, sizeof(radio->name));
6798 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006799 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006800 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6801
6802 return radio;
6803}
6804
6805
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006806static void radio_work_free(struct wpa_radio_work *work)
6807{
6808 if (work->wpa_s->scan_work == work) {
6809 /* This should not really happen. */
6810 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6811 work->type, work, work->started);
6812 work->wpa_s->scan_work = NULL;
6813 }
6814
6815#ifdef CONFIG_P2P
6816 if (work->wpa_s->p2p_scan_work == work) {
6817 /* This should not really happen. */
6818 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6819 work->type, work, work->started);
6820 work->wpa_s->p2p_scan_work = NULL;
6821 }
6822#endif /* CONFIG_P2P */
6823
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006824 if (work->started) {
6825 work->wpa_s->radio->num_active_works--;
6826 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006827 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006828 work->type, work,
6829 work->wpa_s->radio->num_active_works);
6830 }
6831
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006832 dl_list_del(&work->list);
6833 os_free(work);
6834}
6835
6836
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006837static int radio_work_is_connect(struct wpa_radio_work *work)
6838{
6839 return os_strcmp(work->type, "sme-connect") == 0 ||
6840 os_strcmp(work->type, "connect") == 0;
6841}
6842
6843
6844static int radio_work_is_scan(struct wpa_radio_work *work)
6845{
6846 return os_strcmp(work->type, "scan") == 0 ||
6847 os_strcmp(work->type, "p2p-scan") == 0;
6848}
6849
6850
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006851static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6852{
6853 struct wpa_radio_work *active_work = NULL;
6854 struct wpa_radio_work *tmp;
6855
6856 /* Get the active work to know the type and band. */
6857 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6858 if (tmp->started) {
6859 active_work = tmp;
6860 break;
6861 }
6862 }
6863
6864 if (!active_work) {
6865 /* No active work, start one */
6866 radio->num_active_works = 0;
6867 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6868 list) {
6869 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006870 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006871 (((struct wpa_driver_scan_params *)
6872 tmp->ctx)->only_new_results ||
6873 tmp->wpa_s->clear_driver_scan_cache))
6874 continue;
6875 return tmp;
6876 }
6877 return NULL;
6878 }
6879
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006880 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006881 /*
6882 * If the active work is either connect or sme-connect,
6883 * do not parallelize them with other radio works.
6884 */
6885 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6886 "Do not parallelize radio work with %s",
6887 active_work->type);
6888 return NULL;
6889 }
6890
6891 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6892 if (tmp->started)
6893 continue;
6894
6895 /*
6896 * If connect or sme-connect are enqueued, parallelize only
6897 * those operations ahead of them in the queue.
6898 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006899 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006900 break;
6901
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006902 /* Serialize parallel scan and p2p_scan operations on the same
6903 * interface since the driver_nl80211 mechanism for tracking
6904 * scan cookies does not yet have support for this. */
6905 if (active_work->wpa_s == tmp->wpa_s &&
6906 radio_work_is_scan(active_work) &&
6907 radio_work_is_scan(tmp)) {
6908 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6909 "Do not start work '%s' when another work '%s' is already scheduled",
6910 tmp->type, active_work->type);
6911 continue;
6912 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006913 /*
6914 * Check that the radio works are distinct and
6915 * on different bands.
6916 */
6917 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6918 (active_work->bands != tmp->bands)) {
6919 /*
6920 * If a scan has to be scheduled through nl80211 scan
6921 * interface and if an external scan is already running,
6922 * do not schedule the scan since it is likely to get
6923 * rejected by kernel.
6924 */
6925 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006926 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006927 (((struct wpa_driver_scan_params *)
6928 tmp->ctx)->only_new_results ||
6929 tmp->wpa_s->clear_driver_scan_cache))
6930 continue;
6931
6932 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6933 "active_work:%s new_work:%s",
6934 active_work->type, tmp->type);
6935 return tmp;
6936 }
6937 }
6938
6939 /* Did not find a radio work to schedule in parallel. */
6940 return NULL;
6941}
6942
6943
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006944static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6945{
6946 struct wpa_radio *radio = eloop_ctx;
6947 struct wpa_radio_work *work;
6948 struct os_reltime now, diff;
6949 struct wpa_supplicant *wpa_s;
6950
6951 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006952 if (work == NULL) {
6953 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006954 return;
6955 }
6956
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006957 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6958 radio_list);
6959
6960 if (!(wpa_s &&
6961 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6962 if (work->started)
6963 return; /* already started and still in progress */
6964
Hai Shalom60840252021-02-19 19:02:11 -08006965 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006966 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6967 return;
6968 }
6969 } else {
6970 work = NULL;
6971 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6972 /* get the work to schedule next */
6973 work = radio_work_get_next_work(radio);
6974 }
6975 if (!work)
6976 return;
6977 }
6978
6979 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006980 os_get_reltime(&now);
6981 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006982 wpa_dbg(wpa_s, MSG_DEBUG,
6983 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006984 work->type, work, diff.sec, diff.usec);
6985 work->started = 1;
6986 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006987 radio->num_active_works++;
6988
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006989 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006990
6991 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6992 radio->num_active_works < MAX_ACTIVE_WORKS)
6993 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006994}
6995
6996
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006997/*
6998 * This function removes both started and pending radio works running on
6999 * the provided interface's radio.
7000 * Prior to the removal of the radio work, its callback (cb) is called with
7001 * deinit set to be 1. Each work's callback is responsible for clearing its
7002 * internal data and restoring to a correct state.
7003 * @wpa_s: wpa_supplicant data
7004 * @type: type of works to be removed
7005 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
7006 * this interface's works.
7007 */
7008void radio_remove_works(struct wpa_supplicant *wpa_s,
7009 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007010{
7011 struct wpa_radio_work *work, *tmp;
7012 struct wpa_radio *radio = wpa_s->radio;
7013
7014 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
7015 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007016 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007017 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007018
7019 /* skip other ifaces' works */
7020 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007021 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007022
7023 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
7024 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007025 work->cb(work, 1);
7026 radio_work_free(work);
7027 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007028
7029 /* in case we removed the started work */
7030 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007031}
7032
7033
Roshan Pius3a1667e2018-07-03 15:17:14 -07007034void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
7035{
7036 struct wpa_radio_work *work;
7037 struct wpa_radio *radio = wpa_s->radio;
7038
7039 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7040 if (work->ctx != ctx)
7041 continue;
7042 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
7043 work->type, work, work->started ? " (started)" : "");
7044 radio_work_free(work);
7045 break;
7046 }
7047}
7048
7049
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007050static void radio_remove_interface(struct wpa_supplicant *wpa_s)
7051{
7052 struct wpa_radio *radio = wpa_s->radio;
7053
7054 if (!radio)
7055 return;
7056
7057 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
7058 wpa_s->ifname, radio->name);
7059 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007060 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08007061 /* If the interface that triggered the external scan was removed, the
7062 * external scan is no longer running. */
7063 if (wpa_s == radio->external_scan_req_interface)
7064 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007065 wpa_s->radio = NULL;
7066 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007067 return; /* Interfaces remain for this radio */
7068
7069 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007070 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007071 os_free(radio);
7072}
7073
7074
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007075void radio_work_check_next(struct wpa_supplicant *wpa_s)
7076{
7077 struct wpa_radio *radio = wpa_s->radio;
7078
7079 if (dl_list_empty(&radio->work))
7080 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007081 if (wpa_s->ext_work_in_progress) {
7082 wpa_printf(MSG_DEBUG,
7083 "External radio work in progress - delay start of pending item");
7084 return;
7085 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007086 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
7087 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
7088}
7089
7090
7091/**
7092 * radio_add_work - Add a radio work item
7093 * @wpa_s: Pointer to wpa_supplicant data
7094 * @freq: Frequency of the offchannel operation in MHz or 0
7095 * @type: Unique identifier for each type of work
7096 * @next: Force as the next work to be executed
7097 * @cb: Callback function for indicating when radio is available
7098 * @ctx: Context pointer for the work (work->ctx in cb())
7099 * Returns: 0 on success, -1 on failure
7100 *
7101 * This function is used to request time for an operation that requires
7102 * exclusive radio control. Once the radio is available, the registered callback
7103 * function will be called. radio_work_done() must be called once the exclusive
7104 * radio operation has been completed, so that the radio is freed for other
7105 * operations. The special case of deinit=1 is used to free the context data
7106 * during interface removal. That does not allow the callback function to start
7107 * the radio operation, i.e., it must free any resources allocated for the radio
7108 * work and return.
7109 *
7110 * The @freq parameter can be used to indicate a single channel on which the
7111 * offchannel operation will occur. This may allow multiple radio work
7112 * operations to be performed in parallel if they apply for the same channel.
7113 * Setting this to 0 indicates that the work item may use multiple channels or
7114 * requires exclusive control of the radio.
7115 */
7116int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
7117 const char *type, int next,
7118 void (*cb)(struct wpa_radio_work *work, int deinit),
7119 void *ctx)
7120{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007121 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007122 struct wpa_radio_work *work;
7123 int was_empty;
7124
7125 work = os_zalloc(sizeof(*work));
7126 if (work == NULL)
7127 return -1;
7128 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
7129 os_get_reltime(&work->time);
7130 work->freq = freq;
7131 work->type = type;
7132 work->wpa_s = wpa_s;
7133 work->cb = cb;
7134 work->ctx = ctx;
7135
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007136 if (freq)
7137 work->bands = wpas_freq_to_band(freq);
7138 else if (os_strcmp(type, "scan") == 0 ||
7139 os_strcmp(type, "p2p-scan") == 0)
7140 work->bands = wpas_get_bands(wpa_s,
7141 ((struct wpa_driver_scan_params *)
7142 ctx)->freqs);
7143 else
7144 work->bands = wpas_get_bands(wpa_s, NULL);
7145
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007146 was_empty = dl_list_empty(&wpa_s->radio->work);
7147 if (next)
7148 dl_list_add(&wpa_s->radio->work, &work->list);
7149 else
7150 dl_list_add_tail(&wpa_s->radio->work, &work->list);
7151 if (was_empty) {
7152 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
7153 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007154 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
7155 && radio->num_active_works < MAX_ACTIVE_WORKS) {
7156 wpa_dbg(wpa_s, MSG_DEBUG,
7157 "Try to schedule a radio work (num_active_works=%u)",
7158 radio->num_active_works);
7159 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007160 }
7161
7162 return 0;
7163}
7164
7165
7166/**
7167 * radio_work_done - Indicate that a radio work item has been completed
7168 * @work: Completed work
7169 *
7170 * This function is called once the callback function registered with
7171 * radio_add_work() has completed its work.
7172 */
7173void radio_work_done(struct wpa_radio_work *work)
7174{
7175 struct wpa_supplicant *wpa_s = work->wpa_s;
7176 struct os_reltime now, diff;
7177 unsigned int started = work->started;
7178
7179 os_get_reltime(&now);
7180 os_reltime_sub(&now, &work->time, &diff);
7181 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
7182 work->type, work, started ? "done" : "canceled",
7183 diff.sec, diff.usec);
7184 radio_work_free(work);
7185 if (started)
7186 radio_work_check_next(wpa_s);
7187}
7188
7189
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007190struct wpa_radio_work *
7191radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007192{
7193 struct wpa_radio_work *work;
7194 struct wpa_radio *radio = wpa_s->radio;
7195
7196 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7197 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007198 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007199 }
7200
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007201 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007202}
7203
7204
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007205static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007206 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007207{
7208 const char *ifname, *driver, *rn;
7209
7210 driver = iface->driver;
7211next_driver:
7212 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
7213 return -1;
7214
7215 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
7216 if (wpa_s->drv_priv == NULL) {
7217 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07007218 int level = MSG_ERROR;
7219
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007220 pos = driver ? os_strchr(driver, ',') : NULL;
7221 if (pos) {
7222 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
7223 "driver interface - try next driver wrapper");
7224 driver = pos + 1;
7225 goto next_driver;
7226 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007227
7228#ifdef CONFIG_MATCH_IFACE
7229 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
7230 level = MSG_DEBUG;
7231#endif /* CONFIG_MATCH_IFACE */
7232 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007233 return -1;
7234 }
7235 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
7236 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
7237 "driver_param '%s'", wpa_s->conf->driver_param);
7238 return -1;
7239 }
7240
7241 ifname = wpa_drv_get_ifname(wpa_s);
7242 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7243 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7244 "interface name with '%s'", ifname);
7245 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7246 }
7247
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007248 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007249 if (rn && rn[0] == '\0')
7250 rn = NULL;
7251
7252 wpa_s->radio = radio_add_interface(wpa_s, rn);
7253 if (wpa_s->radio == NULL)
7254 return -1;
7255
7256 return 0;
7257}
7258
7259
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007260#ifdef CONFIG_GAS_SERVER
7261
7262static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7263 unsigned int freq, const u8 *dst,
7264 const u8 *src, const u8 *bssid,
7265 const u8 *data, size_t data_len,
7266 enum offchannel_send_action_result result)
7267{
7268 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7269 " result=%s",
7270 freq, MAC2STR(dst),
7271 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7272 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7273 "FAILED"));
7274 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7275 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7276}
7277
7278
7279static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7280 struct wpabuf *buf, unsigned int wait_time)
7281{
7282 struct wpa_supplicant *wpa_s = ctx;
7283 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7284
7285 if (wait_time > wpa_s->max_remain_on_chan)
7286 wait_time = wpa_s->max_remain_on_chan;
7287
7288 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7289 wpabuf_head(buf), wpabuf_len(buf),
7290 wait_time, wpas_gas_server_tx_status, 0);
7291}
7292
7293#endif /* CONFIG_GAS_SERVER */
7294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007296 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007297{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007298 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007299 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007300 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007301
7302 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7303 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7304 iface->confname ? iface->confname : "N/A",
7305 iface->driver ? iface->driver : "default",
7306 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7307 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7308
7309 if (iface->confname) {
7310#ifdef CONFIG_BACKEND_FILE
7311 wpa_s->confname = os_rel2abs_path(iface->confname);
7312 if (wpa_s->confname == NULL) {
7313 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7314 "for configuration file '%s'.",
7315 iface->confname);
7316 return -1;
7317 }
7318 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7319 iface->confname, wpa_s->confname);
7320#else /* CONFIG_BACKEND_FILE */
7321 wpa_s->confname = os_strdup(iface->confname);
7322#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007323 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007324 if (wpa_s->conf == NULL) {
7325 wpa_printf(MSG_ERROR, "Failed to read or parse "
7326 "configuration '%s'.", wpa_s->confname);
7327 return -1;
7328 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007329 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007330 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007331 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007332 wpa_printf(MSG_ERROR,
7333 "Failed to read or parse configuration '%s'.",
7334 wpa_s->confanother);
7335 return -1;
7336 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007337
7338 /*
7339 * Override ctrl_interface and driver_param if set on command
7340 * line.
7341 */
7342 if (iface->ctrl_interface) {
7343 os_free(wpa_s->conf->ctrl_interface);
7344 wpa_s->conf->ctrl_interface =
7345 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007346 if (!wpa_s->conf->ctrl_interface) {
7347 wpa_printf(MSG_ERROR,
7348 "Failed to duplicate control interface '%s'.",
7349 iface->ctrl_interface);
7350 return -1;
7351 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007352 }
7353
7354 if (iface->driver_param) {
7355 os_free(wpa_s->conf->driver_param);
7356 wpa_s->conf->driver_param =
7357 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007358 if (!wpa_s->conf->driver_param) {
7359 wpa_printf(MSG_ERROR,
7360 "Failed to duplicate driver param '%s'.",
7361 iface->driver_param);
7362 return -1;
7363 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007364 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007365
7366 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7367 os_free(wpa_s->conf->ctrl_interface);
7368 wpa_s->conf->ctrl_interface = NULL;
7369 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007370 } else
7371 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7372 iface->driver_param);
7373
7374 if (wpa_s->conf == NULL) {
7375 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7376 return -1;
7377 }
7378
7379 if (iface->ifname == NULL) {
7380 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7381 return -1;
7382 }
7383 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7384 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7385 iface->ifname);
7386 return -1;
7387 }
7388 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007389#ifdef CONFIG_MATCH_IFACE
7390 wpa_s->matched = iface->matched;
7391#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007392
7393 if (iface->bridge_ifname) {
7394 if (os_strlen(iface->bridge_ifname) >=
7395 sizeof(wpa_s->bridge_ifname)) {
7396 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7397 "name '%s'.", iface->bridge_ifname);
7398 return -1;
7399 }
7400 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7401 sizeof(wpa_s->bridge_ifname));
7402 }
7403
7404 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007405 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7406 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007407
7408 /* Initialize driver interface and register driver event handler before
7409 * L2 receive handler so that association events are processed before
7410 * EAPOL-Key packets if both become available for the same select()
7411 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007412 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007413 return -1;
7414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007415 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7416 return -1;
7417
7418 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7419 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7420 NULL);
7421 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7422
7423 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7424 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7425 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7426 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7427 "dot11RSNAConfigPMKLifetime");
7428 return -1;
7429 }
7430
7431 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7432 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7433 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7434 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7435 "dot11RSNAConfigPMKReauthThreshold");
7436 return -1;
7437 }
7438
7439 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7440 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7441 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7442 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7443 "dot11RSNAConfigSATimeout");
7444 return -1;
7445 }
7446
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007447 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
7448 wpa_s->conf->ft_prepend_pmkid);
7449
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007450 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7451 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007452 &wpa_s->hw.flags,
7453 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007454 if (wpa_s->hw.modes) {
7455 u16 i;
7456
7457 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7458 if (wpa_s->hw.modes[i].vht_capab) {
7459 wpa_s->hw_capab = CAPAB_VHT;
7460 break;
7461 }
7462
7463 if (wpa_s->hw.modes[i].ht_capab &
7464 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7465 wpa_s->hw_capab = CAPAB_HT40;
7466 else if (wpa_s->hw.modes[i].ht_capab &&
7467 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7468 wpa_s->hw_capab = CAPAB_HT;
7469 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007470 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007471 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007472
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007473 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7474 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007475 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007476 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007477 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007478 wpa_s->drv_enc = capa.enc;
Sunil Ravi7f769292024-07-23 22:21:32 +00007479 wpa_s->drv_key_mgmt = capa.key_mgmt;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007480 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007481 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007482 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007484 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007485 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7486 wpa_s->max_sched_scan_plan_interval =
7487 capa.max_sched_scan_plan_interval;
7488 wpa_s->max_sched_scan_plan_iterations =
7489 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007490 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7491 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007492 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7493 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007494 wpa_s->extended_capa = capa.extended_capa;
7495 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7496 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007497 wpa_s->num_multichan_concurrent =
7498 capa.num_multichan_concurrent;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007499#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007500 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007501#endif /* CONFIG_NO_WMM_AC */
Sunil Ravi89eba102022-09-13 21:04:37 -07007502 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007503
7504 if (capa.mac_addr_rand_scan_supported)
7505 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7506 if (wpa_s->sched_scan_supported &&
7507 capa.mac_addr_rand_sched_scan_supported)
7508 wpa_s->mac_addr_rand_supported |=
7509 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007510
7511 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7512 if (wpa_s->extended_capa &&
7513 wpa_s->extended_capa_len >= 3 &&
7514 wpa_s->extended_capa[2] & 0x40)
7515 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007516 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007517#ifdef CONFIG_PASN
7518 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7519#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007520 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7521 !!(wpa_s->drv_flags &
7522 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007523 if (wpa_s->max_remain_on_chan == 0)
7524 wpa_s->max_remain_on_chan = 1000;
7525
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007526 /*
7527 * Only take p2p_mgmt parameters when P2P Device is supported.
7528 * Doing it here as it determines whether l2_packet_init() will be done
7529 * during wpa_supplicant_driver_init().
7530 */
7531 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7532 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007533
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007534 if (wpa_s->num_multichan_concurrent == 0)
7535 wpa_s->num_multichan_concurrent = 1;
7536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007537 if (wpa_supplicant_driver_init(wpa_s) < 0)
7538 return -1;
7539
7540#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007541 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007542 return -1;
7543#endif /* CONFIG_TDLS */
7544
7545 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7546 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7547 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7548 return -1;
7549 }
7550
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007551#ifdef CONFIG_FST
7552 if (wpa_s->conf->fst_group_id) {
7553 struct fst_iface_cfg cfg;
7554 struct fst_wpa_obj iface_obj;
7555
7556 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7557 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7558 sizeof(cfg.group_id));
7559 cfg.priority = wpa_s->conf->fst_priority;
7560 cfg.llt = wpa_s->conf->fst_llt;
7561
7562 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7563 &iface_obj, &cfg);
7564 if (!wpa_s->fst) {
7565 wpa_msg(wpa_s, MSG_ERROR,
7566 "FST: Cannot attach iface %s to group %s",
7567 wpa_s->ifname, cfg.group_id);
7568 return -1;
7569 }
7570 }
7571#endif /* CONFIG_FST */
7572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007573 if (wpas_wps_init(wpa_s))
7574 return -1;
7575
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007576#ifdef CONFIG_GAS_SERVER
7577 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7578 if (!wpa_s->gas_server) {
7579 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7580 return -1;
7581 }
7582#endif /* CONFIG_GAS_SERVER */
7583
7584#ifdef CONFIG_DPP
7585 if (wpas_dpp_init(wpa_s) < 0)
7586 return -1;
7587#endif /* CONFIG_DPP */
7588
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007589#ifdef CONFIG_NAN_USD
7590 if (wpas_nan_usd_init(wpa_s) < 0)
7591 return -1;
7592#endif /* CONFIG_NAN_USD */
7593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007594 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7595 return -1;
7596 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7597
7598 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7599 if (wpa_s->ctrl_iface == NULL) {
7600 wpa_printf(MSG_ERROR,
7601 "Failed to initialize control interface '%s'.\n"
7602 "You may have another wpa_supplicant process "
7603 "already running or the file was\n"
7604 "left by an unclean termination of wpa_supplicant "
7605 "in which case you will need\n"
7606 "to manually remove this file before starting "
7607 "wpa_supplicant again.\n",
7608 wpa_s->conf->ctrl_interface);
7609 return -1;
7610 }
7611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007612 wpa_s->gas = gas_query_init(wpa_s);
7613 if (wpa_s->gas == NULL) {
7614 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7615 return -1;
7616 }
7617
Roshan Pius3a1667e2018-07-03 15:17:14 -07007618 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7619 wpa_s->p2p_mgmt) &&
7620 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007621 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7622 return -1;
7623 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007624
7625 if (wpa_bss_init(wpa_s) < 0)
7626 return -1;
7627
Paul Stewart092955c2017-02-06 09:13:09 -08007628#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7629#ifdef CONFIG_MESH
7630 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7631#endif /* CONFIG_MESH */
7632#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7633
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007634 /*
7635 * Set Wake-on-WLAN triggers, if configured.
7636 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7637 * have effect anyway when the interface is down).
7638 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007639 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007640 return -1;
7641
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007642#ifdef CONFIG_EAP_PROXY
7643{
7644 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007645 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7646 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007647 if (wpa_s->mnc_len > 0) {
7648 wpa_s->imsi[len] = '\0';
7649 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7650 wpa_s->imsi, wpa_s->mnc_len);
7651 } else {
7652 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7653 }
7654}
7655#endif /* CONFIG_EAP_PROXY */
7656
Dmitry Shmidt04949592012-07-19 12:16:46 -07007657 if (pcsc_reader_init(wpa_s) < 0)
7658 return -1;
7659
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007660 if (wpas_init_ext_pw(wpa_s) < 0)
7661 return -1;
7662
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007663#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007664 wpas_rrm_reset(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007665#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007666
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007667 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7668
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007669#ifdef CONFIG_HS20
7670 hs20_init(wpa_s);
7671#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007672#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007673 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007674 if ((wpa_s->conf->oce & OCE_STA) &&
7675 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7676 wpa_s->enable_oce = OCE_STA;
7677 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7678 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7679 /* TODO: Need to add STA-CFON support */
7680 wpa_printf(MSG_ERROR,
7681 "OCE STA-CFON feature is not yet supported");
7682 }
7683 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007684 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7685#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007686
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007687 wpa_supplicant_set_default_scan_ies(wpa_s);
7688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007689 return 0;
7690}
7691
7692
7693static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007694 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007695{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007696 struct wpa_global *global = wpa_s->global;
7697 struct wpa_supplicant *iface, *prev;
7698
Jimmy Chen0e73c002021-08-18 13:21:30 +08007699 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007700 wpas_p2p_group_remove(wpa_s, "*");
7701
7702 iface = global->ifaces;
7703 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007704 if (iface->p2pdev == wpa_s)
7705 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007706 if (iface == wpa_s || iface->parent != wpa_s) {
7707 iface = iface->next;
7708 continue;
7709 }
7710 wpa_printf(MSG_DEBUG,
7711 "Remove remaining child interface %s from parent %s",
7712 iface->ifname, wpa_s->ifname);
7713 prev = iface;
7714 iface = iface->next;
7715 wpa_supplicant_remove_iface(global, prev, terminate);
7716 }
7717
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007718 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007719 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007720 /*
7721 * Don't deauthenticate if WoWLAN is enable and not explicitly
7722 * been configured to disconnect.
7723 */
7724 if (!wpa_drv_get_wowlan(wpa_s) ||
7725 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007726 wpa_supplicant_deauthenticate(
7727 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007728
Hai Shalomfdcde762020-04-02 11:19:20 -07007729 wpa_drv_set_countermeasures(wpa_s, 0);
7730 wpa_clear_keys(wpa_s, NULL);
7731 } else {
7732 wpa_msg(wpa_s, MSG_INFO,
7733 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7734 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007735 }
7736
7737 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007738 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007739
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007740 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007741 radio_remove_interface(wpa_s);
7742
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007743#ifdef CONFIG_FST
7744 if (wpa_s->fst) {
7745 fst_detach(wpa_s->fst);
7746 wpa_s->fst = NULL;
7747 }
7748 if (wpa_s->received_mb_ies) {
7749 wpabuf_free(wpa_s->received_mb_ies);
7750 wpa_s->received_mb_ies = NULL;
7751 }
7752#endif /* CONFIG_FST */
7753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007754 if (wpa_s->drv_priv)
7755 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007756
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007757 if (notify)
7758 wpas_notify_iface_removed(wpa_s);
7759
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007760 if (terminate)
7761 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007762
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007763 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7764 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007765
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007766#ifdef CONFIG_MESH
7767 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007768 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007769 wpa_s->ifmsh = NULL;
7770 }
7771#endif /* CONFIG_MESH */
7772
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007773 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007774 wpa_config_free(wpa_s->conf);
7775 wpa_s->conf = NULL;
7776 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007777
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007778 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007779 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007780
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007781 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007782}
7783
7784
Dmitry Shmidte4663042016-04-04 10:07:49 -07007785#ifdef CONFIG_MATCH_IFACE
7786
7787/**
7788 * wpa_supplicant_match_iface - Match an interface description to a name
7789 * @global: Pointer to global data from wpa_supplicant_init()
7790 * @ifname: Name of the interface to match
7791 * Returns: Pointer to the created interface description or %NULL on failure
7792 */
7793struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7794 const char *ifname)
7795{
7796 int i;
7797 struct wpa_interface *iface, *miface;
7798
7799 for (i = 0; i < global->params.match_iface_count; i++) {
7800 miface = &global->params.match_ifaces[i];
7801 if (!miface->ifname ||
7802 fnmatch(miface->ifname, ifname, 0) == 0) {
7803 iface = os_zalloc(sizeof(*iface));
7804 if (!iface)
7805 return NULL;
7806 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007807 if (!miface->ifname)
7808 iface->matched = WPA_IFACE_MATCHED_NULL;
7809 else
7810 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007811 iface->ifname = ifname;
7812 return iface;
7813 }
7814 }
7815
7816 return NULL;
7817}
7818
7819
7820/**
7821 * wpa_supplicant_match_existing - Match existing interfaces
7822 * @global: Pointer to global data from wpa_supplicant_init()
7823 * Returns: 0 on success, -1 on failure
7824 */
7825static int wpa_supplicant_match_existing(struct wpa_global *global)
7826{
7827 struct if_nameindex *ifi, *ifp;
7828 struct wpa_supplicant *wpa_s;
7829 struct wpa_interface *iface;
7830
7831 ifp = if_nameindex();
7832 if (!ifp) {
7833 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7834 return -1;
7835 }
7836
7837 for (ifi = ifp; ifi->if_name; ifi++) {
7838 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7839 if (wpa_s)
7840 continue;
7841 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7842 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007843 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007844 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007845 }
7846 }
7847
7848 if_freenameindex(ifp);
7849 return 0;
7850}
7851
7852#endif /* CONFIG_MATCH_IFACE */
7853
7854
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007855/**
7856 * wpa_supplicant_add_iface - Add a new network interface
7857 * @global: Pointer to global data from wpa_supplicant_init()
7858 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007859 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007860 * Returns: Pointer to the created interface or %NULL on failure
7861 *
7862 * This function is used to add new network interfaces for %wpa_supplicant.
7863 * This can be called before wpa_supplicant_run() to add interfaces before the
7864 * main event loop has been started. In addition, new interfaces can be added
7865 * dynamically while %wpa_supplicant is already running. This could happen,
7866 * e.g., when a hotplug network adapter is inserted.
7867 */
7868struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007869 struct wpa_interface *iface,
7870 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007871{
7872 struct wpa_supplicant *wpa_s;
7873 struct wpa_interface t_iface;
7874 struct wpa_ssid *ssid;
7875
7876 if (global == NULL || iface == NULL)
7877 return NULL;
7878
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007879 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007880 if (wpa_s == NULL)
7881 return NULL;
7882
7883 wpa_s->global = global;
7884
7885 t_iface = *iface;
7886 if (global->params.override_driver) {
7887 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7888 "('%s' -> '%s')",
7889 iface->driver, global->params.override_driver);
7890 t_iface.driver = global->params.override_driver;
7891 }
7892 if (global->params.override_ctrl_interface) {
7893 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7894 "ctrl_interface ('%s' -> '%s')",
7895 iface->ctrl_interface,
7896 global->params.override_ctrl_interface);
7897 t_iface.ctrl_interface =
7898 global->params.override_ctrl_interface;
7899 }
7900 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7901 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7902 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007903 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007904 return NULL;
7905 }
7906
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007907 /* Notify the control interfaces about new iface */
7908 if (wpas_notify_iface_added(wpa_s)) {
7909 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7910 return NULL;
7911 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007912
Jimmy Chene2206be2022-07-10 10:25:21 +08007913 /* Notify the control interfaces about new networks */
7914 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7915 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007916 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007917 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7918 && os_strncmp((const char *) ssid->ssid,
7919 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7920 wpas_notify_persistent_group_added(wpa_s, ssid);
7921 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007922 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007923
7924 wpa_s->next = global->ifaces;
7925 global->ifaces = wpa_s;
7926
7927 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007928 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007929
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007930#ifdef CONFIG_P2P
7931 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007932 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007933 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007934 wpas_p2p_add_p2pdev_interface(
7935 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007936 wpa_printf(MSG_INFO,
7937 "P2P: Failed to enable P2P Device interface");
7938 /* Try to continue without. P2P will be disabled. */
7939 }
7940#endif /* CONFIG_P2P */
7941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007942 return wpa_s;
7943}
7944
7945
7946/**
7947 * wpa_supplicant_remove_iface - Remove a network interface
7948 * @global: Pointer to global data from wpa_supplicant_init()
7949 * @wpa_s: Pointer to the network interface to be removed
7950 * Returns: 0 if interface was removed, -1 if interface was not found
7951 *
7952 * This function can be used to dynamically remove network interfaces from
7953 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7954 * addition, this function is used to remove all remaining interfaces when
7955 * %wpa_supplicant is terminated.
7956 */
7957int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007958 struct wpa_supplicant *wpa_s,
7959 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007960{
7961 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007962#ifdef CONFIG_MESH
7963 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7964 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007965 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007966#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007967
7968 /* Remove interface from the global list of interfaces */
7969 prev = global->ifaces;
7970 if (prev == wpa_s) {
7971 global->ifaces = wpa_s->next;
7972 } else {
7973 while (prev && prev->next != wpa_s)
7974 prev = prev->next;
7975 if (prev == NULL)
7976 return -1;
7977 prev->next = wpa_s->next;
7978 }
7979
7980 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7981
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007982#ifdef CONFIG_MESH
7983 if (mesh_if_created) {
7984 ifname = os_strdup(wpa_s->ifname);
7985 if (ifname == NULL) {
7986 wpa_dbg(wpa_s, MSG_ERROR,
7987 "mesh: Failed to malloc ifname");
7988 return -1;
7989 }
7990 }
7991#endif /* CONFIG_MESH */
7992
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007993 if (global->p2p_group_formation == wpa_s)
7994 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007995 if (global->p2p_invite_group == wpa_s)
7996 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007997 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007998
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007999#ifdef CONFIG_MESH
8000 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008001 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008002 os_free(ifname);
8003 }
8004#endif /* CONFIG_MESH */
8005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008006 return 0;
8007}
8008
8009
8010/**
8011 * wpa_supplicant_get_eap_mode - Get the current EAP mode
8012 * @wpa_s: Pointer to the network interface
8013 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
8014 */
8015const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
8016{
8017 const char *eapol_method;
8018
8019 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
8020 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
8021 return "NO-EAP";
8022 }
8023
8024 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
8025 if (eapol_method == NULL)
8026 return "UNKNOWN-EAP";
8027
8028 return eapol_method;
8029}
8030
8031
8032/**
8033 * wpa_supplicant_get_iface - Get a new network interface
8034 * @global: Pointer to global data from wpa_supplicant_init()
8035 * @ifname: Interface name
8036 * Returns: Pointer to the interface or %NULL if not found
8037 */
8038struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
8039 const char *ifname)
8040{
8041 struct wpa_supplicant *wpa_s;
8042
8043 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8044 if (os_strcmp(wpa_s->ifname, ifname) == 0)
8045 return wpa_s;
8046 }
8047 return NULL;
8048}
8049
8050
8051#ifndef CONFIG_NO_WPA_MSG
8052static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
8053{
8054 struct wpa_supplicant *wpa_s = ctx;
8055 if (wpa_s == NULL)
8056 return NULL;
8057 return wpa_s->ifname;
8058}
8059#endif /* CONFIG_NO_WPA_MSG */
8060
8061
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008062#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
8063#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
8064#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
8065
8066/* Periodic cleanup tasks */
8067static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
8068{
8069 struct wpa_global *global = eloop_ctx;
8070 struct wpa_supplicant *wpa_s;
8071
8072 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8073 wpas_periodic, global, NULL);
8074
8075#ifdef CONFIG_P2P
8076 if (global->p2p)
8077 p2p_expire_peers(global->p2p);
8078#endif /* CONFIG_P2P */
8079
8080 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8081 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
8082#ifdef CONFIG_AP
8083 ap_periodic(wpa_s);
8084#endif /* CONFIG_AP */
8085 }
8086}
8087
8088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008089/**
8090 * wpa_supplicant_init - Initialize %wpa_supplicant
8091 * @params: Parameters for %wpa_supplicant
8092 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
8093 *
8094 * This function is used to initialize %wpa_supplicant. After successful
8095 * initialization, the returned data pointer can be used to add and remove
8096 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
8097 */
8098struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
8099{
8100 struct wpa_global *global;
8101 int ret, i;
8102
8103 if (params == NULL)
8104 return NULL;
8105
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008106#ifdef CONFIG_DRIVER_NDIS
8107 {
8108 void driver_ndis_init_ops(void);
8109 driver_ndis_init_ops();
8110 }
8111#endif /* CONFIG_DRIVER_NDIS */
8112
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008113#ifndef CONFIG_NO_WPA_MSG
8114 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
8115#endif /* CONFIG_NO_WPA_MSG */
8116
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008117 if (params->wpa_debug_file_path)
8118 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07008119 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008120 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008121 if (params->wpa_debug_syslog)
8122 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008123 if (params->wpa_debug_tracing) {
8124 ret = wpa_debug_open_linux_tracing();
8125 if (ret) {
8126 wpa_printf(MSG_ERROR,
8127 "Failed to enable trace logging");
8128 return NULL;
8129 }
8130 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008131
8132 ret = eap_register_methods();
8133 if (ret) {
8134 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
8135 if (ret == -2)
8136 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
8137 "the same EAP type.");
8138 return NULL;
8139 }
8140
8141 global = os_zalloc(sizeof(*global));
8142 if (global == NULL)
8143 return NULL;
8144 dl_list_init(&global->p2p_srv_bonjour);
8145 dl_list_init(&global->p2p_srv_upnp);
8146 global->params.daemonize = params->daemonize;
8147 global->params.wait_for_monitor = params->wait_for_monitor;
8148 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008149
8150 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008151 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008152 if (!global->params.pid_file) {
8153 wpa_supplicant_deinit(global);
8154 return NULL;
8155 }
8156 }
8157
8158 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008159 global->params.ctrl_interface =
8160 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008161 if (!global->params.ctrl_interface) {
8162 wpa_supplicant_deinit(global);
8163 return NULL;
8164 }
8165 }
8166
8167 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008168 global->params.ctrl_interface_group =
8169 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008170 if (!global->params.ctrl_interface_group) {
8171 wpa_supplicant_deinit(global);
8172 return NULL;
8173 }
8174 }
8175
8176 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008177 global->params.override_driver =
8178 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008179 if (!global->params.override_driver) {
8180 wpa_supplicant_deinit(global);
8181 return NULL;
8182 }
8183 }
8184
8185 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008186 global->params.override_ctrl_interface =
8187 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008188 if (!global->params.override_ctrl_interface) {
8189 wpa_supplicant_deinit(global);
8190 return NULL;
8191 }
8192 }
8193
Dmitry Shmidte4663042016-04-04 10:07:49 -07008194#ifdef CONFIG_MATCH_IFACE
8195 global->params.match_iface_count = params->match_iface_count;
8196 if (params->match_iface_count) {
8197 global->params.match_ifaces =
8198 os_calloc(params->match_iface_count,
8199 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00008200 if (!global->params.match_ifaces) {
8201 wpa_printf(MSG_ERROR,
8202 "Failed to allocate match interfaces");
8203 wpa_supplicant_deinit(global);
8204 return NULL;
8205 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07008206 os_memcpy(global->params.match_ifaces,
8207 params->match_ifaces,
8208 params->match_iface_count *
8209 sizeof(struct wpa_interface));
8210 }
8211#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008212#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00008213 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008214 global->params.conf_p2p_dev =
8215 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008216 if (!global->params.conf_p2p_dev) {
8217 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
8218 wpa_supplicant_deinit(global);
8219 return NULL;
8220 }
8221 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008222#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008223 wpa_debug_level = global->params.wpa_debug_level =
8224 params->wpa_debug_level;
8225 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
8226 params->wpa_debug_show_keys;
8227 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
8228 params->wpa_debug_timestamp;
8229
Hai Shalomfdcde762020-04-02 11:19:20 -07008230 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008231
8232 if (eloop_init()) {
8233 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
8234 wpa_supplicant_deinit(global);
8235 return NULL;
8236 }
8237
Jouni Malinen75ecf522011-06-27 15:19:46 -07008238 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008239
8240 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
8241 if (global->ctrl_iface == NULL) {
8242 wpa_supplicant_deinit(global);
8243 return NULL;
8244 }
8245
8246 if (wpas_notify_supplicant_initialized(global)) {
8247 wpa_supplicant_deinit(global);
8248 return NULL;
8249 }
8250
8251 for (i = 0; wpa_drivers[i]; i++)
8252 global->drv_count++;
8253 if (global->drv_count == 0) {
8254 wpa_printf(MSG_ERROR, "No drivers enabled");
8255 wpa_supplicant_deinit(global);
8256 return NULL;
8257 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008258 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008259 if (global->drv_priv == NULL) {
8260 wpa_supplicant_deinit(global);
8261 return NULL;
8262 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008263
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008264#ifdef CONFIG_WIFI_DISPLAY
8265 if (wifi_display_init(global) < 0) {
8266 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8267 wpa_supplicant_deinit(global);
8268 return NULL;
8269 }
8270#endif /* CONFIG_WIFI_DISPLAY */
8271
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008272 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8273 wpas_periodic, global, NULL);
8274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008275 return global;
8276}
8277
8278
8279/**
8280 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8281 * @global: Pointer to global data from wpa_supplicant_init()
8282 * Returns: 0 after successful event loop run, -1 on failure
8283 *
8284 * This function starts the main event loop and continues running as long as
8285 * there are any remaining events. In most cases, this function is running as
8286 * long as the %wpa_supplicant process in still in use.
8287 */
8288int wpa_supplicant_run(struct wpa_global *global)
8289{
8290 struct wpa_supplicant *wpa_s;
8291
8292 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008293 (wpa_supplicant_daemon(global->params.pid_file) ||
8294 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008295 return -1;
8296
Dmitry Shmidte4663042016-04-04 10:07:49 -07008297#ifdef CONFIG_MATCH_IFACE
8298 if (wpa_supplicant_match_existing(global))
8299 return -1;
8300#endif
8301
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008302 if (global->params.wait_for_monitor) {
8303 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008304 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008305 wpa_supplicant_ctrl_iface_wait(
8306 wpa_s->ctrl_iface);
8307 }
8308
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008309#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008310 // If daemonize is enabled, initialize AIDL here.
8311 if (global->params.daemonize) {
8312 global->aidl = wpas_aidl_init(global);
8313 if (!global->aidl)
8314 return -1;
8315 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008316#endif /* CONFIG_AIDL */
8317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008318 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8319 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8320
8321 eloop_run();
8322
8323 return 0;
8324}
8325
8326
8327/**
8328 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8329 * @global: Pointer to global data from wpa_supplicant_init()
8330 *
8331 * This function is called to deinitialize %wpa_supplicant and to free all
8332 * allocated resources. Remaining network interfaces will also be removed.
8333 */
8334void wpa_supplicant_deinit(struct wpa_global *global)
8335{
8336 int i;
8337
8338 if (global == NULL)
8339 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008340
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008341 eloop_cancel_timeout(wpas_periodic, global, NULL);
8342
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008343#ifdef CONFIG_WIFI_DISPLAY
8344 wifi_display_deinit(global);
8345#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008346
8347 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008348 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008349
8350 if (global->ctrl_iface)
8351 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8352
8353 wpas_notify_supplicant_deinitialized(global);
8354
8355 eap_peer_unregister_methods();
8356#ifdef CONFIG_AP
8357 eap_server_unregister_methods();
8358#endif /* CONFIG_AP */
8359
8360 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8361 if (!global->drv_priv[i])
8362 continue;
8363 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8364 }
8365 os_free(global->drv_priv);
8366
8367 random_deinit();
8368
8369 eloop_destroy();
8370
8371 if (global->params.pid_file) {
8372 os_daemonize_terminate(global->params.pid_file);
8373 os_free(global->params.pid_file);
8374 }
8375 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008376 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008377 os_free(global->params.override_driver);
8378 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008379#ifdef CONFIG_MATCH_IFACE
8380 os_free(global->params.match_ifaces);
8381#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008382#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008383 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008384#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008385
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008386 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008387 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008388 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008389
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008390 os_free(global);
8391 wpa_debug_close_syslog();
8392 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008393 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008394}
8395
8396
8397void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8398{
8399 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8400 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8401 char country[3];
8402 country[0] = wpa_s->conf->country[0];
8403 country[1] = wpa_s->conf->country[1];
8404 country[2] = '\0';
8405 if (wpa_drv_set_country(wpa_s, country) < 0) {
8406 wpa_printf(MSG_ERROR, "Failed to set country code "
8407 "'%s'", country);
8408 }
8409 }
8410
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008411 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8412 wpas_init_ext_pw(wpa_s);
8413
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008414 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8415 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8416
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008417 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8418 struct wpa_driver_capa capa;
8419 int res = wpa_drv_get_capa(wpa_s, &capa);
8420
8421 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8422 wpa_printf(MSG_ERROR,
8423 "Failed to update wowlan_triggers to '%s'",
8424 wpa_s->conf->wowlan_triggers);
8425 }
8426
Hai Shalom81f62d82019-07-22 12:10:00 -07008427 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8428 wpa_supplicant_set_default_scan_ies(wpa_s);
8429
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008430 if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
8431 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
8432 wpa_s->conf->ft_prepend_pmkid);
8433
Hai Shalom899fcc72020-10-19 14:38:18 -07008434#ifdef CONFIG_BGSCAN
8435 /*
8436 * We default to global bgscan parameters only when per-network bgscan
8437 * parameters aren't set. Only bother resetting bgscan parameters if
8438 * this is the case.
8439 */
8440 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8441 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8442 wpa_s->wpa_state == WPA_COMPLETED)
8443 wpa_supplicant_reset_bgscan(wpa_s);
8444#endif /* CONFIG_BGSCAN */
8445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008446#ifdef CONFIG_WPS
8447 wpas_wps_update_config(wpa_s);
8448#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008449 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008450 wpa_s->conf->changed_parameters = 0;
8451}
8452
8453
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008454void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008455{
8456 int i;
8457
8458 for (i = 0; i < *num_freqs; i++) {
8459 if (freqs[i] == freq)
8460 return;
8461 }
8462
8463 freqs[*num_freqs] = freq;
8464 (*num_freqs)++;
8465}
8466
8467
8468static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8469{
8470 struct wpa_bss *bss, *cbss;
8471 const int max_freqs = 10;
8472 int *freqs;
8473 int num_freqs = 0;
8474
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008475 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008476 if (freqs == NULL)
8477 return NULL;
8478
8479 cbss = wpa_s->current_bss;
8480
8481 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8482 if (bss == cbss)
8483 continue;
8484 if (bss->ssid_len == cbss->ssid_len &&
8485 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008486 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008487 add_freq(freqs, &num_freqs, bss->freq);
8488 if (num_freqs == max_freqs)
8489 break;
8490 }
8491 }
8492
8493 if (num_freqs == 0) {
8494 os_free(freqs);
8495 freqs = NULL;
8496 }
8497
8498 return freqs;
8499}
8500
8501
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008502void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
8503 const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008504{
8505 int timeout;
8506 int count;
8507 int *freqs = NULL;
8508
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008509 wpas_connect_work_done(wpa_s);
8510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008511 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008512 * Remove possible authentication timeout since the connection failed.
8513 */
8514 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8515
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008516 /*
Hai Shalom60840252021-02-19 19:02:11 -08008517 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008518 * generated based on local request to disconnect.
8519 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008520 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008521 wpa_s->own_disconnect_req = 0;
8522 wpa_dbg(wpa_s, MSG_DEBUG,
8523 "Ignore connection failure due to local request to disconnect");
8524 return;
8525 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008526 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008527 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8528 "indication since interface has been put into "
8529 "disconnected state");
8530 return;
8531 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008532 if (wpa_s->auto_reconnect_disabled) {
8533 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8534 "indication since auto connect is disabled");
8535 return;
8536 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008537
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008538 /* Also mark links as failed */
8539 while (link_bssids && *link_bssids) {
8540 wpa_bssid_ignore_add(wpa_s, *link_bssids);
8541 link_bssids++;
8542 }
8543
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008544 /*
Hai Shalom60840252021-02-19 19:02:11 -08008545 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008546 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008547 */
Hai Shalom60840252021-02-19 19:02:11 -08008548 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008549 if (count == 1 && wpa_s->current_bss) {
8550 /*
Hai Shalom60840252021-02-19 19:02:11 -08008551 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008552 * another BSS available for the same ESS, we should try that
8553 * next. Otherwise, we may as well try this one once more
8554 * before allowing other, likely worse, ESSes to be considered.
8555 */
8556 freqs = get_bss_freqs_in_ess(wpa_s);
8557 if (freqs) {
8558 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8559 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008560 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008561 /*
8562 * On the next scan, go through only the known channels
8563 * used in this ESS based on previous scans to speed up
8564 * common load balancing use case.
8565 */
8566 os_free(wpa_s->next_scan_freqs);
8567 wpa_s->next_scan_freqs = freqs;
8568 }
8569 }
8570
Hai Shalom899fcc72020-10-19 14:38:18 -07008571 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008572
Hai Shalom899fcc72020-10-19 14:38:18 -07008573 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008574 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8575 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008576 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008577 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008578 /*
8579 * Multiple consecutive connection failures mean that other APs are
8580 * either not available or have already been tried, so we can start
8581 * increasing the delay here to avoid constant scanning.
8582 */
8583 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008584 case 1:
8585 timeout = 100;
8586 break;
8587 case 2:
8588 timeout = 500;
8589 break;
8590 case 3:
8591 timeout = 1000;
8592 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008593 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008594 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008595 break;
8596 default:
8597 timeout = 10000;
8598 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008599 }
8600
Hai Shalom899fcc72020-10-19 14:38:18 -07008601 wpa_dbg(wpa_s, MSG_DEBUG,
8602 "Consecutive connection failures: %d --> request scan in %d ms",
8603 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008605 /*
8606 * TODO: if more than one possible AP is available in scan results,
8607 * could try the other ones before requesting a new scan.
8608 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008609
8610 /* speed up the connection attempt with normal scan */
8611 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008612 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8613 1000 * (timeout % 1000));
8614}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008615
8616
Hai Shalomce48b4a2018-09-05 11:41:35 -07008617#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008618
8619void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8620{
8621 struct wpa_ssid *ssid = wpa_s->current_ssid;
8622 const u8 *realm, *username, *rrk;
8623 size_t realm_len, username_len, rrk_len;
8624 u16 next_seq_num;
8625
8626 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8627 * Check for ERP keys existing to limit when this can be done since
8628 * the rejection response is not protected and such triggers should
8629 * really not allow internal state to be modified unless required to
8630 * avoid significant issues in functionality. In addition, drop
8631 * externally configure PMKSA entries even without ERP keys since it
8632 * is possible for an external component to add PMKSA entries for FILS
8633 * authentication without restoring previously generated ERP keys.
8634 *
8635 * In this case, this is needed to allow recovery from cases where the
8636 * AP or authentication server has dropped PMKSAs and ERP keys. */
8637 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8638 return;
8639
8640 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8641 &username, &username_len,
8642 &realm, &realm_len, &next_seq_num,
8643 &rrk, &rrk_len) != 0 ||
8644 !realm) {
8645 wpa_dbg(wpa_s, MSG_DEBUG,
8646 "FILS: Drop external PMKSA cache entry");
8647 wpa_sm_aborted_external_cached(wpa_s->wpa);
8648 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8649 return;
8650 }
8651
8652 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8653 wpa_sm_aborted_cached(wpa_s->wpa);
8654 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8655}
8656
8657
Hai Shalomce48b4a2018-09-05 11:41:35 -07008658void fils_connection_failure(struct wpa_supplicant *wpa_s)
8659{
8660 struct wpa_ssid *ssid = wpa_s->current_ssid;
8661 const u8 *realm, *username, *rrk;
8662 size_t realm_len, username_len, rrk_len;
8663 u16 next_seq_num;
8664
8665 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8666 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8667 &username, &username_len,
8668 &realm, &realm_len, &next_seq_num,
8669 &rrk, &rrk_len) != 0 ||
8670 !realm)
8671 return;
8672
8673 wpa_hexdump_ascii(MSG_DEBUG,
8674 "FILS: Store last connection failure realm",
8675 realm, realm_len);
8676 os_free(wpa_s->last_con_fail_realm);
8677 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8678 if (wpa_s->last_con_fail_realm) {
8679 wpa_s->last_con_fail_realm_len = realm_len;
8680 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8681 }
8682}
8683#endif /* CONFIG_FILS */
8684
8685
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008686int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8687{
8688 return wpa_s->conf->ap_scan == 2 ||
8689 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8690}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008691
Dmitry Shmidt04949592012-07-19 12:16:46 -07008692
Sunil Ravi7f769292024-07-23 22:21:32 +00008693static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
8694{
8695 return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
8696}
8697
8698
8699bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
8700{
8701 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
8702 return false;
8703
8704 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
8705 return true;
8706
8707 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
8708 wpas_driver_bss_selection(wpa_s))
8709 return wpas_driver_rsn_override(wpa_s);
8710
8711 return true;
8712}
8713
8714
Gabriel Biren57ededa2021-09-03 16:08:50 +00008715#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008716int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8717 struct wpa_ssid *ssid,
8718 const char *field,
8719 const char *value)
8720{
8721#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008722 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008723
8724 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8725 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8726 (const u8 *) value, os_strlen(value));
8727
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008728 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008729 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008730#else /* IEEE8021X_EAPOL */
8731 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8732 return -1;
8733#endif /* IEEE8021X_EAPOL */
8734}
8735
8736int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8737 struct wpa_ssid *ssid,
8738 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008739 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008740{
8741#ifdef IEEE8021X_EAPOL
8742 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008743 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008744
8745 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008746 case WPA_CTRL_REQ_EAP_IDENTITY:
8747 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008748 os_free(eap->imsi_identity);
8749 if (value == NULL)
8750 return -1;
8751 identity = os_strchr(value, ':');
8752 if (identity == NULL) {
8753 /* plain identity */
8754 eap->identity = (u8 *)os_strdup(value);
8755 eap->identity_len = os_strlen(value);
8756 } else {
8757 /* have both plain identity and encrypted identity */
8758 imsi_identity = value;
8759 *identity++ = '\0';
8760 /* plain identity */
8761 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8762 eap->imsi_identity_len = strlen(imsi_identity);
8763 /* encrypted identity */
8764 eap->identity = (u8 *)dup_binstr(identity,
8765 value_len - strlen(imsi_identity) - 1);
8766 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8767 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008768 eap->pending_req_identity = 0;
8769 if (ssid == wpa_s->current_ssid)
8770 wpa_s->reassociate = 1;
8771 break;
8772 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008773 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008774 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008775 if (!eap->password)
8776 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008777 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008778 eap->pending_req_password = 0;
8779 if (ssid == wpa_s->current_ssid)
8780 wpa_s->reassociate = 1;
8781 break;
8782 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008783 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008784 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008785 if (!eap->new_password)
8786 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008787 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008788 eap->pending_req_new_password = 0;
8789 if (ssid == wpa_s->current_ssid)
8790 wpa_s->reassociate = 1;
8791 break;
8792 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008793 str_clear_free(eap->cert.pin);
8794 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008795 if (!eap->cert.pin)
8796 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008797 eap->pending_req_pin = 0;
8798 if (ssid == wpa_s->current_ssid)
8799 wpa_s->reassociate = 1;
8800 break;
8801 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008802 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008803 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008804 if (!eap->otp)
8805 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008806 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008807 os_free(eap->pending_req_otp);
8808 eap->pending_req_otp = NULL;
8809 eap->pending_req_otp_len = 0;
8810 break;
8811 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008812 str_clear_free(eap->cert.private_key_passwd);
8813 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008814 if (!eap->cert.private_key_passwd)
8815 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008816 eap->pending_req_passphrase = 0;
8817 if (ssid == wpa_s->current_ssid)
8818 wpa_s->reassociate = 1;
8819 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008820 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008821 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008822 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008823 if (!eap->external_sim_resp)
8824 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008825 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008826 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008827 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8828 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8829 return -1;
8830 ssid->mem_only_psk = 1;
8831 if (ssid->passphrase)
8832 wpa_config_update_psk(ssid);
8833 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8834 wpa_supplicant_req_scan(wpa_s, 0, 0);
8835 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008836 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8837 if (eap->pending_ext_cert_check != PENDING_CHECK)
8838 return -1;
8839 if (os_strcmp(value, "good") == 0)
8840 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8841 else if (os_strcmp(value, "bad") == 0)
8842 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8843 else
8844 return -1;
8845 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008846 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008847 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008848 return -1;
8849 }
8850
8851 return 0;
8852#else /* IEEE8021X_EAPOL */
8853 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8854 return -1;
8855#endif /* IEEE8021X_EAPOL */
8856}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008857#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008858
8859
8860int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8861{
Hai Shalomfdcde762020-04-02 11:19:20 -07008862#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008863 int i;
8864 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008865#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008866
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008867 if (wpa_s->p2p_mgmt)
8868 return 1; /* no normal network profiles on p2p_mgmt interface */
8869
Dmitry Shmidt04949592012-07-19 12:16:46 -07008870 if (ssid == NULL)
8871 return 1;
8872
8873 if (ssid->disabled)
8874 return 1;
8875
Hai Shalomfdcde762020-04-02 11:19:20 -07008876#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008877 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008878 drv_enc = wpa_s->drv_enc;
8879 else
8880 drv_enc = (unsigned int) -1;
8881
8882 for (i = 0; i < NUM_WEP_KEYS; i++) {
8883 size_t len = ssid->wep_key_len[i];
8884 if (len == 0)
8885 continue;
8886 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8887 continue;
8888 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8889 continue;
8890 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8891 continue;
8892 return 1; /* invalid WEP key */
8893 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008894#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008895
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008896 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008897 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008898 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008899 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008900 return 1;
8901
Sunil Ravi89eba102022-09-13 21:04:37 -07008902#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008903#ifdef CRYPTO_RSA_OAEP_SHA256
8904 if (ssid->eap.imsi_privacy_cert) {
8905 struct crypto_rsa_key *key;
8906 bool failed = false;
8907
8908 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8909 if (!key)
8910 failed = true;
8911 crypto_rsa_key_free(key);
8912 if (failed) {
8913 wpa_printf(MSG_DEBUG,
8914 "Invalid imsi_privacy_cert (%s) - disable network",
8915 ssid->eap.imsi_privacy_cert);
8916 return 1;
8917 }
8918 }
8919#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008920#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008921
Dmitry Shmidt04949592012-07-19 12:16:46 -07008922 return 0;
8923}
8924
8925
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008926int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8927{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008928 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8929 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8930 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8931 /*
8932 * Driver does not support BIP -- ignore pmf=1 default
8933 * since the connection with PMF would fail and the
8934 * configuration does not require PMF to be enabled.
8935 */
8936 return NO_MGMT_FRAME_PROTECTION;
8937 }
8938
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008939 if (ssid &&
8940 (ssid->key_mgmt &
8941 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8942 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8943 /*
8944 * Do not use the default PMF value for non-RSN networks
8945 * since PMF is available only with RSN and pmf=2
8946 * configuration would otherwise prevent connections to
8947 * all open networks.
8948 */
8949 return NO_MGMT_FRAME_PROTECTION;
8950 }
8951
Sunil Ravi77d572f2023-01-17 23:58:31 +00008952#ifdef CONFIG_OCV
8953 /* Enable PMF if OCV is being enabled */
8954 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8955 ssid && ssid->ocv)
8956 return MGMT_FRAME_PROTECTION_OPTIONAL;
8957#endif /* CONFIG_OCV */
8958
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008959 return wpa_s->conf->pmf;
8960 }
8961
8962 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008963}
8964
8965
Sunil Ravi77d572f2023-01-17 23:58:31 +00008966#ifdef CONFIG_SAE
8967bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8968 struct wpa_ssid *ssid,
8969 const struct wpa_ie_data *ie)
8970{
8971 return wpa_s->conf->sae_check_mfp &&
8972 (!(ie->capabilities &
8973 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8974 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8975}
8976#endif /* CONFIG_SAE */
8977
8978
Hai Shalomc1a21442022-02-04 13:43:00 -08008979int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8980{
8981 if (wpa_s->current_ssid == NULL ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008982 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
Hai Shalomc1a21442022-02-04 13:43:00 -08008983 return 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008984 if (wpa_s->valid_links) {
8985 if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
8986 !wpas_ap_link_address(wpa_s, addr))
8987 return 0;
8988 } else {
8989 if (!ether_addr_equal(addr, wpa_s->bssid))
8990 return 0;
8991 }
Hai Shalomc1a21442022-02-04 13:43:00 -08008992 return wpa_sm_pmf_enabled(wpa_s->wpa);
8993}
8994
8995
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008996int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008997{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008998 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008999 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07009000 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009001 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009002 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009003}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009004
9005
Sunil Ravi77d572f2023-01-17 23:58:31 +00009006void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
9007 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009008{
9009 struct wpa_ssid *ssid = wpa_s->current_ssid;
9010 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009011 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009012
9013 if (ssid == NULL) {
9014 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
9015 "SSID block");
9016 return;
9017 }
9018
9019 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
9020 return;
9021
9022 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07009023
9024#ifdef CONFIG_P2P
9025 if (ssid->p2p_group &&
9026 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
9027 /*
9028 * Skip the wait time since there is a short timeout on the
9029 * connection to a P2P group.
9030 */
9031 return;
9032 }
9033#endif /* CONFIG_P2P */
9034
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009035 if (ssid->auth_failures > 50)
9036 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009037 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009038 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009039 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009040 dur = 90;
9041 else if (ssid->auth_failures > 3)
9042 dur = 60;
9043 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009044 dur = 30;
9045 else if (ssid->auth_failures > 1)
9046 dur = 20;
9047 else
9048 dur = 10;
9049
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009050 if (ssid->auth_failures > 1 &&
9051 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
9052 dur += os_random() % (ssid->auth_failures * 10);
9053
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009054 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009055 if (now.sec + dur <= ssid->disabled_until.sec)
9056 return;
9057
9058 ssid->disabled_until.sec = now.sec + dur;
9059
9060 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009061 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009062 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009063 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009064
9065 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
9066 int msg_len = snprintf(NULL, 0, format_str,
9067 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9068 ssid->auth_failures, dur, reason) + 1;
9069 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05309070 if (!msg)
9071 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009072 snprintf(msg, msg_len, format_str,
9073 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9074 ssid->auth_failures, dur, reason);
9075 wpas_notify_ssid_temp_disabled(wpa_s, msg);
9076 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009077
9078 if (bssid)
9079 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009080}
9081
9082
9083void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
9084 struct wpa_ssid *ssid, int clear_failures)
9085{
9086 if (ssid == NULL)
9087 return;
9088
9089 if (ssid->disabled_until.sec) {
9090 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
9091 "id=%d ssid=\"%s\"",
9092 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
9093 }
9094 ssid->disabled_until.sec = 0;
9095 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009096 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009097 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009098 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
9099 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
9100 " ignored to allow a lower priority BSS, if any, to be tried next",
9101 MAC2STR(ssid->disabled_due_to));
9102 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
9103 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
9104 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009105}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009106
9107
9108int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
9109{
9110 size_t i;
9111
9112 if (wpa_s->disallow_aps_bssid == NULL)
9113 return 0;
9114
9115 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009116 if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
9117 bssid))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009118 return 1;
9119 }
9120
9121 return 0;
9122}
9123
9124
9125int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
9126 size_t ssid_len)
9127{
9128 size_t i;
9129
9130 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
9131 return 0;
9132
9133 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
9134 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
9135 if (ssid_len == s->ssid_len &&
9136 os_memcmp(ssid, s->ssid, ssid_len) == 0)
9137 return 1;
9138 }
9139
9140 return 0;
9141}
9142
9143
9144/**
9145 * wpas_request_connection - Request a new connection
9146 * @wpa_s: Pointer to the network interface
9147 *
9148 * This function is used to request a new connection to be found. It will mark
9149 * the interface to allow reassociation and request a new scan to find a
9150 * suitable network to connect to.
9151 */
9152void wpas_request_connection(struct wpa_supplicant *wpa_s)
9153{
9154 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009155 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009156 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009157 wpa_s->disconnected = 0;
9158 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07009159 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08009160
9161 if (wpa_supplicant_fast_associate(wpa_s) != 1)
9162 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009163 else
9164 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009165}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009166
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009167
Roshan Pius02242d72016-08-09 15:31:48 -07009168/**
9169 * wpas_request_disconnection - Request disconnection
9170 * @wpa_s: Pointer to the network interface
9171 *
9172 * This function is used to request disconnection from the currently connected
9173 * network. This will stop any ongoing scans and initiate deauthentication.
9174 */
9175void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
9176{
9177#ifdef CONFIG_SME
9178 wpa_s->sme.prev_bssid_set = 0;
9179#endif /* CONFIG_SME */
9180 wpa_s->reassociate = 0;
9181 wpa_s->disconnected = 1;
9182 wpa_supplicant_cancel_sched_scan(wpa_s);
9183 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009184 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07009185 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
9186 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07009187 radio_remove_works(wpa_s, "connect", 0);
9188 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08009189 wpa_s->roam_in_progress = false;
9190#ifdef CONFIG_WNM
9191 wpa_s->bss_trans_mgmt_in_progress = false;
9192#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07009193}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009194
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07009195
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009196void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
9197 struct wpa_used_freq_data *freqs_data,
9198 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009199{
9200 unsigned int i;
9201
9202 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
9203 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009204 for (i = 0; i < len; i++) {
9205 struct wpa_used_freq_data *cur = &freqs_data[i];
9206 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
9207 i, cur->freq, cur->flags);
9208 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009209}
9210
9211
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009212/*
9213 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009214 * are using the same radio as the current interface, and in addition, get
9215 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009216 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009217int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
9218 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009219 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009220{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009221 struct wpa_supplicant *ifs;
9222 u8 bssid[ETH_ALEN];
9223 int freq;
9224 unsigned int idx = 0, i;
9225
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009226 wpa_dbg(wpa_s, MSG_DEBUG,
9227 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009228 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009229
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009230 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
9231 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009232 if (idx == len)
9233 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009234
Sunil Ravi77d572f2023-01-17 23:58:31 +00009235 if (exclude_current && ifs == wpa_s)
9236 continue;
9237
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009238 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
9239 continue;
9240
9241 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009242 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
9243 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009244 freq = ifs->current_ssid->frequency;
9245 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
9246 freq = ifs->assoc_freq;
9247 else
9248 continue;
9249
9250 /* Hold only distinct freqs */
9251 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009252 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009253 break;
9254
9255 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009256 freqs_data[idx++].freq = freq;
9257
9258 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009259 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009260 WPA_FREQ_USED_BY_P2P_CLIENT :
9261 WPA_FREQ_USED_BY_INFRA_STATION;
9262 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009263 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009264
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009265 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009266 return idx;
9267}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009268
9269
9270/*
9271 * Find the operating frequencies of any of the virtual interfaces that
9272 * are using the same radio as the current interface.
9273 */
9274int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009275 int *freq_array, unsigned int len,
9276 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009277{
9278 struct wpa_used_freq_data *freqs_data;
9279 int num, i;
9280
9281 os_memset(freq_array, 0, sizeof(int) * len);
9282
9283 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
9284 if (!freqs_data)
9285 return -1;
9286
Sunil Ravi77d572f2023-01-17 23:58:31 +00009287 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
9288 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009289 for (i = 0; i < num; i++)
9290 freq_array[i] = freqs_data[i].freq;
9291
9292 os_free(freqs_data);
9293
9294 return num;
9295}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009296
9297
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009298struct wpa_supplicant *
9299wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9300{
9301 switch (frame) {
9302#ifdef CONFIG_P2P
9303 case VENDOR_ELEM_PROBE_REQ_P2P:
9304 case VENDOR_ELEM_PROBE_RESP_P2P:
9305 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9306 case VENDOR_ELEM_BEACON_P2P_GO:
9307 case VENDOR_ELEM_P2P_PD_REQ:
9308 case VENDOR_ELEM_P2P_PD_RESP:
9309 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9310 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9311 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9312 case VENDOR_ELEM_P2P_INV_REQ:
9313 case VENDOR_ELEM_P2P_INV_RESP:
9314 case VENDOR_ELEM_P2P_ASSOC_REQ:
9315 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009316 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009317#endif /* CONFIG_P2P */
9318 default:
9319 return wpa_s;
9320 }
9321}
9322
9323
9324void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9325{
9326 unsigned int i;
9327 char buf[30];
9328
9329 wpa_printf(MSG_DEBUG, "Update vendor elements");
9330
9331 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9332 if (wpa_s->vendor_elem[i]) {
9333 int res;
9334
9335 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9336 if (!os_snprintf_error(sizeof(buf), res)) {
9337 wpa_hexdump_buf(MSG_DEBUG, buf,
9338 wpa_s->vendor_elem[i]);
9339 }
9340 }
9341 }
9342
9343#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009344 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009345 wpa_s->global->p2p &&
9346 !wpa_s->global->p2p_disabled)
9347 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9348#endif /* CONFIG_P2P */
9349}
9350
9351
9352int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9353 const u8 *elem, size_t len)
9354{
9355 u8 *ie, *end;
9356
9357 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9358 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9359
9360 for (; ie + 1 < end; ie += 2 + ie[1]) {
9361 if (ie + len > end)
9362 break;
9363 if (os_memcmp(ie, elem, len) != 0)
9364 continue;
9365
9366 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9367 wpabuf_free(wpa_s->vendor_elem[frame]);
9368 wpa_s->vendor_elem[frame] = NULL;
9369 } else {
9370 os_memmove(ie, ie + len, end - (ie + len));
9371 wpa_s->vendor_elem[frame]->used -= len;
9372 }
9373 wpas_vendor_elem_update(wpa_s);
9374 return 0;
9375 }
9376
9377 return -1;
9378}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009379
9380
9381struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009382 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009383 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009384{
9385 u16 i;
9386
Hai Shalomc1a21442022-02-04 13:43:00 -08009387 if (!modes)
9388 return NULL;
9389
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009390 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009391 if (modes[i].mode != mode ||
9392 !modes[i].num_channels || !modes[i].channels)
9393 continue;
Sunil Ravi99c035e2024-07-12 01:42:03 +00009394 if (is_6ghz == modes[i].is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009395 return &modes[i];
9396 }
9397
9398 return NULL;
9399}
9400
9401
Hai Shalomc1a21442022-02-04 13:43:00 -08009402struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9403 u16 num_modes, int freq)
9404{
9405 int i, j;
9406
9407 for (i = 0; i < num_modes; i++) {
9408 for (j = 0; j < modes[i].num_channels; j++) {
9409 if (freq == modes[i].channels[j].freq)
9410 return &modes[i];
9411 }
9412 }
9413
9414 return NULL;
9415}
9416
9417
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009418static struct
9419wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9420 const u8 *bssid)
9421{
9422 struct wpa_bss_tmp_disallowed *bss;
9423
9424 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9425 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009426 if (ether_addr_equal(bssid, bss->bssid))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009427 return bss;
9428 }
9429
9430 return NULL;
9431}
9432
9433
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009434static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9435{
9436 struct wpa_bss_tmp_disallowed *tmp;
9437 unsigned int num_bssid = 0;
9438 u8 *bssids;
9439 int ret;
9440
9441 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9442 if (!bssids)
9443 return -1;
9444 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9445 struct wpa_bss_tmp_disallowed, list) {
9446 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9447 ETH_ALEN);
9448 num_bssid++;
9449 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009450 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009451 os_free(bssids);
9452 return ret;
9453}
9454
9455
9456static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9457{
9458 struct wpa_supplicant *wpa_s = eloop_ctx;
9459 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9460
9461 /* Make sure the bss is not already freed */
9462 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9463 struct wpa_bss_tmp_disallowed, list) {
9464 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009465 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009466 wpa_set_driver_tmp_disallow_list(wpa_s);
9467 break;
9468 }
9469 }
9470}
9471
9472
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009473void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009474 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009475{
9476 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009477
9478 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9479 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009480 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009481 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009482 }
9483
9484 bss = os_malloc(sizeof(*bss));
9485 if (!bss) {
9486 wpa_printf(MSG_DEBUG,
9487 "Failed to allocate memory for temp disallow BSS");
9488 return;
9489 }
9490
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009491 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9492 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009493 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009494
9495finish:
9496 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009497 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9498 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009499}
9500
9501
Hai Shalom74f70d42019-02-11 14:42:39 -08009502int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9503 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009504{
Hai Shalom74f70d42019-02-11 14:42:39 -08009505 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009506
9507 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9508 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009509 if (ether_addr_equal(bss->bssid, tmp->bssid)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009510 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009511 break;
9512 }
9513 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009514 if (!disallowed)
9515 return 0;
9516
9517 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009518 bss->level > disallowed->rssi_threshold) {
9519 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9520 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009521 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009522 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009523
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009524 return 1;
9525}
Hai Shalom81f62d82019-07-22 12:10:00 -07009526
9527
9528int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9529 unsigned int type, const u8 *addr,
9530 const u8 *mask)
9531{
9532 if ((addr && !mask) || (!addr && mask)) {
9533 wpa_printf(MSG_INFO,
9534 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9535 return -1;
9536 }
9537
9538 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9539 wpa_printf(MSG_INFO,
9540 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9541 return -1;
9542 }
9543
9544 if (type & MAC_ADDR_RAND_SCAN) {
9545 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9546 addr, mask))
9547 return -1;
9548 }
9549
9550 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9551 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9552 addr, mask))
9553 return -1;
9554
9555 if (wpa_s->sched_scanning && !wpa_s->pno)
9556 wpas_scan_restart_sched_scan(wpa_s);
9557 }
9558
9559 if (type & MAC_ADDR_RAND_PNO) {
9560 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9561 addr, mask))
9562 return -1;
9563
9564 if (wpa_s->pno) {
9565 wpas_stop_pno(wpa_s);
9566 wpas_start_pno(wpa_s);
9567 }
9568 }
9569
9570 return 0;
9571}
9572
9573
9574int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9575 unsigned int type)
9576{
9577 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9578 if (wpa_s->pno) {
9579 if (type & MAC_ADDR_RAND_PNO) {
9580 wpas_stop_pno(wpa_s);
9581 wpas_start_pno(wpa_s);
9582 }
9583 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9584 wpas_scan_restart_sched_scan(wpa_s);
9585 }
9586
9587 return 0;
9588}
Hai Shalomfdcde762020-04-02 11:19:20 -07009589
9590
9591int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9592 struct wpa_signal_info *si)
9593{
9594 int res;
9595
9596 if (!wpa_s->driver->signal_poll)
9597 return -1;
9598
9599 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9600
9601#ifdef CONFIG_TESTING_OPTIONS
9602 if (res == 0) {
9603 struct driver_signal_override *dso;
9604
9605 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9606 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009607 if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009608 continue;
9609 wpa_printf(MSG_DEBUG,
9610 "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 +00009611 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009612 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009613 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009614 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009615 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009616 dso->si_avg_beacon_signal,
9617 si->current_noise,
9618 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009619 si->data.signal = dso->si_current_signal;
9620 si->data.avg_signal = dso->si_avg_signal;
9621 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009622 si->current_noise = dso->si_current_noise;
9623 break;
9624 }
9625 }
9626#endif /* CONFIG_TESTING_OPTIONS */
9627
9628 return res;
9629}
9630
9631
9632struct wpa_scan_results *
Sunil Ravi99c035e2024-07-12 01:42:03 +00009633wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07009634{
9635 struct wpa_scan_results *scan_res;
9636#ifdef CONFIG_TESTING_OPTIONS
9637 size_t idx;
9638#endif /* CONFIG_TESTING_OPTIONS */
9639
Sunil Ravi99c035e2024-07-12 01:42:03 +00009640 if (wpa_s->driver->get_scan_results)
9641 scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
9642 bssid);
9643 else if (wpa_s->driver->get_scan_results2)
9644 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9645 else
Hai Shalomfdcde762020-04-02 11:19:20 -07009646 return NULL;
9647
Hai Shalomfdcde762020-04-02 11:19:20 -07009648
9649#ifdef CONFIG_TESTING_OPTIONS
9650 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9651 struct driver_signal_override *dso;
9652 struct wpa_scan_res *res = scan_res->res[idx];
9653
9654 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9655 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009656 if (!ether_addr_equal(res->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009657 continue;
9658 wpa_printf(MSG_DEBUG,
9659 "Override driver scan signal level %d->%d for "
9660 MACSTR,
9661 res->level, dso->scan_level,
9662 MAC2STR(res->bssid));
9663 res->flags |= WPA_SCAN_QUAL_INVALID;
9664 if (dso->scan_level < 0)
9665 res->flags |= WPA_SCAN_LEVEL_DBM;
9666 else
9667 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9668 res->level = dso->scan_level;
9669 break;
9670 }
9671 }
9672#endif /* CONFIG_TESTING_OPTIONS */
9673
9674 return scan_res;
9675}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009676
9677
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009678bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009679{
9680 int i;
9681
9682 if (!wpa_s->valid_links)
9683 return false;
9684
Sunil Ravi99c035e2024-07-12 01:42:03 +00009685 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009686 if (ether_addr_equal(wpa_s->links[i].bssid, addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00009687 return true;
9688 }
9689
9690 return false;
9691}
9692
9693
9694int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9695 unsigned int wait, const u8 *dst, const u8 *src,
9696 const u8 *bssid, const u8 *data, size_t data_len,
9697 int no_cck)
9698{
9699 if (!wpa_s->driver->send_action)
9700 return -1;
9701
9702 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9703 if (wpas_ap_link_address(wpa_s, dst))
9704 dst = wpa_s->ap_mld_addr;
9705
9706 if (wpas_ap_link_address(wpa_s, bssid))
9707 bssid = wpa_s->ap_mld_addr;
9708 }
9709
9710 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9711 bssid, data, data_len, no_cck);
9712}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009713
9714
9715bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9716{
9717 struct hostapd_channel_data *chnl;
9718 int i, j;
9719
9720 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9721 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9722 chnl = wpa_s->hw.modes[i].channels;
9723 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9724 if (only_enabled &&
9725 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9726 continue;
9727 if (is_6ghz_freq(chnl[j].freq))
9728 return true;
9729 }
9730 }
9731 }
9732
9733 return false;
9734}
Sunil Ravi7f769292024-07-23 22:21:32 +00009735
9736
9737bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
9738 struct wpa_bss *bss)
9739{
9740 int i;
9741
9742 if (!bss)
9743 return false;
9744 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9745 wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9746 return true;
9747
9748 if (!wpa_s->valid_links)
9749 return false;
9750
9751 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9752 if (!(wpa_s->valid_links & BIT(i)))
9753 continue;
9754 if (wpa_s->links[i].bss &&
9755 (wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9756 RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9757 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9758 RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
9759 return true;
9760 }
9761
9762 return false;
9763}
9764
9765
9766bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
9767 struct wpa_bss *bss)
9768{
9769 int i;
9770
9771 if (!bss)
9772 return false;
9773 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9774 return true;
9775
9776 if (!wpa_s->valid_links)
9777 return false;
9778
9779 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9780 if (!(wpa_s->valid_links & BIT(i)))
9781 continue;
9782 if (wpa_s->links[i].bss &&
9783 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9784 RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9785 return true;
9786 }
9787
9788 return false;
9789}