blob: 3fde0a8aaa237043b728b36224a3862593ea0752 [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"
Hai Shalomc1a21442022-02-04 13:43:00 -080077"Copyright (c) 2003-2022, 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);
129#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
130static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
131#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700132#ifdef CONFIG_OWE
133static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
134#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700135
136
Hai Shalomfdcde762020-04-02 11:19:20 -0700137#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700138/* Configure default/group WEP keys for static WEP */
139int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
140{
141 int i, set = 0;
142
143 for (i = 0; i < NUM_WEP_KEYS; i++) {
144 if (ssid->wep_key_len[i] == 0)
145 continue;
146
147 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000148 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700150 ssid->wep_key[i], ssid->wep_key_len[i],
151 i == ssid->wep_tx_keyidx ?
152 KEY_FLAG_GROUP_RX_TX_DEFAULT :
153 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700154 }
155
156 return set;
157}
Hai Shalomfdcde762020-04-02 11:19:20 -0700158#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159
160
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700161int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
162 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700163{
164 u8 key[32];
165 size_t keylen;
166 enum wpa_alg alg;
167 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800168 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169
170 /* IBSS/WPA-None uses only one key (Group) for both receiving and
171 * sending unicast and multicast packets. */
172
173 if (ssid->mode != WPAS_MODE_IBSS) {
174 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
175 "IBSS/ad-hoc) for WPA-None", ssid->mode);
176 return -1;
177 }
178
179 if (!ssid->psk_set) {
180 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
181 "WPA-None");
182 return -1;
183 }
184
185 switch (wpa_s->group_cipher) {
186 case WPA_CIPHER_CCMP:
187 os_memcpy(key, ssid->psk, 16);
188 keylen = 16;
189 alg = WPA_ALG_CCMP;
190 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700191 case WPA_CIPHER_GCMP:
192 os_memcpy(key, ssid->psk, 16);
193 keylen = 16;
194 alg = WPA_ALG_GCMP;
195 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700196 case WPA_CIPHER_TKIP:
197 /* WPA-None uses the same Michael MIC key for both TX and RX */
198 os_memcpy(key, ssid->psk, 16 + 8);
199 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
200 keylen = 32;
201 alg = WPA_ALG_TKIP;
202 break;
203 default:
204 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
205 "WPA-None", wpa_s->group_cipher);
206 return -1;
207 }
208
209 /* TODO: should actually remember the previously used seq#, both for TX
210 * and RX from each STA.. */
211
Sunil Ravi77d572f2023-01-17 23:58:31 +0000212 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700213 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800214 os_memset(key, 0, sizeof(key));
215 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700216}
217
218
219static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
220{
221 struct wpa_supplicant *wpa_s = eloop_ctx;
222 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700223 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
224 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
225 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700226 bssid = wpa_s->pending_bssid;
227 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
228 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800229 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700230 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800232 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700233 wpa_s->reassociate = 1;
234
235 /*
236 * If we timed out, the AP or the local radio may be busy.
237 * So, wait a second until scanning again.
238 */
239 wpa_supplicant_req_scan(wpa_s, 1, 0);
240}
241
242
243/**
244 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
245 * @wpa_s: Pointer to wpa_supplicant data
246 * @sec: Number of seconds after which to time out authentication
247 * @usec: Number of microseconds after which to time out authentication
248 *
249 * This function is used to schedule a timeout for the current authentication
250 * attempt.
251 */
252void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
253 int sec, int usec)
254{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700255 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700256 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
257 return;
258
259 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
260 "%d usec", sec, usec);
261 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700262 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700263 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
264}
265
266
Roshan Pius3a1667e2018-07-03 15:17:14 -0700267/*
268 * wpas_auth_timeout_restart - Restart and change timeout for authentication
269 * @wpa_s: Pointer to wpa_supplicant data
270 * @sec_diff: difference in seconds applied to original timeout value
271 */
272void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
273{
274 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
275
276 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
277 wpa_dbg(wpa_s, MSG_DEBUG,
278 "Authentication timeout restart: %d sec", new_sec);
279 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
280 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
281 wpa_s, NULL);
282 }
283}
284
285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286/**
287 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
288 * @wpa_s: Pointer to wpa_supplicant data
289 *
290 * This function is used to cancel authentication timeout scheduled with
291 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
292 * been completed.
293 */
294void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
295{
296 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
297 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800298 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700299 os_free(wpa_s->last_con_fail_realm);
300 wpa_s->last_con_fail_realm = NULL;
301 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700302}
303
304
305/**
306 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
307 * @wpa_s: Pointer to wpa_supplicant data
308 *
309 * This function is used to configure EAPOL state machine based on the selected
310 * authentication mode.
311 */
312void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
313{
314#ifdef IEEE8021X_EAPOL
315 struct eapol_config eapol_conf;
316 struct wpa_ssid *ssid = wpa_s->current_ssid;
317
318#ifdef CONFIG_IBSS_RSN
319 if (ssid->mode == WPAS_MODE_IBSS &&
320 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
321 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
322 /*
323 * RSN IBSS authentication is per-STA and we can disable the
324 * per-BSSID EAPOL authentication.
325 */
326 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700327 eapol_sm_notify_eap_success(wpa_s->eapol, true);
328 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329 return;
330 }
331#endif /* CONFIG_IBSS_RSN */
332
Hai Shalome21d4e82020-04-29 16:34:06 -0700333 eapol_sm_notify_eap_success(wpa_s->eapol, false);
334 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700335
336 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
337 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
338 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
339 else
340 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
341
342 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
343 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
344 eapol_conf.accept_802_1x_keys = 1;
345 eapol_conf.required_keys = 0;
346 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
347 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
348 }
349 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
350 eapol_conf.required_keys |=
351 EAPOL_REQUIRE_KEY_BROADCAST;
352 }
353
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700354 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 eapol_conf.required_keys = 0;
356 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700357 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700358 eapol_conf.workaround = ssid->eap_workaround;
359 eapol_conf.eap_disabled =
360 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
361 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
362 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700363 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800364
365#ifdef CONFIG_WPS
366 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
367 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
368 if (wpa_s->current_bss) {
369 struct wpabuf *ie;
370 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
371 WPS_IE_VENDOR_TYPE);
372 if (ie) {
373 if (wps_is_20(ie))
374 eapol_conf.wps |=
375 EAPOL_PEER_IS_WPS20_AP;
376 wpabuf_free(ie);
377 }
378 }
379 }
380#endif /* CONFIG_WPS */
381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700382 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700383
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800384#ifdef CONFIG_MACSEC
385 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
386 ieee802_1x_create_preshared_mka(wpa_s, ssid);
387 else
388 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
389#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800390#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700391}
392
393
394/**
395 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
396 * @wpa_s: Pointer to wpa_supplicant data
397 * @ssid: Configuration data for the network
398 *
399 * This function is used to configure WPA state machine and related parameters
400 * to a mode where WPA is not enabled. This is called as part of the
401 * authentication configuration when the selected network does not use WPA.
402 */
403void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
404 struct wpa_ssid *ssid)
405{
Hai Shalomfdcde762020-04-02 11:19:20 -0700406#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700408#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000409 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700410
411 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
412 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
413 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
414 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
415 else
416 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
417 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
418 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700419 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700421 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
422 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
424 wpa_s->group_cipher = WPA_CIPHER_NONE;
425 wpa_s->mgmt_group_cipher = 0;
426
Hai Shalomfdcde762020-04-02 11:19:20 -0700427#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428 for (i = 0; i < NUM_WEP_KEYS; i++) {
429 if (ssid->wep_key_len[i] > 5) {
430 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
431 wpa_s->group_cipher = WPA_CIPHER_WEP104;
432 break;
433 } else if (ssid->wep_key_len[i] > 0) {
434 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
435 wpa_s->group_cipher = WPA_CIPHER_WEP40;
436 break;
437 }
438 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700439#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700440
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
444 wpa_s->pairwise_cipher);
445 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700446 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
447 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700448
449 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000450 os_memset(&mlo, 0, sizeof(mlo));
451 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452}
453
454
Dmitry Shmidt04949592012-07-19 12:16:46 -0700455void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800456{
457 int i;
458 if (wpa_s->hw.modes == NULL)
459 return;
460
461 for (i = 0; i < wpa_s->hw.num_modes; i++) {
462 os_free(wpa_s->hw.modes[i].channels);
463 os_free(wpa_s->hw.modes[i].rates);
464 }
465
466 os_free(wpa_s->hw.modes);
467 wpa_s->hw.modes = NULL;
468}
469
470
Hai Shalomc1a21442022-02-04 13:43:00 -0800471static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
472 struct wpa_bss_tmp_disallowed *bss)
473{
474 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
475 dl_list_del(&bss->list);
476 os_free(bss);
477}
478
479
Hai Shalom74f70d42019-02-11 14:42:39 -0800480void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800481{
482 struct wpa_bss_tmp_disallowed *bss, *prev;
483
484 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800485 struct wpa_bss_tmp_disallowed, list)
486 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800487}
488
489
Paul Stewart092955c2017-02-06 09:13:09 -0800490void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
491{
492 struct fils_hlp_req *req;
493
494 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
495 list)) != NULL) {
496 dl_list_del(&req->list);
497 wpabuf_free(req->pkt);
498 os_free(req);
499 }
500}
501
502
Hai Shalomfdcde762020-04-02 11:19:20 -0700503void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
504{
505 struct wpa_supplicant *wpa_s = eloop_ctx;
506
507 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
508 return;
509 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
510 wpa_bss_flush(wpa_s);
511}
512
513
514#ifdef CONFIG_TESTING_OPTIONS
515void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
516{
517 struct driver_signal_override *dso;
518
519 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
520 struct driver_signal_override, list))) {
521 dl_list_del(&dso->list);
522 os_free(dso);
523 }
524}
525#endif /* CONFIG_TESTING_OPTIONS */
526
527
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
529{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700530 int i;
531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700533 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534 scard_deinit(wpa_s->scard);
535 wpa_s->scard = NULL;
536 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
537 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
538 l2_packet_deinit(wpa_s->l2);
539 wpa_s->l2 = NULL;
540 if (wpa_s->l2_br) {
541 l2_packet_deinit(wpa_s->l2_br);
542 wpa_s->l2_br = NULL;
543 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800544#ifdef CONFIG_TESTING_OPTIONS
545 l2_packet_deinit(wpa_s->l2_test);
546 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800547 os_free(wpa_s->get_pref_freq_list_override);
548 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700549 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
550 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800551 os_free(wpa_s->extra_sae_rejected_groups);
552 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700553 wpabuf_free(wpa_s->rsne_override_eapol);
554 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800555 wpabuf_free(wpa_s->rsnxe_override_assoc);
556 wpa_s->rsnxe_override_assoc = NULL;
557 wpabuf_free(wpa_s->rsnxe_override_eapol);
558 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700559 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800560#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700562 if (wpa_s->conf != NULL) {
563 struct wpa_ssid *ssid;
564 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
565 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566 }
567
568 os_free(wpa_s->confname);
569 wpa_s->confname = NULL;
570
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700571 os_free(wpa_s->confanother);
572 wpa_s->confanother = NULL;
573
Hai Shalomce48b4a2018-09-05 11:41:35 -0700574 os_free(wpa_s->last_con_fail_realm);
575 wpa_s->last_con_fail_realm = NULL;
576 wpa_s->last_con_fail_realm_len = 0;
577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578 wpa_sm_set_eapol(wpa_s->wpa, NULL);
579 eapol_sm_deinit(wpa_s->eapol);
580 wpa_s->eapol = NULL;
581
582 rsn_preauth_deinit(wpa_s->wpa);
583
584#ifdef CONFIG_TDLS
585 wpa_tdls_deinit(wpa_s->wpa);
586#endif /* CONFIG_TDLS */
587
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000588#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800589 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000590#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800592 ptksa_cache_deinit(wpa_s->ptksa);
593 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594 wpa_sm_deinit(wpa_s->wpa);
595 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800596 wpa_bssid_ignore_clear(wpa_s);
597
598#ifdef CONFIG_PASN
599 wpas_pasn_auth_stop(wpa_s);
600#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601
602 wpa_bss_deinit(wpa_s);
603
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700604 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605 wpa_supplicant_cancel_scan(wpa_s);
606 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800607 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
608#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
609 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
610 wpa_s, NULL);
611#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700613 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700614 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700615
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616 wpas_wps_deinit(wpa_s);
617
618 wpabuf_free(wpa_s->pending_eapol_rx);
619 wpa_s->pending_eapol_rx = NULL;
620
621#ifdef CONFIG_IBSS_RSN
622 ibss_rsn_deinit(wpa_s->ibss_rsn);
623 wpa_s->ibss_rsn = NULL;
624#endif /* CONFIG_IBSS_RSN */
625
626 sme_deinit(wpa_s);
627
628#ifdef CONFIG_AP
629 wpa_supplicant_ap_deinit(wpa_s);
630#endif /* CONFIG_AP */
631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700632 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800634#ifdef CONFIG_OFFCHANNEL
635 offchannel_deinit(wpa_s);
636#endif /* CONFIG_OFFCHANNEL */
637
638 wpa_supplicant_cancel_sched_scan(wpa_s);
639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700640 os_free(wpa_s->next_scan_freqs);
641 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800642
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800643 os_free(wpa_s->manual_scan_freqs);
644 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700645 os_free(wpa_s->select_network_scan_freqs);
646 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800647
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700648 os_free(wpa_s->manual_sched_scan_freqs);
649 wpa_s->manual_sched_scan_freqs = NULL;
650
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800651 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
652
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700653 /*
654 * Need to remove any pending gas-query radio work before the
655 * gas_query_deinit() call because gas_query::work has not yet been set
656 * for works that have not been started. gas_query_free() will be unable
657 * to cancel such pending radio works and once the pending gas-query
658 * radio work eventually gets removed, the deinit notification call to
659 * gas_query_start_cb() would result in dereferencing freed memory.
660 */
661 if (wpa_s->radio)
662 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800663 gas_query_deinit(wpa_s->gas);
664 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700665 gas_server_deinit(wpa_s->gas_server);
666 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800667
668 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700669
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700670 ieee802_1x_dealloc_kay_sm(wpa_s);
671
Dmitry Shmidt04949592012-07-19 12:16:46 -0700672 os_free(wpa_s->bssid_filter);
673 wpa_s->bssid_filter = NULL;
674
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800675 os_free(wpa_s->disallow_aps_bssid);
676 wpa_s->disallow_aps_bssid = NULL;
677 os_free(wpa_s->disallow_aps_ssid);
678 wpa_s->disallow_aps_ssid = NULL;
679
Dmitry Shmidt04949592012-07-19 12:16:46 -0700680 wnm_bss_keep_alive_deinit(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000681 wnm_btm_reset(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700682
683 ext_password_deinit(wpa_s->ext_pw);
684 wpa_s->ext_pw = NULL;
685
686 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800687 wpa_s->last_gas_resp = NULL;
688 wpabuf_free(wpa_s->prev_gas_resp);
689 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700690
691 os_free(wpa_s->last_scan_res);
692 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800693
694#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700695 if (wpa_s->drv_priv)
696 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700697 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800698#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700699
700 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
701 wpabuf_free(wpa_s->vendor_elem[i]);
702 wpa_s->vendor_elem[i] = NULL;
703 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800704
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000705#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800706 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000707#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800708
709 wpa_s->sched_scan_plans_num = 0;
710 os_free(wpa_s->sched_scan_plans);
711 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800712
713#ifdef CONFIG_MBO
714 wpa_s->non_pref_chan_num = 0;
715 os_free(wpa_s->non_pref_chan);
716 wpa_s->non_pref_chan = NULL;
717#endif /* CONFIG_MBO */
718
719 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700720
721 wpabuf_free(wpa_s->lci);
722 wpa_s->lci = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000723#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800724 wpas_clear_beacon_rep_data(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000725#endif /* CONFIG_NO_RRM */
Paul Stewart092955c2017-02-06 09:13:09 -0800726
727#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
728#ifdef CONFIG_MESH
729 {
730 struct external_pmksa_cache *entry;
731
732 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
733 struct external_pmksa_cache,
734 list)) != NULL) {
735 dl_list_del(&entry->list);
736 os_free(entry->pmksa_cache);
737 os_free(entry);
738 }
739 }
740#endif /* CONFIG_MESH */
741#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
742
743 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800744
745 wpabuf_free(wpa_s->ric_ies);
746 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700747
748#ifdef CONFIG_DPP
749 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700750 dpp_global_deinit(wpa_s->dpp);
751 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700752#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800753
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000754#ifdef CONFIG_NAN_USD
755 wpas_nan_usd_deinit(wpa_s);
756#endif /* CONFIG_NAN_USD */
757
Hai Shalom60840252021-02-19 19:02:11 -0800758#ifdef CONFIG_PASN
759 wpas_pasn_auth_stop(wpa_s);
760#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000761#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -0800762 wpas_scs_deinit(wpa_s);
763 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000764#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000765
766#ifdef CONFIG_OWE
767 os_free(wpa_s->owe_trans_scan_freq);
768 wpa_s->owe_trans_scan_freq = NULL;
769#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770}
771
772
773/**
774 * wpa_clear_keys - Clear keys configured for the driver
775 * @wpa_s: Pointer to wpa_supplicant data
776 * @addr: Previously used BSSID or %NULL if not available
777 *
778 * This function clears the encryption keys that has been previously configured
779 * for the driver.
780 */
781void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
782{
Hai Shalomc3565922019-10-28 11:58:20 -0700783 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784
785 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800786 for (i = 0; i < max; i++) {
787 if (wpa_s->keys_cleared & BIT(i))
788 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000789 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700790 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800791 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700792 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
793 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700795 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000796 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
797 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700798 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000799 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
800 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 /* MLME-SETPROTECTION.request(None) */
802 wpa_drv_mlme_setprotection(
803 wpa_s, addr,
804 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
805 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
806 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800807 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808}
809
810
811/**
812 * wpa_supplicant_state_txt - Get the connection state name as a text string
813 * @state: State (wpa_state; WPA_*)
814 * Returns: The state name as a printable text string
815 */
816const char * wpa_supplicant_state_txt(enum wpa_states state)
817{
818 switch (state) {
819 case WPA_DISCONNECTED:
820 return "DISCONNECTED";
821 case WPA_INACTIVE:
822 return "INACTIVE";
823 case WPA_INTERFACE_DISABLED:
824 return "INTERFACE_DISABLED";
825 case WPA_SCANNING:
826 return "SCANNING";
827 case WPA_AUTHENTICATING:
828 return "AUTHENTICATING";
829 case WPA_ASSOCIATING:
830 return "ASSOCIATING";
831 case WPA_ASSOCIATED:
832 return "ASSOCIATED";
833 case WPA_4WAY_HANDSHAKE:
834 return "4WAY_HANDSHAKE";
835 case WPA_GROUP_HANDSHAKE:
836 return "GROUP_HANDSHAKE";
837 case WPA_COMPLETED:
838 return "COMPLETED";
839 default:
840 return "UNKNOWN";
841 }
842}
843
844
845#ifdef CONFIG_BGSCAN
846
Hai Shalom899fcc72020-10-19 14:38:18 -0700847static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
848{
849 if (wpa_s->bgscan_ssid) {
850 bgscan_deinit(wpa_s);
851 wpa_s->bgscan_ssid = NULL;
852 }
853}
854
855
856/**
857 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
858 * @wpa_s: Pointer to the wpa_supplicant data
859 *
860 * Stop, start, or reconfigure the scan parameters depending on the method.
861 */
862void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800864 const char *name;
865
866 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
867 name = wpa_s->current_ssid->bgscan;
868 else
869 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700870 if (!name || name[0] == '\0') {
871 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800872 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700873 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800874 if (wpas_driver_bss_selection(wpa_s))
875 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800876#ifdef CONFIG_P2P
877 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
878 return;
879#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880
881 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800882 if (wpa_s->current_ssid) {
883 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
885 "bgscan");
886 /*
887 * Live without bgscan; it is only used as a roaming
888 * optimization, so the initial connection is not
889 * affected.
890 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700891 } else {
892 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700893 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700894 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
Sunil Ravi99c035e2024-07-12 01:42:03 +0000895 0, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700896 if (scan_res) {
897 bgscan_notify_scan(wpa_s, scan_res);
898 wpa_scan_results_free(scan_res);
899 }
900 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700901 } else
902 wpa_s->bgscan_ssid = NULL;
903}
904
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905#endif /* CONFIG_BGSCAN */
906
907
Dmitry Shmidt04949592012-07-19 12:16:46 -0700908static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
909{
910 if (autoscan_init(wpa_s, 0))
911 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
912}
913
914
915static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
916{
917 autoscan_deinit(wpa_s);
918}
919
920
921void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
922{
923 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
924 wpa_s->wpa_state == WPA_SCANNING) {
925 autoscan_deinit(wpa_s);
926 wpa_supplicant_start_autoscan(wpa_s);
927 }
928}
929
930
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931/**
932 * wpa_supplicant_set_state - Set current connection state
933 * @wpa_s: Pointer to wpa_supplicant data
934 * @state: The new connection state
935 *
936 * This function is called whenever the connection state changes, e.g.,
937 * association is completed for WPA/WPA2 4-Way Handshake is started.
938 */
939void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
940 enum wpa_states state)
941{
942 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700943#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700944 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700945#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946
947 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
948 wpa_supplicant_state_txt(wpa_s->wpa_state),
949 wpa_supplicant_state_txt(state));
950
Hai Shalom74f70d42019-02-11 14:42:39 -0800951 if (state == WPA_COMPLETED &&
952 os_reltime_initialized(&wpa_s->roam_start)) {
953 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
954 wpa_s->roam_start.sec = 0;
955 wpa_s->roam_start.usec = 0;
956 wpas_notify_auth_changed(wpa_s);
957 wpas_notify_roam_time(wpa_s);
958 wpas_notify_roam_complete(wpa_s);
959 } else if (state == WPA_DISCONNECTED &&
960 os_reltime_initialized(&wpa_s->roam_start)) {
961 wpa_s->roam_start.sec = 0;
962 wpa_s->roam_start.usec = 0;
963 wpa_s->roam_time.sec = 0;
964 wpa_s->roam_time.usec = 0;
965 wpas_notify_roam_complete(wpa_s);
966 }
967
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800968 if (state == WPA_INTERFACE_DISABLED) {
969 /* Assure normal scan when interface is restored */
970 wpa_s->normal_scans = 0;
971 }
972
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700973 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800974 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700975 /* Reinitialize normal_scan counter */
976 wpa_s->normal_scans = 0;
977 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800978
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700979#ifdef CONFIG_P2P
980 /*
981 * P2PS client has to reply to Probe Request frames received on the
982 * group operating channel. Enable Probe Request frame reporting for
983 * P2P connected client in case p2p_cli_probe configuration property is
984 * set to 1.
985 */
986 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
987 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
988 wpa_s->current_ssid->p2p_group) {
989 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
990 wpa_dbg(wpa_s, MSG_DEBUG,
991 "P2P: Enable CLI Probe Request RX reporting");
992 wpa_s->p2p_cli_probe =
993 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
994 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
995 wpa_dbg(wpa_s, MSG_DEBUG,
996 "P2P: Disable CLI Probe Request RX reporting");
997 wpa_s->p2p_cli_probe = 0;
998 wpa_drv_probe_req_report(wpa_s, 0);
999 }
1000 }
1001#endif /* CONFIG_P2P */
1002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 if (state != WPA_SCANNING)
1004 wpa_supplicant_notify_scanning(wpa_s, 0);
1005
1006 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001008 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001009 char mld_addr[50];
1010
1011 mld_addr[0] = '\0';
1012 if (wpa_s->valid_links)
1013 os_snprintf(mld_addr, sizeof(mld_addr),
1014 " ap_mld_addr=" MACSTR,
1015 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001016
1017#ifdef CONFIG_SME
1018 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1019 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1020 fils_hlp_sent = 1;
1021#endif /* CONFIG_SME */
1022 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1023 wpa_auth_alg_fils(wpa_s->auth_alg))
1024 fils_hlp_sent = 1;
1025
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001026#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001028 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001029 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001031 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001032 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001034 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001035 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 wpa_drv_set_operstate(wpa_s, 1);
1038#ifndef IEEE8021X_EAPOL
1039 wpa_drv_set_supp_port(wpa_s, 1);
1040#endif /* IEEE8021X_EAPOL */
1041 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001042 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001044
1045 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001046
1047#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1048 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001049 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001050#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001051#ifdef CONFIG_OWE
1052 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1053 wpas_update_owe_connect_params(wpa_s);
1054#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001055#ifdef CONFIG_HS20
1056 hs20_configure_frame_filters(wpa_s);
1057#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1059 state == WPA_ASSOCIATED) {
1060 wpa_s->new_connection = 1;
1061 wpa_drv_set_operstate(wpa_s, 0);
1062#ifndef IEEE8021X_EAPOL
1063 wpa_drv_set_supp_port(wpa_s, 0);
1064#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001065 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 }
1067 wpa_s->wpa_state = state;
1068
1069#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001070 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1071 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001072 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073 wpa_supplicant_stop_bgscan(wpa_s);
1074#endif /* CONFIG_BGSCAN */
1075
Hai Shalom5f92bc92019-04-18 11:54:11 -07001076 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001077 wpa_supplicant_stop_autoscan(wpa_s);
1078
1079 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1080 wpa_supplicant_start_autoscan(wpa_s);
1081
Sunil Ravi99c035e2024-07-12 01:42:03 +00001082 if (state == WPA_COMPLETED || state == WPA_INTERFACE_DISABLED ||
1083 state == WPA_INACTIVE)
1084 wnm_btm_reset(wpa_s);
1085
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001086#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001087 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1088 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001089#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001090
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091 if (wpa_s->wpa_state != old_state) {
1092 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1093
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001094 /*
1095 * Notify the P2P Device interface about a state change in one
1096 * of the interfaces.
1097 */
1098 wpas_p2p_indicate_state_change(wpa_s);
1099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001100 if (wpa_s->wpa_state == WPA_COMPLETED ||
1101 old_state == WPA_COMPLETED)
1102 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001103#ifdef CONFIG_DPP2
1104 if (wpa_s->wpa_state == WPA_COMPLETED)
1105 wpas_dpp_connected(wpa_s);
1106#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107 }
Hai Shalomc3565922019-10-28 11:58:20 -07001108#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1109 if (update_fils_connect_params)
1110 wpas_update_fils_connect_params(wpa_s);
1111#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112}
1113
1114
1115void wpa_supplicant_terminate_proc(struct wpa_global *global)
1116{
1117 int pending = 0;
1118#ifdef CONFIG_WPS
1119 struct wpa_supplicant *wpa_s = global->ifaces;
1120 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001121 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001122 if (wpas_wps_terminate_pending(wpa_s) == 1)
1123 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001124#ifdef CONFIG_P2P
1125 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1126 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1127 wpas_p2p_disconnect(wpa_s);
1128#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001129 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 }
1131#endif /* CONFIG_WPS */
1132 if (pending)
1133 return;
1134 eloop_terminate();
1135}
1136
1137
1138static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1139{
1140 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001141 wpa_supplicant_terminate_proc(global);
1142}
1143
1144
1145void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1146{
1147 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001148 enum wpa_states new_state;
1149
1150 if (old_state == WPA_SCANNING)
1151 new_state = WPA_SCANNING;
1152 else
1153 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154
1155 wpa_s->pairwise_cipher = 0;
1156 wpa_s->group_cipher = 0;
1157 wpa_s->mgmt_group_cipher = 0;
1158 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001159 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001161 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162
1163 if (wpa_s->wpa_state != old_state)
1164 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1165}
1166
1167
1168/**
1169 * wpa_supplicant_reload_configuration - Reload configuration data
1170 * @wpa_s: Pointer to wpa_supplicant data
1171 * Returns: 0 on success or -1 if configuration parsing failed
1172 *
1173 * This function can be used to request that the configuration data is reloaded
1174 * (e.g., after configuration file change). This function is reloading
1175 * configuration only for one interface, so this may need to be called multiple
1176 * times if %wpa_supplicant is controlling multiple interfaces and all
1177 * interfaces need reconfiguration.
1178 */
1179int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1180{
1181 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001182 int reconf_ctrl;
1183 int old_ap_scan;
1184
1185 if (wpa_s->confname == NULL)
1186 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001187 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 if (conf == NULL) {
1189 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1190 "file '%s' - exiting", wpa_s->confname);
1191 return -1;
1192 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001193 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001194 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001195 wpa_msg(wpa_s, MSG_ERROR,
1196 "Failed to parse the configuration file '%s' - exiting",
1197 wpa_s->confanother);
1198 return -1;
1199 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001200
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001201 conf->changed_parameters = (unsigned int) -1;
1202
1203 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1204 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1205 os_strcmp(conf->ctrl_interface,
1206 wpa_s->conf->ctrl_interface) != 0);
1207
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001208 if (reconf_ctrl) {
1209 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_s->ctrl_iface = NULL;
1211 }
1212
1213 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001214 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001215 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1216 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001217 wpa_supplicant_deauthenticate(wpa_s,
1218 WLAN_REASON_DEAUTH_LEAVING);
1219 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220
1221 /*
1222 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001223 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001225 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1226 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1227 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001228 /*
1229 * Clear forced success to clear EAP state for next
1230 * authentication.
1231 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001232 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001233 }
1234 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1235 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001236 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001237 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1238 rsn_preauth_deinit(wpa_s->wpa);
1239
1240 old_ap_scan = wpa_s->conf->ap_scan;
1241 wpa_config_free(wpa_s->conf);
1242 wpa_s->conf = conf;
1243 if (old_ap_scan != wpa_s->conf->ap_scan)
1244 wpas_notify_ap_scan_changed(wpa_s);
1245
1246 if (reconf_ctrl)
1247 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1248
1249 wpa_supplicant_update_config(wpa_s);
1250
1251 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001252 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253 wpa_s->reassociate = 1;
1254 wpa_supplicant_req_scan(wpa_s, 0, 0);
1255 }
Hai Shalom60840252021-02-19 19:02:11 -08001256 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001257 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1258 return 0;
1259}
1260
1261
1262static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1263{
1264 struct wpa_global *global = signal_ctx;
1265 struct wpa_supplicant *wpa_s;
1266 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1267 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1268 sig);
1269 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1270 wpa_supplicant_terminate_proc(global);
1271 }
1272 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001273
1274 if (wpa_debug_reopen_file() < 0) {
1275 /* Ignore errors since we cannot really do much to fix this */
1276 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1277 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001278}
1279
1280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001281static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1282 struct wpa_ssid *ssid,
1283 struct wpa_ie_data *ie)
1284{
1285 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1286 if (ret) {
1287 if (ret == -2) {
1288 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1289 "from association info");
1290 }
1291 return -1;
1292 }
1293
1294 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1295 "cipher suites");
1296 if (!(ie->group_cipher & ssid->group_cipher)) {
1297 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1298 "cipher 0x%x (mask 0x%x) - reject",
1299 ie->group_cipher, ssid->group_cipher);
1300 return -1;
1301 }
1302 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1303 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1304 "cipher 0x%x (mask 0x%x) - reject",
1305 ie->pairwise_cipher, ssid->pairwise_cipher);
1306 return -1;
1307 }
1308 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1309 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1310 "management 0x%x (mask 0x%x) - reject",
1311 ie->key_mgmt, ssid->key_mgmt);
1312 return -1;
1313 }
1314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001316 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1318 "that does not support management frame protection - "
1319 "reject");
1320 return -1;
1321 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001322
1323 return 0;
1324}
1325
1326
Hai Shalom021b0b52019-04-10 11:17:58 -07001327static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1328 int freq)
1329{
1330 if (!ie->has_group)
1331 ie->group_cipher = wpa_default_rsn_cipher(freq);
1332 if (!ie->has_pairwise)
1333 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1334 return (ie->group_cipher & ssid->group_cipher) &&
1335 (ie->pairwise_cipher & ssid->pairwise_cipher);
1336}
1337
1338
Hai Shalomc1a21442022-02-04 13:43:00 -08001339void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1340 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1341{
1342 int sel;
1343
1344 sel = ie->mgmt_group_cipher;
1345 if (ssid->group_mgmt_cipher)
1346 sel &= ssid->group_mgmt_cipher;
1347 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1348 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1349 sel = 0;
1350 wpa_dbg(wpa_s, MSG_DEBUG,
1351 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1352 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1353 if (sel & WPA_CIPHER_AES_128_CMAC) {
1354 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1355 wpa_dbg(wpa_s, MSG_DEBUG,
1356 "WPA: using MGMT group cipher AES-128-CMAC");
1357 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1358 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1359 wpa_dbg(wpa_s, MSG_DEBUG,
1360 "WPA: using MGMT group cipher BIP-GMAC-128");
1361 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1362 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1363 wpa_dbg(wpa_s, MSG_DEBUG,
1364 "WPA: using MGMT group cipher BIP-GMAC-256");
1365 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1366 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1367 wpa_dbg(wpa_s, MSG_DEBUG,
1368 "WPA: using MGMT group cipher BIP-CMAC-256");
1369 } else {
1370 wpa_s->mgmt_group_cipher = 0;
1371 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1372 }
1373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1374 wpa_s->mgmt_group_cipher);
1375 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1376 wpas_get_ssid_pmf(wpa_s, ssid));
1377}
1378
Sunil Ravi77d572f2023-01-17 23:58:31 +00001379/**
1380 * wpa_supplicant_get_psk - Get PSK from config or external database
1381 * @wpa_s: Pointer to wpa_supplicant data
1382 * @bss: Scan results for the selected BSS, or %NULL if not available
1383 * @ssid: Configuration data for the selected network
1384 * @psk: Buffer for the PSK
1385 * Returns: 0 on success or -1 if configuration parsing failed
1386 *
1387 * This function obtains the PSK for a network, either included inline in the
1388 * config or retrieved from an external database.
1389 */
1390static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1391 struct wpa_bss *bss, struct wpa_ssid *ssid,
1392 u8 *psk)
1393{
1394 if (ssid->psk_set) {
1395 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1396 ssid->psk, PMK_LEN);
1397 os_memcpy(psk, ssid->psk, PMK_LEN);
1398 return 0;
1399 }
1400
1401#ifndef CONFIG_NO_PBKDF2
1402 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1403 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1404 4096, psk, PMK_LEN) != 0) {
1405 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1406 return -1;
1407 }
1408 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1409 psk, PMK_LEN);
1410 return 0;
1411 }
1412#endif /* CONFIG_NO_PBKDF2 */
1413
1414#ifdef CONFIG_EXT_PASSWORD
1415 if (ssid->ext_psk) {
1416 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1417 ssid->ext_psk);
1418 char pw_str[64 + 1];
1419
1420 if (!pw) {
1421 wpa_msg(wpa_s, MSG_INFO,
1422 "EXT PW: No PSK found from external storage");
1423 return -1;
1424 }
1425
1426 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1427 wpa_msg(wpa_s, MSG_INFO,
1428 "EXT PW: Unexpected PSK length %d in external storage",
1429 (int) wpabuf_len(pw));
1430 ext_password_free(pw);
1431 return -1;
1432 }
1433
1434 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1435 pw_str[wpabuf_len(pw)] = '\0';
1436
1437#ifndef CONFIG_NO_PBKDF2
1438 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1439 {
1440 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1441 4096, psk, PMK_LEN) != 0) {
1442 wpa_msg(wpa_s, MSG_WARNING,
1443 "Error in pbkdf2_sha1()");
1444 forced_memzero(pw_str, sizeof(pw_str));
1445 ext_password_free(pw);
1446 return -1;
1447 }
1448 wpa_hexdump_key(MSG_MSGDUMP,
1449 "PSK (from external passphrase)",
1450 psk, PMK_LEN);
1451 } else
1452#endif /* CONFIG_NO_PBKDF2 */
1453 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1454 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1455 wpa_msg(wpa_s, MSG_INFO,
1456 "EXT PW: Invalid PSK hex string");
1457 forced_memzero(pw_str, sizeof(pw_str));
1458 ext_password_free(pw);
1459 return -1;
1460 }
1461 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1462 psk, PMK_LEN);
1463 } else {
1464 wpa_msg(wpa_s, MSG_INFO,
1465 "EXT PW: No suitable PSK available");
1466 forced_memzero(pw_str, sizeof(pw_str));
1467 ext_password_free(pw);
1468 return -1;
1469 }
1470
1471 forced_memzero(pw_str, sizeof(pw_str));
1472 ext_password_free(pw);
1473
1474 return 0;
1475 }
1476#endif /* CONFIG_EXT_PASSWORD */
1477
1478 return -1;
1479}
1480
Hai Shalomc1a21442022-02-04 13:43:00 -08001481
Sunil Ravi89eba102022-09-13 21:04:37 -07001482static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1483 struct wpa_ssid *ssid)
1484{
1485 int akm_count = wpa_s->max_num_akms;
1486 u8 capab = 0;
1487
1488 if (akm_count < 2)
1489 return;
1490
1491 akm_count--;
1492 wpa_s->allowed_key_mgmts = 0;
1493 switch (wpa_s->key_mgmt) {
1494 case WPA_KEY_MGMT_PSK:
1495 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1496 akm_count--;
1497 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1498 }
1499 if (!akm_count)
1500 break;
1501 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1502 akm_count--;
1503 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1504 }
1505 if (!akm_count)
1506 break;
1507 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1508 wpa_s->allowed_key_mgmts |=
1509 WPA_KEY_MGMT_PSK_SHA256;
1510 break;
1511 case WPA_KEY_MGMT_PSK_SHA256:
1512 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1513 akm_count--;
1514 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1515 }
1516 if (!akm_count)
1517 break;
1518 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1519 akm_count--;
1520 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1521 }
1522 if (!akm_count)
1523 break;
1524 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1525 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1526 break;
1527 case WPA_KEY_MGMT_SAE:
1528 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1529 akm_count--;
1530 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1531 }
1532 if (!akm_count)
1533 break;
1534 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1535 akm_count--;
1536 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1537 }
1538 if (!akm_count)
1539 break;
1540 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1541 wpa_s->allowed_key_mgmts |=
1542 WPA_KEY_MGMT_PSK_SHA256;
1543 break;
1544 case WPA_KEY_MGMT_SAE_EXT_KEY:
1545 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1546 akm_count--;
1547 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1548 }
1549 if (!akm_count)
1550 break;
1551 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1552 akm_count--;
1553 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1554 }
1555 if (!akm_count)
1556 break;
1557 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1558 wpa_s->allowed_key_mgmts |=
1559 WPA_KEY_MGMT_PSK_SHA256;
1560 break;
1561 default:
1562 return;
1563 }
1564
Sunil Ravi77d572f2023-01-17 23:58:31 +00001565 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1566 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001567 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1568#ifdef CONFIG_SAE_PK
1569 if (ssid->sae_pk)
1570 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1571#endif /* CONFIG_SAE_PK */
1572
1573 if (!((wpa_s->allowed_key_mgmts &
1574 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1575 return;
1576
1577 if (!wpa_s->rsnxe_len) {
1578 wpa_s->rsnxe_len = 3;
1579 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1580 wpa_s->rsnxe[1] = 1;
1581 wpa_s->rsnxe[2] = 0;
1582 }
1583
1584 wpa_s->rsnxe[2] |= capab;
1585}
1586
1587
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001588/**
1589 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1590 * @wpa_s: Pointer to wpa_supplicant data
1591 * @bss: Scan results for the selected BSS, or %NULL if not available
1592 * @ssid: Configuration data for the selected network
1593 * @wpa_ie: Buffer for the WPA/RSN IE
1594 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1595 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001596 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001597 * Returns: 0 on success or -1 on failure
1598 *
1599 * This function is used to configure authentication and encryption parameters
1600 * based on the network configuration and scan result for the selected BSS (if
1601 * available).
1602 */
1603int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1604 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001605 u8 *wpa_ie, size_t *wpa_ie_len,
1606 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607{
1608 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001609 int sel, proto;
1610 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001611 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001612 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613
1614 if (bss) {
1615 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1616 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001617 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001618 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001619 } else {
1620 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1621 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622
1623 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1624 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001625 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001626 (ie.key_mgmt & ssid->key_mgmt)) {
1627 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1628 proto = WPA_PROTO_RSN;
1629 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001630 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 (ie.group_cipher & ssid->group_cipher) &&
1632 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1633 (ie.key_mgmt & ssid->key_mgmt)) {
1634 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1635 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001636#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001637 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1638 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1639 (ie.group_cipher & ssid->group_cipher) &&
1640 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1641 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001642 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001643 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001644 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1645 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1646 (ie.group_cipher & ssid->group_cipher) &&
1647 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1648 (ie.key_mgmt & ssid->key_mgmt)) {
1649 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1650 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001651#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 } else if (bss) {
1653 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001654 wpa_dbg(wpa_s, MSG_DEBUG,
1655 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1656 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1657 ssid->key_mgmt);
1658 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1659 MAC2STR(bss->bssid),
1660 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1661 bss_wpa ? " WPA" : "",
1662 bss_rsn ? " RSN" : "",
1663 bss_osen ? " OSEN" : "");
1664 if (bss_rsn) {
1665 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1666 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1667 wpa_dbg(wpa_s, MSG_DEBUG,
1668 "Could not parse RSN element");
1669 } else {
1670 wpa_dbg(wpa_s, MSG_DEBUG,
1671 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1672 ie.pairwise_cipher, ie.group_cipher,
1673 ie.key_mgmt);
1674 }
1675 }
1676 if (bss_wpa) {
1677 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1678 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1679 wpa_dbg(wpa_s, MSG_DEBUG,
1680 "Could not parse WPA element");
1681 } else {
1682 wpa_dbg(wpa_s, MSG_DEBUG,
1683 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1684 ie.pairwise_cipher, ie.group_cipher,
1685 ie.key_mgmt);
1686 }
1687 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688 return -1;
1689 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001690 if (ssid->proto & WPA_PROTO_OSEN)
1691 proto = WPA_PROTO_OSEN;
1692 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693 proto = WPA_PROTO_RSN;
1694 else
1695 proto = WPA_PROTO_WPA;
1696 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1697 os_memset(&ie, 0, sizeof(ie));
1698 ie.group_cipher = ssid->group_cipher;
1699 ie.pairwise_cipher = ssid->pairwise_cipher;
1700 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001701 ie.mgmt_group_cipher = 0;
1702 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1703 if (ssid->group_mgmt_cipher &
1704 WPA_CIPHER_BIP_GMAC_256)
1705 ie.mgmt_group_cipher =
1706 WPA_CIPHER_BIP_GMAC_256;
1707 else if (ssid->group_mgmt_cipher &
1708 WPA_CIPHER_BIP_CMAC_256)
1709 ie.mgmt_group_cipher =
1710 WPA_CIPHER_BIP_CMAC_256;
1711 else if (ssid->group_mgmt_cipher &
1712 WPA_CIPHER_BIP_GMAC_128)
1713 ie.mgmt_group_cipher =
1714 WPA_CIPHER_BIP_GMAC_128;
1715 else
1716 ie.mgmt_group_cipher =
1717 WPA_CIPHER_AES_128_CMAC;
1718 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001719#ifdef CONFIG_OWE
1720 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1721 !ssid->owe_only &&
1722 !bss_wpa && !bss_rsn && !bss_osen) {
1723 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1724 wpa_s->wpa_proto = 0;
1725 *wpa_ie_len = 0;
1726 return 0;
1727 }
1728#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001729 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1730 "based on configuration");
1731 } else
1732 proto = ie.proto;
1733 }
1734
1735 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1736 "pairwise %d key_mgmt %d proto %d",
1737 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001738 if (ssid->ieee80211w) {
1739 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1740 ie.mgmt_group_cipher);
1741 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001742
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001743 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1745 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001746 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747
1748 if (bss || !wpa_s->ap_ies_from_associnfo) {
1749 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1750 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1751 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001752 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1753 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1754 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001755 return -1;
1756 }
1757
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001758#ifdef CONFIG_NO_WPA
1759 wpa_s->group_cipher = WPA_CIPHER_NONE;
1760 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1761#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001763 wpa_dbg(wpa_s, MSG_DEBUG,
1764 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1765 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001766 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1767 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001768 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1769 "cipher");
1770 return -1;
1771 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001772 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1773 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001774
1775 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001776 wpa_dbg(wpa_s, MSG_DEBUG,
1777 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1778 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001779 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1780 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1782 "cipher");
1783 return -1;
1784 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001785 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1786 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001787#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788
1789 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001790#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001791 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1792 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001793 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001794 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1795 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001796#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001797#ifdef CONFIG_IEEE80211R
1798 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1799 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1800 sel &= ~WPA_KEY_MGMT_FT;
1801#endif /* CONFIG_IEEE80211R */
1802 wpa_dbg(wpa_s, MSG_DEBUG,
1803 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1804 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001806#ifdef CONFIG_IEEE80211R
1807#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001808 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1809 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001810 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1811 wpa_dbg(wpa_s, MSG_DEBUG,
1812 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001813 if (!ssid->ft_eap_pmksa_caching &&
1814 pmksa_cache_get_current(wpa_s->wpa)) {
1815 /* PMKSA caching with FT may have interoperability
1816 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001817 wpa_dbg(wpa_s, MSG_DEBUG,
1818 "WPA: Disable PMKSA caching for FT/802.1X connection");
1819 pmksa_cache_clear_current(wpa_s->wpa);
1820 }
1821#endif /* CONFIG_SHA384 */
1822#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001823#ifdef CONFIG_SUITEB192
1824 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1825 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1826 wpa_dbg(wpa_s, MSG_DEBUG,
1827 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1828#endif /* CONFIG_SUITEB192 */
1829#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001830 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1831 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1832 wpa_dbg(wpa_s, MSG_DEBUG,
1833 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001834#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001835#ifdef CONFIG_SHA384
1836 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1837 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1838 wpa_dbg(wpa_s, MSG_DEBUG,
1839 "WPA: using KEY_MGMT 802.1X with SHA384");
1840#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001841#ifdef CONFIG_FILS
1842#ifdef CONFIG_IEEE80211R
1843 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1844 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1845 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001846#endif /* CONFIG_IEEE80211R */
1847 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1848 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1849 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001850#ifdef CONFIG_IEEE80211R
1851 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1852 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1853 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1854#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001855 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1856 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1857 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1858#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001859#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001860 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1861 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1863 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001864 if (!ssid->ft_eap_pmksa_caching &&
1865 pmksa_cache_get_current(wpa_s->wpa)) {
1866 /* PMKSA caching with FT may have interoperability
1867 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001868 wpa_dbg(wpa_s, MSG_DEBUG,
1869 "WPA: Disable PMKSA caching for FT/802.1X connection");
1870 pmksa_cache_clear_current(wpa_s->wpa);
1871 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001872#endif /* CONFIG_IEEE80211R */
1873#ifdef CONFIG_DPP
1874 } else if (sel & WPA_KEY_MGMT_DPP) {
1875 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1876 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1877#endif /* CONFIG_DPP */
1878#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001879 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1880 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1881 wpa_dbg(wpa_s, MSG_DEBUG,
1882 "RSN: using KEY_MGMT FT/SAE (ext key)");
1883 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1884 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1885 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001886 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1887 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1888 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1889 } else if (sel & WPA_KEY_MGMT_SAE) {
1890 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1891 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1892#endif /* CONFIG_SAE */
1893#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001894 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1895 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1896 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1897#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1899 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1900 wpa_dbg(wpa_s, MSG_DEBUG,
1901 "WPA: using KEY_MGMT 802.1X with SHA256");
1902 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1903 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1904 wpa_dbg(wpa_s, MSG_DEBUG,
1905 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1907 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1908 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1909 } else if (sel & WPA_KEY_MGMT_PSK) {
1910 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1911 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1912 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1913 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1914 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001915#ifdef CONFIG_HS20
1916 } else if (sel & WPA_KEY_MGMT_OSEN) {
1917 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1918 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1919#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001920#ifdef CONFIG_OWE
1921 } else if (sel & WPA_KEY_MGMT_OWE) {
1922 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1923 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1924#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 } else {
1926 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1927 "authenticated key management type");
1928 return -1;
1929 }
1930
1931 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1932 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1933 wpa_s->pairwise_cipher);
1934 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1935
Hai Shalomc3565922019-10-28 11:58:20 -07001936 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001937 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1938 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001939 wpa_msg(wpa_s, MSG_INFO,
1940 "RSN: Management frame protection required but the selected AP does not enable it");
1941 return -1;
1942 }
1943
Hai Shalomc1a21442022-02-04 13:43:00 -08001944 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001945#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001946 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1947 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1948 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001949#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001950 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001951 if ((ssid->sae_password_id ||
1952 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001953 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1954 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1955 if (bss && is_6ghz_freq(bss->freq) &&
1956 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1957 wpa_dbg(wpa_s, MSG_DEBUG,
1958 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1959 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001960 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001961 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001962#ifdef CONFIG_SAE_PK
1963 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1964 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1965 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1966 ((ssid->sae_password &&
1967 sae_pk_valid_password(ssid->sae_password)) ||
1968 (!ssid->sae_password && ssid->passphrase &&
1969 sae_pk_valid_password(ssid->passphrase))));
1970#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001971 if (bss && is_6ghz_freq(bss->freq) &&
1972 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1973 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1974 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1975 MGMT_FRAME_PROTECTION_REQUIRED);
1976 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001977#ifdef CONFIG_TESTING_OPTIONS
1978 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1979 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001980 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1981 wpa_s->oci_freq_override_eapol);
1982 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1983 wpa_s->oci_freq_override_eapol_g2);
1984 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1985 wpa_s->oci_freq_override_ft_assoc);
1986 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1987 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001988 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1989 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001990#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001991
1992 /* Extended Key ID is only supported in infrastructure BSS so far */
1993 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1994 (ssid->proto & WPA_PROTO_RSN) &&
1995 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1996 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1997 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1998 int use_ext_key_id = 0;
1999
2000 wpa_msg(wpa_s, MSG_DEBUG,
2001 "WPA: Enable Extended Key ID support");
2002 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
2003 wpa_s->conf->extended_key_id);
2004 if (bss_rsn &&
2005 wpa_s->conf->extended_key_id &&
2006 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
2007 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
2008 use_ext_key_id = 1;
2009 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
2010 use_ext_key_id);
2011 } else {
2012 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
2013 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
2014 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015
Sunil Ravi640215c2023-06-28 23:08:09 +00002016 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2017 * appropriate advertisement of the supported number of PTKSA receive
2018 * counters. In theory, this could be based on a driver capability, but
2019 * in practice all cases using WMM support at least eight replay
2020 * counters, so use a hardcoded value for now since there is no explicit
2021 * driver capability indication for this.
2022 *
2023 * In addition, claim WMM to be enabled if the AP supports it since it
2024 * is far more likely for any current device to support WMM. */
2025 wmm = wpa_s->connection_set &&
2026 (wpa_s->connection_ht || wpa_s->connection_vht ||
2027 wpa_s->connection_he || wpa_s->connection_eht);
2028 if (!wmm && bss)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002029 wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002030 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2031
Sunil Ravi77d572f2023-01-17 23:58:31 +00002032 if (!skip_default_rsne) {
2033 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2034 wpa_ie_len)) {
2035 wpa_msg(wpa_s, MSG_WARNING,
2036 "RSN: Failed to generate RSNE/WPA IE");
2037 return -1;
2038 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039
Sunil Ravi77d572f2023-01-17 23:58:31 +00002040 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2041 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2042 &wpa_s->rsnxe_len)) {
2043 wpa_msg(wpa_s, MSG_WARNING,
2044 "RSN: Failed to generate RSNXE");
2045 return -1;
2046 }
Hai Shalomc3565922019-10-28 11:58:20 -07002047 }
2048
Hai Shalom021b0b52019-04-10 11:17:58 -07002049 if (0) {
2050#ifdef CONFIG_DPP
2051 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2052 /* Use PMK from DPP network introduction (PMKSA entry) */
2053 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002054#ifdef CONFIG_DPP2
2055 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2056#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002057#endif /* CONFIG_DPP */
2058 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002059 int psk_set = 0;
2060
Sunil Ravi77d572f2023-01-17 23:58:31 +00002061 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2062 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002063
Sunil Ravi77d572f2023-01-17 23:58:31 +00002064 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2065 psk) == 0) {
2066 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2067 NULL);
2068 psk_set = 1;
2069 }
2070 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002071 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002072
Roshan Pius3a1667e2018-07-03 15:17:14 -07002073 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002074 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002075 psk_set = 1;
2076
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002077 if (!psk_set) {
2078 wpa_msg(wpa_s, MSG_INFO,
2079 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002080 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002081 return -1;
2082 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002083#ifdef CONFIG_OWE
2084 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2085 /* OWE Diffie-Hellman exchange in (Re)Association
2086 * Request/Response frames set the PMK, so do not override it
2087 * here. */
2088#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002089 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2091
Hai Shalomfdcde762020-04-02 11:19:20 -07002092 if (ssid->mode != WPAS_MODE_IBSS &&
2093 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2094 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2095 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2096 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2097 wpa_msg(wpa_s, MSG_INFO,
2098 "Disable PTK0 rekey support - replaced with reconnect");
2099 wpa_s->deny_ptk0_rekey = 1;
2100 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2101 } else {
2102 wpa_s->deny_ptk0_rekey = 0;
2103 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2104 }
2105
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002106#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2107 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302108 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002109 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2110 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002111 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2112 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302113 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2114 wpa_dbg(wpa_s, MSG_INFO,
2115 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2116 }
Sunil Ravif42be322022-11-04 03:31:21 +00002117#else
2118 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2119 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2120 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002121#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2122 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302123
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124 return 0;
2125}
2126
2127
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002128static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2129 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002130{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002131#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002132 bool scs = true, mscs = true;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002133#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08002134
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002135 *pos = 0x00;
2136
2137 switch (idx) {
2138 case 0: /* Bits 0-7 */
2139 break;
2140 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002141 if (wpa_s->conf->coloc_intf_reporting) {
2142 /* Bit 13 - Collocated Interference Reporting */
2143 *pos |= 0x20;
2144 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002145 break;
2146 case 2: /* Bits 16-23 */
2147#ifdef CONFIG_WNM
2148 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002149 if ((wpas_driver_bss_selection(wpa_s) ||
2150 !wpa_s->disable_mbo_oce) &&
2151 !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002152 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002153#endif /* CONFIG_WNM */
2154 break;
2155 case 3: /* Bits 24-31 */
2156#ifdef CONFIG_WNM
2157 *pos |= 0x02; /* Bit 25 - SSID List */
2158#endif /* CONFIG_WNM */
2159#ifdef CONFIG_INTERWORKING
2160 if (wpa_s->conf->interworking)
2161 *pos |= 0x80; /* Bit 31 - Interworking */
2162#endif /* CONFIG_INTERWORKING */
2163 break;
2164 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002165#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002166 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002167 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002168#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002169 break;
2170 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002171#ifdef CONFIG_HS20
2172 if (wpa_s->conf->hs20)
2173 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2174#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002175#ifdef CONFIG_MBO
2176 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2177#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002178 break;
2179 case 6: /* Bits 48-55 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002180#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002181#ifdef CONFIG_TESTING_OPTIONS
2182 if (wpa_s->disable_scs_support)
2183 scs = false;
2184#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002185 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2186 /* Drop own SCS capability indication since the AP does
2187 * not support it. This is needed to avoid
2188 * interoperability issues with APs that get confused
2189 * with Extended Capabilities element. */
2190 scs = false;
2191 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002192 if (scs)
2193 *pos |= 0x40; /* Bit 54 - SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002194#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002195 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002196 case 7: /* Bits 56-63 */
2197 break;
2198 case 8: /* Bits 64-71 */
2199 if (wpa_s->conf->ftm_responder)
2200 *pos |= 0x40; /* Bit 70 - FTM responder */
2201 if (wpa_s->conf->ftm_initiator)
2202 *pos |= 0x80; /* Bit 71 - FTM initiator */
2203 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002204 case 9: /* Bits 72-79 */
2205#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002206 if (!wpa_s->disable_fils)
2207 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002208#endif /* CONFIG_FILS */
2209 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002210 case 10: /* Bits 80-87 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002211#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002212#ifdef CONFIG_TESTING_OPTIONS
2213 if (wpa_s->disable_mscs_support)
2214 mscs = false;
2215#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002216 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2217 /* Drop own MSCS capability indication since the AP does
2218 * not support it. This is needed to avoid
2219 * interoperability issues with APs that get confused
2220 * with Extended Capabilities element. */
2221 mscs = false;
2222 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002223 if (mscs)
2224 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002225#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002226 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002227 }
2228}
2229
2230
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002231int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2232 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002233{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002234 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002235 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002236
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002237 if (len < wpa_s->extended_capa_len)
2238 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002239 if (buflen < (size_t) len + 2) {
2240 wpa_printf(MSG_INFO,
2241 "Not enough room for building extended capabilities element");
2242 return -1;
2243 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002244
2245 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002246 *pos++ = len;
2247 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002248 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002249
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002250 if (i < wpa_s->extended_capa_len) {
2251 *pos &= ~wpa_s->extended_capa_mask[i];
2252 *pos |= wpa_s->extended_capa[i];
2253 }
2254 }
2255
2256 while (len > 0 && buf[1 + len] == 0) {
2257 len--;
2258 buf[1] = len;
2259 }
2260 if (len == 0)
2261 return 0;
2262
2263 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002264}
2265
2266
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002267static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2268 struct wpa_bss *test_bss)
2269{
2270 struct wpa_bss *bss;
2271
2272 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2273 if (bss == test_bss)
2274 return 1;
2275 }
2276
2277 return 0;
2278}
2279
2280
2281static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2282 struct wpa_ssid *test_ssid)
2283{
2284 struct wpa_ssid *ssid;
2285
2286 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2287 if (ssid == test_ssid)
2288 return 1;
2289 }
2290
2291 return 0;
2292}
2293
2294
2295int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2296 struct wpa_ssid *test_ssid)
2297{
2298 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2299 return 0;
2300
2301 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2302}
2303
2304
2305void wpas_connect_work_free(struct wpa_connect_work *cwork)
2306{
2307 if (cwork == NULL)
2308 return;
2309 os_free(cwork);
2310}
2311
2312
2313void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2314{
2315 struct wpa_connect_work *cwork;
2316 struct wpa_radio_work *work = wpa_s->connect_work;
2317
2318 if (!work)
2319 return;
2320
2321 wpa_s->connect_work = NULL;
2322 cwork = work->ctx;
2323 work->ctx = NULL;
2324 wpas_connect_work_free(cwork);
2325 radio_work_done(work);
2326}
2327
2328
Sunil Ravi77d572f2023-01-17 23:58:31 +00002329int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2330 enum wpas_mac_addr_style style,
2331 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002332{
2333 struct os_reltime now;
2334 u8 addr[ETH_ALEN];
2335
2336 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002337 /* Random addresses are valid within a given ESS so check
2338 * expiration/value only when continuing to use the same ESS. */
2339 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2340 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2341 /* Pregenerated addresses do not expire but their value
2342 * might have changed, so let's check that. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002343 if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
Sunil Ravi77d572f2023-01-17 23:58:31 +00002344 return 0;
2345 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2346 wpa_s->last_mac_addr_change.usec != 0) &&
2347 !os_reltime_expired(
2348 &now,
2349 &wpa_s->last_mac_addr_change,
2350 wpa_s->conf->rand_addr_lifetime)) {
2351 wpa_msg(wpa_s, MSG_DEBUG,
2352 "Previously selected random MAC address has not yet expired");
2353 return 0;
2354 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002355 }
2356
2357 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002358 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002359 if (random_mac_addr(addr) < 0)
2360 return -1;
2361 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002362 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002363 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2364 if (random_mac_addr_keep_oui(addr) < 0)
2365 return -1;
2366 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002367 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2368 if (!ssid) {
2369 wpa_msg(wpa_s, MSG_INFO,
2370 "Invalid 'ssid' for address policy 3");
2371 return -1;
2372 }
2373 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2374 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002375 default:
2376 return -1;
2377 }
2378
2379 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2380 wpa_msg(wpa_s, MSG_INFO,
2381 "Failed to set random MAC address");
2382 return -1;
2383 }
2384
2385 os_get_reltime(&wpa_s->last_mac_addr_change);
2386 wpa_s->mac_addr_changed = 1;
2387 wpa_s->last_mac_addr_style = style;
2388
2389 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2390 wpa_msg(wpa_s, MSG_INFO,
2391 "Could not update MAC address information");
2392 return -1;
2393 }
2394
2395 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2396 MAC2STR(addr));
2397
Sunil Ravi77d572f2023-01-17 23:58:31 +00002398 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002399}
2400
2401
2402int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2403{
2404 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2405 !wpa_s->conf->preassoc_mac_addr)
2406 return 0;
2407
Sunil Ravi77d572f2023-01-17 23:58:31 +00002408 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2409 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002410}
2411
2412
Sunil Ravi036cec52023-03-29 11:35:17 -07002413void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2414 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002415{
2416#ifdef CONFIG_SAE
2417 int *groups = conf->sae_groups;
2418 int default_groups[] = { 19, 20, 21, 0 };
2419 const char *password;
2420
2421 if (!groups || groups[0] <= 0)
2422 groups = default_groups;
2423
2424 password = ssid->sae_password;
2425 if (!password)
2426 password = ssid->passphrase;
2427
Hai Shalom899fcc72020-10-19 14:38:18 -07002428 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002429 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002430 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002431 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002432 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002433 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002434 /* PT derivation not needed */
2435 sae_deinit_pt(ssid->pt);
2436 ssid->pt = NULL;
2437 return;
2438 }
2439
2440 if (ssid->pt)
2441 return; /* PT already derived */
2442 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2443 (const u8 *) password, os_strlen(password),
2444 ssid->sae_password_id);
2445#endif /* CONFIG_SAE */
2446}
2447
2448
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002449static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2450{
2451#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2452 os_free(wpa_s->sme.sae_rejected_groups);
2453 wpa_s->sme.sae_rejected_groups = NULL;
2454#ifdef CONFIG_TESTING_OPTIONS
2455 if (wpa_s->extra_sae_rejected_groups) {
2456 int i, *groups = wpa_s->extra_sae_rejected_groups;
2457
2458 for (i = 0; groups[i]; i++) {
2459 wpa_printf(MSG_DEBUG,
2460 "TESTING: Indicate rejection of an extra SAE group %d",
2461 groups[i]);
2462 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2463 groups[i]);
2464 }
2465 }
2466#endif /* CONFIG_TESTING_OPTIONS */
2467#endif /* CONFIG_SAE && CONFIG_SME */
2468}
2469
2470
Hai Shalom60840252021-02-19 19:02:11 -08002471int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2472{
2473 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2474 wpa_msg(wpa_s, MSG_INFO,
2475 "Could not restore permanent MAC address");
2476 return -1;
2477 }
2478 wpa_s->mac_addr_changed = 0;
2479 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2480 wpa_msg(wpa_s, MSG_INFO,
2481 "Could not update MAC address information");
2482 return -1;
2483 }
2484 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2485 return 0;
2486}
2487
2488
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002489static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2490
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491/**
2492 * wpa_supplicant_associate - Request association
2493 * @wpa_s: Pointer to wpa_supplicant data
2494 * @bss: Scan results for the selected BSS, or %NULL if not available
2495 * @ssid: Configuration data for the selected network
2496 *
2497 * This function is used to request %wpa_supplicant to associate with a BSS.
2498 */
2499void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2500 struct wpa_bss *bss, struct wpa_ssid *ssid)
2501{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002502 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002503 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002504
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002505 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002506 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002507
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002508 /*
2509 * If we are starting a new connection, any previously pending EAPOL
2510 * RX cannot be valid anymore.
2511 */
2512 wpabuf_free(wpa_s->pending_eapol_rx);
2513 wpa_s->pending_eapol_rx = NULL;
2514
Sunil Ravi77d572f2023-01-17 23:58:31 +00002515 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002516 rand_style = wpa_s->conf->mac_addr;
2517 else
2518 rand_style = ssid->mac_addr;
2519
Sunil Ravia04bd252022-05-02 22:54:18 -07002520 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002521 wpa_s->multi_ap_ie = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002522#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002523 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002524#endif /* CONFIG_NO_WMM_AC */
2525#ifdef CONFIG_WNM
2526 wpa_s->wnm_mode = 0;
Sunil Ravi99c035e2024-07-12 01:42:03 +00002527 wpa_s->wnm_target_bss = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002528#endif /* CONFIG_WNM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002529 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002530 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002531#ifdef CONFIG_TESTING_OPTIONS
2532 wpa_s->testing_resend_assoc = 0;
2533#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002534
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002535 if (wpa_s->last_ssid == ssid) {
2536 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002537 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002538 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002539#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002540 wmm_ac_save_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002541#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002542 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002543 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2544 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002545 }
Hai Shalomc3565922019-10-28 11:58:20 -07002546 } else {
2547#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002548 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002549#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002550 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002551#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002552 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002553#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002554
Sunil Ravi77d572f2023-01-17 23:58:31 +00002555 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2556 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2557
2558 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002559 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002560 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2561 status > 0) /* MAC changed */
2562 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2563 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2564 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002565 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002566 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002567 }
2568 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569
2570#ifdef CONFIG_IBSS_RSN
2571 ibss_rsn_deinit(wpa_s->ibss_rsn);
2572 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002573#else /* CONFIG_IBSS_RSN */
2574 if (ssid->mode == WPAS_MODE_IBSS &&
2575 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2576 wpa_msg(wpa_s, MSG_INFO,
2577 "IBSS RSN not supported in the build");
2578 return;
2579 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580#endif /* CONFIG_IBSS_RSN */
2581
2582 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2583 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2584#ifdef CONFIG_AP
2585 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2586 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2587 "mode");
2588 return;
2589 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002590 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2591 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302592 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2593 ssid->mode == WPAS_MODE_P2P_GO) {
2594 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002595 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302596 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002597 return;
2598 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 wpa_s->current_bss = bss;
2600#else /* CONFIG_AP */
2601 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2602 "the build");
2603#endif /* CONFIG_AP */
2604 return;
2605 }
2606
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002607 if (ssid->mode == WPAS_MODE_MESH) {
2608#ifdef CONFIG_MESH
2609 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2610 wpa_msg(wpa_s, MSG_INFO,
2611 "Driver does not support mesh mode");
2612 return;
2613 }
2614 if (bss)
2615 ssid->frequency = bss->freq;
2616 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002617 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002618 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2619 return;
2620 }
2621 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002622#else /* CONFIG_MESH */
2623 wpa_msg(wpa_s, MSG_ERROR,
2624 "mesh mode support not included in the build");
2625#endif /* CONFIG_MESH */
2626 return;
2627 }
2628
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002629 /*
2630 * Set WPA state machine configuration to match the selected network now
2631 * so that the information is available before wpas_start_assoc_cb()
2632 * gets called. This is needed at least for RSN pre-authentication where
2633 * candidate APs are added to a list based on scan result processing
2634 * before completion of the first association.
2635 */
2636 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2637
2638#ifdef CONFIG_DPP
2639 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2640 return;
2641#endif /* CONFIG_DPP */
2642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643#ifdef CONFIG_TDLS
2644 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002645 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646#endif /* CONFIG_TDLS */
2647
Hai Shalomc3565922019-10-28 11:58:20 -07002648#ifdef CONFIG_MBO
2649 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2650#endif /* CONFIG_MBO */
2651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002653 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 sme_authenticate(wpa_s, bss, ssid);
2655 return;
2656 }
2657
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002658 if (wpa_s->connect_work) {
2659 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2660 return;
2661 }
2662
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002663 if (radio_work_pending(wpa_s, "connect")) {
2664 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2665 return;
2666 }
2667
Dmitry Shmidt29333592017-01-09 12:27:11 -08002668#ifdef CONFIG_SME
2669 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2670 /* Clear possibly set auth_alg, if any, from last attempt. */
2671 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2672 }
2673#endif /* CONFIG_SME */
2674
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002675 wpas_abort_ongoing_scan(wpa_s);
2676
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002677 cwork = os_zalloc(sizeof(*cwork));
2678 if (cwork == NULL)
2679 return;
2680
2681 cwork->bss = bss;
2682 cwork->ssid = ssid;
2683
2684 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2685 wpas_start_assoc_cb, cwork) < 0) {
2686 os_free(cwork);
2687 }
2688}
2689
2690
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002691static int bss_is_ibss(struct wpa_bss *bss)
2692{
2693 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2694 IEEE80211_CAP_IBSS;
2695}
2696
2697
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002698static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2699 const struct wpa_ssid *ssid)
2700{
2701 enum hostapd_hw_mode hw_mode;
2702 struct hostapd_hw_modes *mode = NULL;
2703 u8 channel;
2704 int i;
2705
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002706 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2707 if (hw_mode == NUM_HOSTAPD_MODES)
2708 return 0;
2709 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2710 if (wpa_s->hw.modes[i].mode == hw_mode) {
2711 mode = &wpa_s->hw.modes[i];
2712 break;
2713 }
2714 }
2715
2716 if (!mode)
2717 return 0;
2718
2719 return mode->vht_capab != 0;
2720}
2721
2722
Hai Shalomc1a21442022-02-04 13:43:00 -08002723static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2724{
2725 int i;
2726
2727 for (i = channel; i < channel + 16; i += 4) {
2728 struct hostapd_channel_data *chan;
2729
2730 chan = hw_get_channel_chan(mode, i, NULL);
2731 if (!chan ||
2732 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2733 return false;
2734 }
2735
2736 return true;
2737}
2738
2739
Sunil Ravi036cec52023-03-29 11:35:17 -07002740static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2741 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002742{
Sunil Ravi036cec52023-03-29 11:35:17 -07002743 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002744
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002745 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2746 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2747
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002748 if (!bss_is_ibss(bss))
2749 continue;
2750
2751 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002752 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2753 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002754 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002755 return NULL;
2756}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002757
Sunil Ravi036cec52023-03-29 11:35:17 -07002758
2759static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2760 const struct wpa_ssid *ssid,
2761 struct hostapd_hw_modes *mode)
2762{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002763 /* For IBSS check HT_IBSS flag */
2764 if (ssid->mode == WPAS_MODE_IBSS &&
2765 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002766 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002767
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002768 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2769 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2770 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2771 wpa_printf(MSG_DEBUG,
2772 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002773 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002774 }
2775
Sunil Ravi036cec52023-03-29 11:35:17 -07002776 if (!ht_supported(mode))
2777 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002778
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002779#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002780 if (ssid->disable_ht)
2781 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002782#endif /* CONFIG_HT_OVERRIDES */
2783
Sunil Ravi036cec52023-03-29 11:35:17 -07002784 return true;
2785}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002786
Sunil Ravi036cec52023-03-29 11:35:17 -07002787
2788static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2789 const struct wpa_ssid *ssid,
2790 struct hostapd_hw_modes *mode)
2791{
2792 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2793 return false;
2794
2795 if (!drv_supports_vht(wpa_s, ssid))
2796 return false;
2797
2798 /* For IBSS check VHT_IBSS flag */
2799 if (ssid->mode == WPAS_MODE_IBSS &&
2800 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2801 return false;
2802
2803 if (!vht_supported(mode))
2804 return false;
2805
2806#ifdef CONFIG_VHT_OVERRIDES
2807 if (ssid->disable_vht)
2808 return false;
2809#endif /* CONFIG_VHT_OVERRIDES */
2810
2811 return true;
2812}
2813
2814
2815static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2816 const struct wpa_ssid *ssid,
2817 const struct hostapd_hw_modes *mode,
2818 int ieee80211_mode)
2819{
Hai Shalomfdcde762020-04-02 11:19:20 -07002820#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002821 if (ssid->disable_he)
2822 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002823#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002824
Sunil Ravi036cec52023-03-29 11:35:17 -07002825 switch (mode->mode) {
2826 case HOSTAPD_MODE_IEEE80211G:
2827 case HOSTAPD_MODE_IEEE80211B:
2828 case HOSTAPD_MODE_IEEE80211A:
2829 return mode->he_capab[ieee80211_mode].he_supported;
2830 default:
2831 return false;
2832 }
2833}
2834
2835
2836static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2837 const struct wpa_ssid *ssid,
2838 const struct hostapd_hw_modes *mode,
2839 int ieee80211_mode)
2840{
2841 if (ssid->disable_eht)
2842 return false;
2843
2844 switch(mode->mode) {
2845 case HOSTAPD_MODE_IEEE80211G:
2846 case HOSTAPD_MODE_IEEE80211B:
2847 case HOSTAPD_MODE_IEEE80211A:
2848 return mode->eht_capab[ieee80211_mode].eht_supported;
2849 default:
2850 return false;
2851 }
2852}
2853
2854
2855static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2856 const struct wpa_ssid *ssid,
2857 struct hostapd_hw_modes *mode,
2858 struct hostapd_freq_params *freq,
2859 int obss_scan) {
2860 int chan_idx;
2861 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2862 int i, res;
2863 unsigned int j;
2864 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002865 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2866 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002867 };
2868 int ht40 = -1;
2869
2870 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002871 return;
2872
2873 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2874 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002875 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002876 break;
2877 pri_chan = NULL;
2878 }
2879 if (!pri_chan)
2880 return;
2881
2882 /* Check primary channel flags */
2883 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2884 return;
2885
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002886#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002887 if (ssid->disable_ht40)
2888 return;
2889#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002890
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002891 /* Check/setup HT40+/HT40- */
2892 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002893 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002894 ht40 = 1;
2895 break;
2896 }
2897 }
2898
2899 /* Find secondary channel */
2900 for (i = 0; i < mode->num_channels; i++) {
2901 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002902 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002903 break;
2904 sec_chan = NULL;
2905 }
2906 if (!sec_chan)
2907 return;
2908
2909 /* Check secondary channel flags */
2910 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2911 return;
2912
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002913 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002914 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2915 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002916 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002917 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2918 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002919 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002920 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002921
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002922 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002923 struct wpa_scan_results *scan_res;
2924
Sunil Ravi99c035e2024-07-12 01:42:03 +00002925 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
2926 NULL);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002927 if (scan_res == NULL) {
2928 /* Back to HT20 */
2929 freq->sec_channel_offset = 0;
2930 return;
2931 }
2932
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002933 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002934 switch (res) {
2935 case 0:
2936 /* Back to HT20 */
2937 freq->sec_channel_offset = 0;
2938 break;
2939 case 1:
2940 /* Configuration allowed */
2941 break;
2942 case 2:
2943 /* Switch pri/sec channels */
2944 freq->freq = hw_get_freq(mode, sec_chan->chan);
2945 freq->sec_channel_offset = -freq->sec_channel_offset;
2946 freq->channel = sec_chan->chan;
2947 break;
2948 default:
2949 freq->sec_channel_offset = 0;
2950 break;
2951 }
2952
2953 wpa_scan_results_free(scan_res);
2954 }
2955
2956 wpa_printf(MSG_DEBUG,
2957 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2958 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002959}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002960
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002961
Sunil Ravi036cec52023-03-29 11:35:17 -07002962static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2963 const struct wpa_ssid *ssid,
2964 struct hostapd_hw_modes *mode,
2965 struct hostapd_freq_params *freq,
2966 int ieee80211_mode, bool is_6ghz) {
2967 static const int bw80[] = {
2968 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2969 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2970 6515, 6595, 6675, 6755, 6835, 6915, 6995
2971 };
2972 static const int bw160[] = {
2973 5955, 6115, 6275, 6435, 6595, 6755, 6915
2974 };
2975 struct hostapd_freq_params vht_freq;
2976 int i;
2977 unsigned int j, k;
2978 int chwidth, seg0, seg1;
2979 u32 vht_caps = 0;
2980 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002981
Sunil Ravi036cec52023-03-29 11:35:17 -07002982 if (!freq->vht_enabled && !freq->he_enabled)
2983 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002984
Hai Shalomc1a21442022-02-04 13:43:00 -08002985 vht_freq = *freq;
2986
Sunil Ravi036cec52023-03-29 11:35:17 -07002987 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2988 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2989 seg1 = 0;
2990 if (freq->sec_channel_offset == 0) {
2991 seg0 = 0;
2992 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2993 if (freq->ht_enabled && !is_6ghz)
2994 goto skip_80mhz;
2995 }
2996 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2997 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002998
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002999 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003000 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
3001 if (freq->freq >= bw80[j] &&
3002 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003003 break;
3004 }
3005
Hai Shalomc1a21442022-02-04 13:43:00 -08003006 if (j == ARRAY_SIZE(bw80) ||
3007 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003008 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003009
Sunil Ravi036cec52023-03-29 11:35:17 -07003010 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08003011 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07003012 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003013
Sunil8cd6f4d2022-06-28 18:40:46 +00003014 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003015 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003016 seg1 = 0;
3017
Sunil Ravi036cec52023-03-29 11:35:17 -07003018 /* In 160 MHz, the initial four 20 MHz channels were validated
3019 * above. If 160 MHz is supported, check the remaining four 20 MHz
3020 * channels for the total of 160 MHz bandwidth for 6 GHz.
3021 */
Hai Shalomc1a21442022-02-04 13:43:00 -08003022 if ((mode->he_capab[ieee80211_mode].phy_cap[
3023 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07003024 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
3025 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003026 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
3027 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003028 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003029 seg0 = channel + 14;
3030 break;
3031 }
3032 }
3033 }
3034
Sunil8cd6f4d2022-06-28 18:40:46 +00003035 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003036 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003037 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003038 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003039 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003040 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003041
3042 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3043 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003044 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003045
3046 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003047 struct hostapd_channel_data *chan;
3048
3049 chan = hw_get_channel_chan(mode, i, NULL);
3050 if (!chan)
3051 continue;
3052
3053 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3054 HOSTAPD_CHAN_NO_IR |
3055 HOSTAPD_CHAN_RADAR))
3056 continue;
3057
3058 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003059 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003060 if (!is_6ghz)
3061 vht_caps |=
3062 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3063 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003064 }
3065
Sunil8cd6f4d2022-06-28 18:40:46 +00003066 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003067 break;
3068 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003069 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003070 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003071 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003072 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3073 seg0 = 50;
3074 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003075 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003076 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3077 seg0 = 114;
3078 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003079 }
3080
Sunil Ravi036cec52023-03-29 11:35:17 -07003081skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003082 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003083 freq->channel, ssid->enable_edmg,
3084 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003085 freq->vht_enabled, freq->he_enabled,
3086 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003087 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003088 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003089 &mode->he_capab[ieee80211_mode],
Sunil Ravi99c035e2024-07-12 01:42:03 +00003090 &mode->eht_capab[ieee80211_mode], 0) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003091 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003092
3093 *freq = vht_freq;
3094
3095 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3096 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003097 return true;
3098}
3099
3100
3101void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3102 const struct wpa_ssid *ssid,
3103 struct hostapd_freq_params *freq)
3104{
3105 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3106 enum hostapd_hw_mode hw_mode;
3107 struct hostapd_hw_modes *mode = NULL;
3108 int i, obss_scan = 1;
3109 u8 channel;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003110 bool is_6ghz, is_24ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003111
3112 freq->freq = ssid->frequency;
3113
3114 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3115 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3116
3117 if (bss) {
3118 wpa_printf(MSG_DEBUG,
3119 "IBSS already found in scan results, adjust control freq: %d",
3120 bss->freq);
3121 freq->freq = bss->freq;
3122 obss_scan = 0;
3123 }
3124 }
3125
3126 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3127 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3128 if (wpa_s->hw.modes[i].mode == hw_mode &&
3129 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3130 NULL) != NULL) {
3131 mode = &wpa_s->hw.modes[i];
3132 break;
3133 }
3134 }
3135
3136 if (!mode)
3137 return;
3138
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003139 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
3140 hw_mode == HOSTAPD_MODE_IEEE80211B;
3141
Sunil Ravi036cec52023-03-29 11:35:17 -07003142 is_6ghz = is_6ghz_freq(freq->freq);
3143
3144 freq->ht_enabled = 0;
3145 freq->vht_enabled = 0;
3146 freq->he_enabled = 0;
3147 freq->eht_enabled = 0;
3148
3149 if (!is_6ghz)
3150 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3151 if (freq->ht_enabled)
3152 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003153 if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003154 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3155 ieee80211_mode);
3156 freq->channel = channel;
3157 /* Setup higher BW only for 5 GHz */
3158 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3159 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3160 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3161 ieee80211_mode, is_6ghz))
3162 freq->he_enabled = freq->vht_enabled = false;
3163 }
3164
3165 if (freq->he_enabled)
3166 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3167 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003168}
3169
3170
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003171#ifdef CONFIG_FILS
3172static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3173 size_t ie_buf_len)
3174{
3175 struct fils_hlp_req *req;
3176 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3177 const u8 *pos;
3178 u8 *buf = ie_buf;
3179
3180 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3181 list) {
3182 rem_len = ie_buf_len - ie_len;
3183 pos = wpabuf_head(req->pkt);
3184 hdr_len = 1 + 2 * ETH_ALEN + 6;
3185 hlp_len = wpabuf_len(req->pkt);
3186
3187 if (rem_len < 2 + hdr_len + hlp_len) {
3188 wpa_printf(MSG_ERROR,
3189 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3190 (unsigned long) rem_len,
3191 (unsigned long) (2 + hdr_len + hlp_len));
3192 break;
3193 }
3194
3195 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3196 /* Element ID */
3197 *buf++ = WLAN_EID_EXTENSION;
3198 /* Length */
3199 *buf++ = len;
3200 /* Element ID Extension */
3201 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3202 /* Destination MAC address */
3203 os_memcpy(buf, req->dst, ETH_ALEN);
3204 buf += ETH_ALEN;
3205 /* Source MAC address */
3206 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3207 buf += ETH_ALEN;
3208 /* LLC/SNAP Header */
3209 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3210 buf += 6;
3211 /* HLP Packet */
3212 os_memcpy(buf, pos, len - hdr_len);
3213 buf += len - hdr_len;
3214 pos += len - hdr_len;
3215
3216 hlp_len -= len - hdr_len;
3217 ie_len += 2 + len;
3218 rem_len -= 2 + len;
3219
3220 while (hlp_len) {
3221 len = (hlp_len > 255) ? 255 : hlp_len;
3222 if (rem_len < 2 + len)
3223 break;
3224 *buf++ = WLAN_EID_FRAGMENT;
3225 *buf++ = len;
3226 os_memcpy(buf, pos, len);
3227 buf += len;
3228 pos += len;
3229
3230 hlp_len -= len;
3231 ie_len += 2 + len;
3232 rem_len -= 2 + len;
3233 }
3234 }
3235
3236 return ie_len;
3237}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003238
3239
3240int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3241{
3242 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3243 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3244 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3245 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3246}
3247
3248
3249int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3250{
3251#ifdef CONFIG_FILS_SK_PFS
3252 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3253 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3254#else /* CONFIG_FILS_SK_PFS */
3255 return 0;
3256#endif /* CONFIG_FILS_SK_PFS */
3257}
3258
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259#endif /* CONFIG_FILS */
3260
3261
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003262bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3263{
3264 const u8 *wfa_capa;
3265
3266 if (!bss)
3267 return false;
3268
3269 /* Get WFA capability from Beacon or Probe Response frame elements */
3270 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3271 if (!wfa_capa)
3272 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3273 bss, WFA_CAPA_IE_VENDOR_TYPE);
3274
3275 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3276 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3277 /* AP does not enable QM non EHT traffic description policy */
3278 return false;
3279 }
3280
3281 return true;
3282}
3283
3284
Hai Shalomc1a21442022-02-04 13:43:00 -08003285static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3286 struct wpa_bss *bss,
3287 u8 *wpa_ie, size_t wpa_ie_len,
3288 size_t max_wpa_ie_len)
3289{
3290 struct wpabuf *wfa_ie = NULL;
3291 u8 wfa_capa[1];
3292 size_t wfa_ie_len, buf_len;
3293
3294 os_memset(wfa_capa, 0, sizeof(wfa_capa));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003295#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003296 if (wpa_s->enable_dscp_policy_capa)
3297 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003298#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003299
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003300 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3301 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3302
Hai Shalomc1a21442022-02-04 13:43:00 -08003303 if (!wfa_capa[0])
3304 return wpa_ie_len;
3305
3306 /* Wi-Fi Alliance element */
3307 buf_len = 1 + /* Element ID */
3308 1 + /* Length */
3309 3 + /* OUI */
3310 1 + /* OUI Type */
3311 1 + /* Capabilities Length */
3312 sizeof(wfa_capa); /* Capabilities */
3313 wfa_ie = wpabuf_alloc(buf_len);
3314 if (!wfa_ie)
3315 return wpa_ie_len;
3316
3317 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3318 wpabuf_put_u8(wfa_ie, buf_len - 2);
3319 wpabuf_put_be24(wfa_ie, OUI_WFA);
3320 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3321 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3322 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3323
3324 wfa_ie_len = wpabuf_len(wfa_ie);
3325 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3326 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3327 wfa_ie);
3328 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3329 wfa_ie_len);
3330 wpa_ie_len += wfa_ie_len;
3331 }
3332
3333 wpabuf_free(wfa_ie);
3334 return wpa_ie_len;
3335}
3336
3337
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003338static u8 * wpas_populate_assoc_ies(
3339 struct wpa_supplicant *wpa_s,
3340 struct wpa_bss *bss, struct wpa_ssid *ssid,
3341 struct wpa_driver_associate_params *params,
3342 enum wpa_drv_update_connect_params_mask *mask)
3343{
3344 u8 *wpa_ie;
3345 size_t max_wpa_ie_len = 500;
3346 size_t wpa_ie_len;
3347 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003348#ifdef CONFIG_MBO
3349 const u8 *mbo_ie;
3350#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303351#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3352 int pmksa_cached = 0;
3353#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003354#ifdef CONFIG_FILS
3355 const u8 *realm, *username, *rrk;
3356 size_t realm_len, username_len, rrk_len;
3357 u16 next_seq_num;
3358 struct fils_hlp_req *req;
3359
3360 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3361 list) {
3362 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3363 2 + 2 * wpabuf_len(req->pkt) / 255;
3364 }
3365#endif /* CONFIG_FILS */
3366
3367 wpa_ie = os_malloc(max_wpa_ie_len);
3368 if (!wpa_ie) {
3369 wpa_printf(MSG_ERROR,
3370 "Failed to allocate connect IE buffer for %lu bytes",
3371 (unsigned long) max_wpa_ie_len);
3372 return NULL;
3373 }
3374
3375 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3376 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3377 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3378 int try_opportunistic;
3379 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003380 const u8 *addr = bss->bssid;
3381
Sunil Ravi036cec52023-03-29 11:35:17 -07003382 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3383 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3384 !is_zero_ether_addr(bss->mld_addr))
3385 addr = bss->mld_addr;
3386
3387 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3388 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003389 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390
3391 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3392 wpa_s->conf->okc :
3393 ssid->proactive_key_caching) &&
3394 (ssid->proto & WPA_PROTO_RSN);
3395#ifdef CONFIG_FILS
3396 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3397 cache_id = wpa_bss_get_fils_cache_id(bss);
3398#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003399 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003400 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003401 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003402 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303403#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3404 pmksa_cached = 1;
3405#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003406 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003407 wpa_ie_len = max_wpa_ie_len;
3408 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003409 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003410 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3411 "key management and encryption suites");
3412 os_free(wpa_ie);
3413 return NULL;
3414 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003415#ifdef CONFIG_HS20
3416 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3417 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3418 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3419 wpa_ie_len = max_wpa_ie_len;
3420 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003421 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003422 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3423 "key management and encryption suites");
3424 os_free(wpa_ie);
3425 return NULL;
3426 }
3427#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003428 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3429 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3430 /*
3431 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3432 * use non-WPA since the scan results did not indicate that the
3433 * AP is using WPA or WPA2.
3434 */
3435 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3436 wpa_ie_len = 0;
3437 wpa_s->wpa_proto = 0;
3438 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3439 wpa_ie_len = max_wpa_ie_len;
3440 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003441 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003442 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3443 "key management and encryption suites (no "
3444 "scan results)");
3445 os_free(wpa_ie);
3446 return NULL;
3447 }
3448#ifdef CONFIG_WPS
3449 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3450 struct wpabuf *wps_ie;
3451 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3452 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3453 wpa_ie_len = wpabuf_len(wps_ie);
3454 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3455 } else
3456 wpa_ie_len = 0;
3457 wpabuf_free(wps_ie);
3458 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3459 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3460 params->wps = WPS_MODE_PRIVACY;
3461 else
3462 params->wps = WPS_MODE_OPEN;
3463 wpa_s->wpa_proto = 0;
3464#endif /* CONFIG_WPS */
3465 } else {
3466 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3467 wpa_ie_len = 0;
3468 wpa_s->wpa_proto = 0;
3469 }
3470
3471#ifdef IEEE8021X_EAPOL
3472 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3473 if (ssid->leap) {
3474 if (ssid->non_leap == 0)
3475 algs = WPA_AUTH_ALG_LEAP;
3476 else
3477 algs |= WPA_AUTH_ALG_LEAP;
3478 }
3479 }
3480
3481#ifdef CONFIG_FILS
3482 /* Clear FILS association */
3483 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3484
3485 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3486 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3487 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3488 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003489 &next_seq_num, &rrk, &rrk_len) == 0 &&
3490 (!wpa_s->last_con_fail_realm ||
3491 wpa_s->last_con_fail_realm_len != realm_len ||
3492 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003493 algs = WPA_AUTH_ALG_FILS;
3494 params->fils_erp_username = username;
3495 params->fils_erp_username_len = username_len;
3496 params->fils_erp_realm = realm;
3497 params->fils_erp_realm_len = realm_len;
3498 params->fils_erp_next_seq_num = next_seq_num;
3499 params->fils_erp_rrk = rrk;
3500 params->fils_erp_rrk_len = rrk_len;
3501
3502 if (mask)
3503 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303504 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3505 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3506 pmksa_cached) {
3507 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003508 }
3509#endif /* CONFIG_FILS */
3510#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003511#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003512 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003513 algs = WPA_AUTH_ALG_SAE;
3514#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003515
3516 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3517 if (ssid->auth_alg) {
3518 algs = ssid->auth_alg;
3519 wpa_dbg(wpa_s, MSG_DEBUG,
3520 "Overriding auth_alg selection: 0x%x", algs);
3521 }
3522
Hai Shalom5f92bc92019-04-18 11:54:11 -07003523#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303524 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003525 wpa_dbg(wpa_s, MSG_DEBUG,
3526 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3527 algs = WPA_AUTH_ALG_OPEN;
3528 }
3529#endif /* CONFIG_SAE */
3530
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003531#ifdef CONFIG_P2P
3532 if (wpa_s->global->p2p) {
3533 u8 *pos;
3534 size_t len;
3535 int res;
3536 pos = wpa_ie + wpa_ie_len;
3537 len = max_wpa_ie_len - wpa_ie_len;
3538 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3539 ssid->p2p_group);
3540 if (res >= 0)
3541 wpa_ie_len += res;
3542 }
3543
3544 wpa_s->cross_connect_disallowed = 0;
3545 if (bss) {
3546 struct wpabuf *p2p;
3547 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3548 if (p2p) {
3549 wpa_s->cross_connect_disallowed =
3550 p2p_get_cross_connect_disallowed(p2p);
3551 wpabuf_free(p2p);
3552 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3553 "connection",
3554 wpa_s->cross_connect_disallowed ?
3555 "disallows" : "allows");
3556 }
3557 }
3558
3559 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3560#endif /* CONFIG_P2P */
3561
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003562#ifndef CONFIG_NO_RRM
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003563 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003564 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003565 wpa_ie + wpa_ie_len,
3566 max_wpa_ie_len -
3567 wpa_ie_len);
3568 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003569#endif /* CONFIG_NO_RRM */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003570
3571 /*
3572 * Workaround: Add Extended Capabilities element only if the AP
3573 * included this element in Beacon/Probe Response frames. Some older
3574 * APs seem to have interoperability issues if this element is
3575 * included, so while the standard may require us to include the
3576 * element in all cases, it is justifiable to skip it to avoid
3577 * interoperability issues.
3578 */
3579 if (ssid->p2p_group)
3580 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3581 else
3582 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3583
3584 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3585 u8 ext_capab[18];
3586 int ext_capab_len;
3587 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003588 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003589 if (ext_capab_len > 0 &&
3590 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3591 u8 *pos = wpa_ie;
3592 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3593 pos += 2 + pos[1];
3594 os_memmove(pos + ext_capab_len, pos,
3595 wpa_ie_len - (pos - wpa_ie));
3596 wpa_ie_len += ext_capab_len;
3597 os_memcpy(pos, ext_capab, ext_capab_len);
3598 }
3599 }
3600
3601#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003602 if (is_hs20_network(wpa_s, ssid, bss)
3603#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3604 && is_hs20_config(wpa_s)
3605#endif /* ANDROID */
3606 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003607 struct wpabuf *hs20;
3608
Roshan Pius3a1667e2018-07-03 15:17:14 -07003609 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003610 if (hs20) {
3611 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3612 size_t len;
3613
Hai Shalom74f70d42019-02-11 14:42:39 -08003614 wpas_hs20_add_indication(hs20, pps_mo_id,
3615 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003616 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003617 len = max_wpa_ie_len - wpa_ie_len;
3618 if (wpabuf_len(hs20) <= len) {
3619 os_memcpy(wpa_ie + wpa_ie_len,
3620 wpabuf_head(hs20), wpabuf_len(hs20));
3621 wpa_ie_len += wpabuf_len(hs20);
3622 }
3623 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003624 }
3625 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003626 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003627#endif /* CONFIG_HS20 */
3628
3629 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3630 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3631 size_t len;
3632
3633 len = max_wpa_ie_len - wpa_ie_len;
3634 if (wpabuf_len(buf) <= len) {
3635 os_memcpy(wpa_ie + wpa_ie_len,
3636 wpabuf_head(buf), wpabuf_len(buf));
3637 wpa_ie_len += wpabuf_len(buf);
3638 }
3639 }
3640
3641#ifdef CONFIG_FST
3642 if (wpa_s->fst_ies) {
3643 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3644
3645 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3646 os_memcpy(wpa_ie + wpa_ie_len,
3647 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3648 wpa_ie_len += fst_ies_len;
3649 }
3650 }
3651#endif /* CONFIG_FST */
3652
3653#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003654 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003655 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003656 int len;
3657
3658 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003659 max_wpa_ie_len - wpa_ie_len,
3660 !!mbo_attr_from_mbo_ie(mbo_ie,
3661 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003662 if (len >= 0)
3663 wpa_ie_len += len;
3664 }
3665#endif /* CONFIG_MBO */
3666
3667#ifdef CONFIG_FILS
3668 if (algs == WPA_AUTH_ALG_FILS) {
3669 size_t len;
3670
3671 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3672 max_wpa_ie_len - wpa_ie_len);
3673 wpa_ie_len += len;
3674 }
3675#endif /* CONFIG_FILS */
3676
3677#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003678#ifdef CONFIG_TESTING_OPTIONS
3679 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3680 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3681 } else
3682#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003683 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003684 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3685 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003686 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003687 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003688
Roshan Pius3a1667e2018-07-03 15:17:14 -07003689 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003690 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003691 } else if (wpa_s->assoc_status_code ==
3692 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003693 if (wpa_s->last_owe_group == 19)
3694 group = 20;
3695 else if (wpa_s->last_owe_group == 20)
3696 group = 21;
3697 else
3698 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003699 } else {
3700 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003701 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003702
Roshan Pius3a1667e2018-07-03 15:17:14 -07003703 wpa_s->last_owe_group = group;
3704 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003705 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3706 if (owe_ie &&
3707 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3708 os_memcpy(wpa_ie + wpa_ie_len,
3709 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3710 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003711 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003712 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003713 }
3714#endif /* CONFIG_OWE */
3715
Hai Shalom021b0b52019-04-10 11:17:58 -07003716#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003717 if (DPP_VERSION > 1 &&
3718 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003719 ssid->dpp_netaccesskey &&
3720 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003721 struct rsn_pmksa_cache_entry *pmksa;
3722
3723 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3724 if (!pmksa || !pmksa->dpp_pfs)
3725 goto pfs_fail;
3726
Hai Shalom021b0b52019-04-10 11:17:58 -07003727 dpp_pfs_free(wpa_s->dpp_pfs);
3728 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3729 ssid->dpp_netaccesskey_len);
3730 if (!wpa_s->dpp_pfs) {
3731 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3732 /* Try to continue without PFS */
3733 goto pfs_fail;
3734 }
3735 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3736 max_wpa_ie_len - wpa_ie_len) {
3737 os_memcpy(wpa_ie + wpa_ie_len,
3738 wpabuf_head(wpa_s->dpp_pfs->ie),
3739 wpabuf_len(wpa_s->dpp_pfs->ie));
3740 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3741 }
3742 }
3743pfs_fail:
3744#endif /* CONFIG_DPP2 */
3745
Roshan Pius3a1667e2018-07-03 15:17:14 -07003746#ifdef CONFIG_IEEE80211R
3747 /*
3748 * Add MDIE under these conditions: the network profile allows FT,
3749 * the AP supports FT, and the mobility domain ID matches.
3750 */
3751 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3752 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3753
3754 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3755 size_t len = 0;
3756 const u8 *md = mdie + 2;
3757 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3758
3759 if (os_memcmp(md, wpa_md,
3760 MOBILITY_DOMAIN_ID_LEN) == 0) {
3761 /* Add mobility domain IE */
3762 len = wpa_ft_add_mdie(
3763 wpa_s->wpa, wpa_ie + wpa_ie_len,
3764 max_wpa_ie_len - wpa_ie_len, mdie);
3765 wpa_ie_len += len;
3766 }
3767#ifdef CONFIG_SME
3768 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003769 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003770 wpa_dbg(wpa_s, MSG_DEBUG,
3771 "SME: Trying to use FT over-the-air");
3772 algs |= WPA_AUTH_ALG_FT;
3773 }
3774#endif /* CONFIG_SME */
3775 }
3776 }
3777#endif /* CONFIG_IEEE80211R */
3778
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003779#ifdef CONFIG_TESTING_OPTIONS
3780 if (wpa_s->rsnxe_override_assoc &&
3781 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3782 max_wpa_ie_len - wpa_ie_len) {
3783 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3784 os_memcpy(wpa_ie + wpa_ie_len,
3785 wpabuf_head(wpa_s->rsnxe_override_assoc),
3786 wpabuf_len(wpa_s->rsnxe_override_assoc));
3787 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3788 } else
3789#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003790 if (wpa_s->rsnxe_len > 0 &&
3791 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3792 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3793 wpa_ie_len += wpa_s->rsnxe_len;
3794 }
3795
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003796#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003797#ifdef CONFIG_TESTING_OPTIONS
3798 if (wpa_s->disable_mscs_support)
3799 goto mscs_end;
3800#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003801 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3802 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003803 struct wpabuf *mscs_ie;
3804 size_t mscs_ie_len, buf_len;
3805
Hai Shalom899fcc72020-10-19 14:38:18 -07003806 buf_len = 3 + /* MSCS descriptor IE header */
3807 1 + /* Request type */
3808 2 + /* User priority control */
3809 4 + /* Stream timeout */
3810 3 + /* TCLAS Mask IE header */
3811 wpa_s->robust_av.frame_classifier_len;
3812 mscs_ie = wpabuf_alloc(buf_len);
3813 if (!mscs_ie) {
3814 wpa_printf(MSG_INFO,
3815 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003816 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003817 }
3818
3819 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3820 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3821 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3822 mscs_ie_len = wpabuf_len(mscs_ie);
3823 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3824 mscs_ie_len);
3825 wpa_ie_len += mscs_ie_len;
3826 }
3827
3828 wpabuf_free(mscs_ie);
3829 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003830mscs_end:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003831#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003832
3833 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3834 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003835
Hai Shalom74f70d42019-02-11 14:42:39 -08003836 if (ssid->multi_ap_backhaul_sta) {
3837 size_t multi_ap_ie_len;
Sunil Ravi99c035e2024-07-12 01:42:03 +00003838 struct multi_ap_params multi_ap = { 0 };
3839
3840 multi_ap.capability = MULTI_AP_BACKHAUL_STA;
3841 multi_ap.profile = ssid->multi_ap_profile;
Hai Shalom74f70d42019-02-11 14:42:39 -08003842
3843 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3844 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi99c035e2024-07-12 01:42:03 +00003845 &multi_ap);
Hai Shalom74f70d42019-02-11 14:42:39 -08003846 if (multi_ap_ie_len == 0) {
3847 wpa_printf(MSG_ERROR,
3848 "Multi-AP: Failed to build Multi-AP IE");
3849 os_free(wpa_ie);
3850 return NULL;
3851 }
3852 wpa_ie_len += multi_ap_ie_len;
3853 }
3854
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003855 params->wpa_ie = wpa_ie;
3856 params->wpa_ie_len = wpa_ie_len;
3857 params->auth_alg = algs;
3858 if (mask)
3859 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3860
3861 return wpa_ie;
3862}
3863
3864
Hai Shalomc3565922019-10-28 11:58:20 -07003865#ifdef CONFIG_OWE
3866static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3867{
3868 struct wpa_driver_associate_params params;
3869 u8 *wpa_ie;
3870
3871 os_memset(&params, 0, sizeof(params));
3872 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3873 wpa_s->current_ssid, &params, NULL);
3874 if (!wpa_ie)
3875 return;
3876
3877 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3878 os_free(wpa_ie);
3879}
3880#endif /* CONFIG_OWE */
3881
3882
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003883#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3884static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3885{
3886 struct wpa_driver_associate_params params;
3887 enum wpa_drv_update_connect_params_mask mask = 0;
3888 u8 *wpa_ie;
3889
3890 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3891 return; /* nothing to do */
3892
3893 os_memset(&params, 0, sizeof(params));
3894 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3895 wpa_s->current_ssid, &params, &mask);
3896 if (!wpa_ie)
3897 return;
3898
Hai Shalomc1a21442022-02-04 13:43:00 -08003899 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3900 wpa_s->auth_alg = params.auth_alg;
3901 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003902 }
3903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003904 os_free(wpa_ie);
3905}
3906#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3907
3908
Hai Shalomc3565922019-10-28 11:58:20 -07003909static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3910{
3911 if (!edmg_ie || edmg_ie[1] < 6)
3912 return 0;
3913 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3914}
3915
3916
3917static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3918{
3919 if (!edmg_ie || edmg_ie[1] < 6)
3920 return 0;
3921 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3922}
3923
3924
3925/* Returns the intersection of two EDMG configurations.
3926 * Note: The current implementation is limited to CB2 only (CB1 included),
3927 * i.e., the implementation supports up to 2 contiguous channels.
3928 * For supporting non-contiguous (aggregated) channels and for supporting
3929 * CB3 and above, this function will need to be extended.
3930 */
3931static struct ieee80211_edmg_config
3932get_edmg_intersection(struct ieee80211_edmg_config a,
3933 struct ieee80211_edmg_config b,
3934 u8 primary_channel)
3935{
3936 struct ieee80211_edmg_config result;
3937 int i, contiguous = 0;
3938 int max_contiguous = 0;
3939
3940 result.channels = b.channels & a.channels;
3941 if (!result.channels) {
3942 wpa_printf(MSG_DEBUG,
3943 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3944 a.channels, b.channels);
3945 goto fail;
3946 }
3947
3948 if (!(result.channels & BIT(primary_channel - 1))) {
3949 wpa_printf(MSG_DEBUG,
3950 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3951 primary_channel, result.channels);
3952 goto fail;
3953 }
3954
3955 /* Find max contiguous channels */
3956 for (i = 0; i < 6; i++) {
3957 if (result.channels & BIT(i))
3958 contiguous++;
3959 else
3960 contiguous = 0;
3961
3962 if (contiguous > max_contiguous)
3963 max_contiguous = contiguous;
3964 }
3965
3966 /* Assuming AP and STA supports ONLY contiguous channels,
3967 * bw configuration can have value between 4-7.
3968 */
3969 if ((b.bw_config < a.bw_config))
3970 result.bw_config = b.bw_config;
3971 else
3972 result.bw_config = a.bw_config;
3973
3974 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3975 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3976 wpa_printf(MSG_DEBUG,
3977 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3978 max_contiguous);
3979 goto fail;
3980 }
3981
3982 return result;
3983
3984fail:
3985 result.channels = 0;
3986 result.bw_config = 0;
3987 return result;
3988}
3989
3990
3991static struct ieee80211_edmg_config
3992get_supported_edmg(struct wpa_supplicant *wpa_s,
3993 struct hostapd_freq_params *freq,
3994 struct ieee80211_edmg_config request_edmg)
3995{
3996 enum hostapd_hw_mode hw_mode;
3997 struct hostapd_hw_modes *mode = NULL;
3998 u8 primary_channel;
3999
4000 if (!wpa_s->hw.modes)
4001 goto fail;
4002
4003 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
4004 if (hw_mode == NUM_HOSTAPD_MODES)
4005 goto fail;
4006
Hai Shalom60840252021-02-19 19:02:11 -08004007 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004008 if (!mode)
4009 goto fail;
4010
4011 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
4012
4013fail:
4014 request_edmg.channels = 0;
4015 request_edmg.bw_config = 0;
4016 return request_edmg;
4017}
4018
4019
Hai Shalom021b0b52019-04-10 11:17:58 -07004020#ifdef CONFIG_MBO
4021void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
4022{
4023 struct wpa_driver_associate_params params;
4024 u8 *wpa_ie;
4025
4026 /*
4027 * Update MBO connect params only in case of change of MBO attributes
4028 * when connected, if the AP support MBO.
4029 */
4030
4031 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
4032 !wpa_s->current_bss ||
4033 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
4034 return;
4035
4036 os_memset(&params, 0, sizeof(params));
4037 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4038 wpa_s->current_ssid, &params, NULL);
4039 if (!wpa_ie)
4040 return;
4041
4042 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4043 os_free(wpa_ie);
4044}
4045#endif /* CONFIG_MBO */
4046
4047
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004048static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4049{
4050 struct wpa_connect_work *cwork = work->ctx;
4051 struct wpa_bss *bss = cwork->bss;
4052 struct wpa_ssid *ssid = cwork->ssid;
4053 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004054 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004055 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004056 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004057 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004058 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004059 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004060#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004061 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004062#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004063 int assoc_failed = 0;
4064 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004065 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004066#ifdef CONFIG_HT_OVERRIDES
4067 struct ieee80211_ht_capabilities htcaps;
4068 struct ieee80211_ht_capabilities htcaps_mask;
4069#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004070#ifdef CONFIG_VHT_OVERRIDES
4071 struct ieee80211_vht_capabilities vhtcaps;
4072 struct ieee80211_vht_capabilities vhtcaps_mask;
4073#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004074
Hai Shalomc1a21442022-02-04 13:43:00 -08004075 wpa_s->roam_in_progress = false;
4076#ifdef CONFIG_WNM
4077 wpa_s->bss_trans_mgmt_in_progress = false;
4078#endif /* CONFIG_WNM */
4079
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004080 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004081 if (work->started) {
4082 wpa_s->connect_work = NULL;
4083
4084 /* cancel possible auth. timeout */
4085 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4086 NULL);
4087 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004088 wpas_connect_work_free(cwork);
4089 return;
4090 }
4091
4092 wpa_s->connect_work = work;
4093
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004094 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4095 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004096 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4097 wpas_connect_work_done(wpa_s);
4098 return;
4099 }
4100
Sunil Ravi640215c2023-06-28 23:08:09 +00004101 /*
4102 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4103 * (for MLO connection) as the previous BSSID for reassociation requests
4104 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4105 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4106 * will be zero.
4107 */
4108 os_memcpy(prev_bssid,
4109 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4110 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111 os_memset(&params, 0, sizeof(params));
4112 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004113 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004114
4115 /* Starting new association, so clear the possibly used WPA IE from the
4116 * previous association. */
4117 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4118 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4119 wpa_s->rsnxe_len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004120#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom60840252021-02-19 19:02:11 -08004121 wpa_s->mscs_setup_done = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004122#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08004123
4124 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4125 if (!wpa_ie) {
4126 wpas_connect_work_done(wpa_s);
4127 return;
4128 }
4129
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004130 if (bss &&
4131 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132#ifdef CONFIG_IEEE80211R
4133 const u8 *ie, *md = NULL;
4134#endif /* CONFIG_IEEE80211R */
4135 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4136 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4137 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4138 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4139 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4140 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4141 if (bssid_changed)
4142 wpas_notify_bssid_changed(wpa_s);
4143#ifdef CONFIG_IEEE80211R
4144 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4145 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4146 md = ie + 2;
4147 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4148 if (md) {
4149 /* Prepare for the next transition */
4150 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4151 }
4152#endif /* CONFIG_IEEE80211R */
4153#ifdef CONFIG_WPS
4154 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4155 wpa_s->conf->ap_scan == 2 &&
4156 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4157 /* Use ap_scan==1 style network selection to find the network
4158 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004159 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004160 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 wpa_s->reassociate = 1;
4162 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004163 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 return;
4165#endif /* CONFIG_WPS */
4166 } else {
4167 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4168 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004169 if (bss)
4170 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4171 else
4172 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004174 if (!wpa_s->pno)
4175 wpa_supplicant_cancel_sched_scan(wpa_s);
4176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004177 wpa_supplicant_cancel_scan(wpa_s);
4178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4180 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004181 cipher_pairwise = wpa_s->pairwise_cipher;
4182 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004183 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004184 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4185 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4186 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4187 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004188#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189 if (wpa_set_wep_keys(wpa_s, ssid)) {
4190 use_crypt = 1;
4191 wep_keys_set = 1;
4192 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004193#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 }
4195 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4196 use_crypt = 0;
4197
4198#ifdef IEEE8021X_EAPOL
4199 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4200 if ((ssid->eapol_flags &
4201 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4202 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4203 !wep_keys_set) {
4204 use_crypt = 0;
4205 } else {
4206 /* Assume that dynamic WEP-104 keys will be used and
4207 * set cipher suites in order for drivers to expect
4208 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004209 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210 }
4211 }
4212#endif /* IEEE8021X_EAPOL */
4213
4214 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4215 /* Set the key before (and later after) association */
4216 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4217 }
4218
Sunil8cd6f4d2022-06-28 18:40:46 +00004219 /* Set current_ssid before changing state to ASSOCIATING, so that the
4220 * selected SSID is available to wpas_notify_state_changed(). */
4221 old_ssid = wpa_s->current_ssid;
4222 wpa_s->current_ssid = ssid;
4223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004224 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4225 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004226 params.ssid = bss->ssid;
4227 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004228 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4229 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004230 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4231 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004232 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004233 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004234 ssid->bssid_set,
4235 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004236 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004237 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004238 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004239 params.bssid_hint = bss->bssid;
4240 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004241 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004242 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004243 if (ssid->bssid_hint_set)
4244 params.bssid_hint = ssid->bssid_hint;
4245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004246 params.ssid = ssid->ssid;
4247 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004248 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004249 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004250
4251 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4252 wpa_s->conf->ap_scan == 2) {
4253 params.bssid = ssid->bssid;
4254 params.fixed_bssid = 1;
4255 }
4256
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004257 /* Initial frequency for IBSS/mesh */
4258 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004259 ssid->frequency > 0 && params.freq.freq == 0)
4260 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004261
4262 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004263 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004264 if (ssid->beacon_int)
4265 params.beacon_int = ssid->beacon_int;
4266 else
4267 params.beacon_int = wpa_s->conf->beacon_int;
4268 }
4269
Hai Shalomc3565922019-10-28 11:58:20 -07004270 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004271 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4272 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004273 else
4274 edmg_ie_oper = NULL;
4275
4276 if (edmg_ie_oper) {
4277 params.freq.edmg.channels =
4278 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4279 params.freq.edmg.bw_config =
4280 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4281 wpa_printf(MSG_DEBUG,
4282 "AP supports EDMG channels 0x%x, bw_config %d",
4283 params.freq.edmg.channels,
4284 params.freq.edmg.bw_config);
4285
4286 /* User may ask for specific EDMG channel for EDMG connection
4287 * (must be supported by AP)
4288 */
4289 if (ssid->edmg_channel) {
4290 struct ieee80211_edmg_config configured_edmg;
4291 enum hostapd_hw_mode hw_mode;
4292 u8 primary_channel;
4293
4294 hw_mode = ieee80211_freq_to_chan(bss->freq,
4295 &primary_channel);
4296 if (hw_mode == NUM_HOSTAPD_MODES)
4297 goto edmg_fail;
4298
4299 hostapd_encode_edmg_chan(ssid->enable_edmg,
4300 ssid->edmg_channel,
4301 primary_channel,
4302 &configured_edmg);
4303
4304 if (ieee802_edmg_is_allowed(params.freq.edmg,
4305 configured_edmg)) {
4306 params.freq.edmg = configured_edmg;
4307 wpa_printf(MSG_DEBUG,
4308 "Use EDMG channel %d for connection",
4309 ssid->edmg_channel);
4310 } else {
4311 edmg_fail:
4312 params.freq.edmg.channels = 0;
4313 params.freq.edmg.bw_config = 0;
4314 wpa_printf(MSG_WARNING,
4315 "EDMG channel %d not supported by AP, fallback to DMG",
4316 ssid->edmg_channel);
4317 }
4318 }
4319
4320 if (params.freq.edmg.channels) {
4321 wpa_printf(MSG_DEBUG,
4322 "EDMG before: channels 0x%x, bw_config %d",
4323 params.freq.edmg.channels,
4324 params.freq.edmg.bw_config);
4325 params.freq.edmg = get_supported_edmg(wpa_s,
4326 &params.freq,
4327 params.freq.edmg);
4328 wpa_printf(MSG_DEBUG,
4329 "EDMG after: channels 0x%x, bw_config %d",
4330 params.freq.edmg.channels,
4331 params.freq.edmg.bw_config);
4332 }
4333 }
4334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004335 params.pairwise_suite = cipher_pairwise;
4336 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004337 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004338 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004339 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004340 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004341 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004342 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004343 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004344#ifdef CONFIG_WEP
4345 {
4346 int i;
4347
4348 for (i = 0; i < NUM_WEP_KEYS; i++) {
4349 if (ssid->wep_key_len[i])
4350 params.wep_key[i] = ssid->wep_key[i];
4351 params.wep_key_len[i] = ssid->wep_key_len[i];
4352 }
4353 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004355#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356
Hai Shalom74f70d42019-02-11 14:42:39 -08004357 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004358#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4359 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004360 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4361 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004362#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4363 defined(CONFIG_DRIVER_NL80211_SYNA)
4364 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4365 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4366 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4367 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304368#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004369 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4370 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4371 (params.allowed_key_mgmts &
4372 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004373#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4374 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004376 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4377 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378 }
4379
Hai Shalom74f70d42019-02-11 14:42:39 -08004380 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4381 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4382 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4383 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004384 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4385 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004386 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004387
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004388 if (wpa_s->conf->key_mgmt_offload) {
4389 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4390 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004391 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004392 params.key_mgmt_suite ==
4393 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4394 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004395 params.req_key_mgmt_offload =
4396 ssid->proactive_key_caching < 0 ?
4397 wpa_s->conf->okc : ssid->proactive_key_caching;
4398 else
4399 params.req_key_mgmt_offload = 1;
4400
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004401#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4402 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004403 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004404 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4405 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004406#else
4407 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4408 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004409#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4410 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004411 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4412 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004413 }
4414
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004415 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4416 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4417 params.auth_alg = WPA_AUTH_ALG_SAE;
4418 if (ssid->sae_password) {
4419 params.sae_password = ssid->sae_password;
4420 params.sae_password_id = ssid->sae_password_id;
4421 } else if (ssid->passphrase) {
4422 params.passphrase = ssid->passphrase;
4423 }
4424 }
4425
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004426 params.drop_unencrypted = use_crypt;
4427
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004428 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004429 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004430 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4431 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004432 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4433 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004434 ie.capabilities &
4435 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4436 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4437 "MFP: require MFP");
4438 params.mgmt_frame_protection =
4439 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004440#ifdef CONFIG_OWE
4441 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4442 !ssid->owe_only) {
4443 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4444#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004445 }
4446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004447
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004448 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004449
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004450 if (wpa_s->p2pdev->set_sta_uapsd)
4451 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 else
4453 params.uapsd = -1;
4454
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004455#ifdef CONFIG_HT_OVERRIDES
4456 os_memset(&htcaps, 0, sizeof(htcaps));
4457 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4458 params.htcaps = (u8 *) &htcaps;
4459 params.htcaps_mask = (u8 *) &htcaps_mask;
4460 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4461#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004462#ifdef CONFIG_VHT_OVERRIDES
4463 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4464 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4465 params.vhtcaps = &vhtcaps;
4466 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004467 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004468#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004469#ifdef CONFIG_HE_OVERRIDES
4470 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4471#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004472 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004473
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004474#ifdef CONFIG_P2P
4475 /*
4476 * If multi-channel concurrency is not supported, check for any
4477 * frequency conflict. In case of any frequency conflict, remove the
4478 * least prioritized connection.
4479 */
4480 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004481 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004482 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004483 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004484 wpa_printf(MSG_DEBUG,
4485 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004486 freq, params.freq.freq);
4487 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004488 wpa_s, params.freq.freq, ssid) < 0) {
4489 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004490 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004491 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004492 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004493 }
4494 }
4495#endif /* CONFIG_P2P */
4496
Dmitry Shmidte4663042016-04-04 10:07:49 -07004497 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004498 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004499 params.prev_bssid = prev_bssid;
4500
Hai Shalom60840252021-02-19 19:02:11 -08004501#ifdef CONFIG_SAE
4502 params.sae_pwe = wpa_s->conf->sae_pwe;
4503#endif /* CONFIG_SAE */
4504
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004505 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004506 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004507 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508 if (ret < 0) {
4509 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4510 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004511 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004512 /*
4513 * The driver is known to mean what is saying, so we
4514 * can stop right here; the association will not
4515 * succeed.
4516 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004517 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
4518 NULL);
Roger Wang4c09cc92020-11-05 18:57:12 +08004519 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004520 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004521 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4523 return;
4524 }
4525 /* try to continue anyway; new association will be tried again
4526 * after timeout */
4527 assoc_failed = 1;
4528 }
4529
4530 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4531 /* Set the key after the association just in case association
4532 * cleared the previously configured key. */
4533 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4534 /* No need to timeout authentication since there is no key
4535 * management. */
4536 wpa_supplicant_cancel_auth_timeout(wpa_s);
4537 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4538#ifdef CONFIG_IBSS_RSN
4539 } else if (ssid->mode == WPAS_MODE_IBSS &&
4540 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4541 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4542 /*
4543 * RSN IBSS authentication is per-STA and we can disable the
4544 * per-BSSID authentication.
4545 */
4546 wpa_supplicant_cancel_auth_timeout(wpa_s);
4547#endif /* CONFIG_IBSS_RSN */
4548 } else {
4549 /* Timeout for IEEE 802.11 authentication and association */
4550 int timeout = 60;
4551
4552 if (assoc_failed) {
4553 /* give IBSS a bit more time */
4554 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4555 } else if (wpa_s->conf->ap_scan == 1) {
4556 /* give IBSS a bit more time */
4557 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4558 }
4559 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4560 }
4561
Hai Shalomfdcde762020-04-02 11:19:20 -07004562#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004563 if (wep_keys_set &&
4564 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004565 /* Set static WEP keys again */
4566 wpa_set_wep_keys(wpa_s, ssid);
4567 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004568#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004569
Sunil8cd6f4d2022-06-28 18:40:46 +00004570 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004571 /*
4572 * Do not allow EAP session resumption between different
4573 * network configurations.
4574 */
4575 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4576 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004577
mtk30479d7f89782024-01-24 11:51:43 +08004578 if (!wpas_driver_bss_selection(wpa_s) ||
4579#ifdef CONFIG_P2P
4580 wpa_s->p2p_in_invitation ||
4581#endif /* CONFIG_P2P */
4582 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004583 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004584#ifdef CONFIG_HS20
4585 hs20_configure_frame_filters(wpa_s);
4586#endif /* CONFIG_HS20 */
4587 }
4588
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004589 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4590 wpa_supplicant_initiate_eapol(wpa_s);
4591 if (old_ssid != wpa_s->current_ssid)
4592 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004593 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4594 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004595}
4596
4597
4598static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4599 const u8 *addr)
4600{
4601 struct wpa_ssid *old_ssid;
4602
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004603 wpa_s->ml_connect_probe_ssid = NULL;
4604 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004605 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004608 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004609 wpa_sm_set_config(wpa_s->wpa, NULL);
4610 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4611 if (old_ssid != wpa_s->current_ssid)
4612 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004613
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004614#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08004615 wpas_scs_deinit(wpa_s);
4616 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004617#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004618 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4619}
4620
4621
4622/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004623 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4624 * @wpa_s: Pointer to wpa_supplicant data
4625 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4626 *
4627 * This function is used to request %wpa_supplicant to deauthenticate from the
4628 * current AP.
4629 */
4630void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004631 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632{
4633 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004634 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004635 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004636
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004637 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004638 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004639 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004640 reason_code, reason2str(reason_code),
4641 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004642
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004643 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4644 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4645 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004646 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004647 else if (!is_zero_ether_addr(wpa_s->bssid))
4648 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004649 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4650 /*
4651 * When using driver-based BSS selection, we may not know the
4652 * BSSID with which we are currently trying to associate. We
4653 * need to notify the driver of this disconnection even in such
4654 * a case, so use the all zeros address here.
4655 */
4656 addr = wpa_s->bssid;
4657 zero_addr = 1;
4658 }
4659
Hai Shalom74f70d42019-02-11 14:42:39 -08004660 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4661 wpa_s->enabled_4addr_mode = 0;
4662
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004663#ifdef CONFIG_TDLS
4664 wpa_tdls_teardown_peers(wpa_s->wpa);
4665#endif /* CONFIG_TDLS */
4666
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004667#ifdef CONFIG_MESH
4668 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004669 struct mesh_conf *mconf;
4670
4671 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004672 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4673 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004674 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4675 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004676 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004677 }
4678#endif /* CONFIG_MESH */
4679
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004680 if (addr) {
4681 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004682 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004683 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004684 event.deauth_info.locally_generated = 1;
4685 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004686 if (zero_addr)
4687 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688 }
4689
4690 wpa_supplicant_clear_connection(wpa_s, addr);
4691}
4692
Hai Shalomfdcde762020-04-02 11:19:20 -07004693
4694void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4695{
4696 wpa_s->own_reconnect_req = 1;
4697 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4698
4699}
4700
4701
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004702static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4703 struct wpa_ssid *ssid)
4704{
4705 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4706 return;
4707
4708 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004709 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004710 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4711 wpas_notify_network_enabled_changed(wpa_s, ssid);
4712
4713 /*
4714 * Try to reassociate since there is no current configuration and a new
4715 * network was made available.
4716 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004717 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004718 wpa_s->reassociate = 1;
4719}
4720
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004721
Roshan Pius950bec92016-07-19 09:49:24 -07004722/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004723 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004724 * @wpa_s: wpa_supplicant structure for a network interface
4725 * Returns: The new network configuration or %NULL if operation failed
4726 *
4727 * This function performs the following operations:
4728 * 1. Adds a new network.
4729 * 2. Send network addition notification.
4730 * 3. Marks the network disabled.
4731 * 4. Set network default parameters.
4732 */
4733struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4734{
4735 struct wpa_ssid *ssid;
4736
4737 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004738 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004739 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004740 wpas_notify_network_added(wpa_s, ssid);
4741 ssid->disabled = 1;
4742 wpa_config_set_network_defaults(ssid);
4743
4744 return ssid;
4745}
4746
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004747
Roshan Pius950bec92016-07-19 09:49:24 -07004748/**
4749 * wpa_supplicant_remove_network - Remove a configured network based on id
4750 * @wpa_s: wpa_supplicant structure for a network interface
4751 * @id: Unique network id to search for
4752 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4753 * could not be removed
4754 *
4755 * This function performs the following operations:
4756 * 1. Removes the network.
4757 * 2. Send network removal notification.
4758 * 3. Update internal state machines.
4759 * 4. Stop any running sched scans.
4760 */
4761int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4762{
Sunil Ravia04bd252022-05-02 22:54:18 -07004763 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004764 int was_disabled;
4765
4766 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004767 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004768 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004769 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004770
Sunil Ravia04bd252022-05-02 22:54:18 -07004771 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004772#ifdef CONFIG_SME
4773 wpa_s->sme.prev_bssid_set = 0;
4774#endif /* CONFIG_SME */
4775 /*
4776 * Invalidate the EAP session cache if the current or
4777 * previously used network is removed.
4778 */
4779 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4780 }
4781
Sunil Ravia04bd252022-05-02 22:54:18 -07004782 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004783 wpa_sm_set_config(wpa_s->wpa, NULL);
4784 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4785
4786 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4787 wpa_s->own_disconnect_req = 1;
4788 wpa_supplicant_deauthenticate(wpa_s,
4789 WLAN_REASON_DEAUTH_LEAVING);
4790 }
4791
4792 was_disabled = ssid->disabled;
4793
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004794 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004795 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004796
4797 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004798 wpa_printf(MSG_DEBUG,
4799 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004800 wpa_supplicant_cancel_sched_scan(wpa_s);
4801 wpa_supplicant_req_scan(wpa_s, 0, 0);
4802 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004803
Roshan Pius950bec92016-07-19 09:49:24 -07004804 return 0;
4805}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004808/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004809 * wpa_supplicant_remove_all_networks - Remove all configured networks
4810 * @wpa_s: wpa_supplicant structure for a network interface
4811 * Returns: 0 on success (errors are currently ignored)
4812 *
4813 * This function performs the following operations:
4814 * 1. Remove all networks.
4815 * 2. Send network removal notifications.
4816 * 3. Update internal state machines.
4817 * 4. Stop any running sched scans.
4818 */
4819int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4820{
4821 struct wpa_ssid *ssid;
4822
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304823 if (wpa_s->drv_flags2 &
4824 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4825 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4826 wpa_drv_flush_pmkid(wpa_s);
4827
Hai Shalom899fcc72020-10-19 14:38:18 -07004828 if (wpa_s->sched_scanning)
4829 wpa_supplicant_cancel_sched_scan(wpa_s);
4830
4831 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4832 if (wpa_s->current_ssid) {
4833#ifdef CONFIG_SME
4834 wpa_s->sme.prev_bssid_set = 0;
4835#endif /* CONFIG_SME */
4836 wpa_sm_set_config(wpa_s->wpa, NULL);
4837 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4838 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4839 wpa_s->own_disconnect_req = 1;
4840 wpa_supplicant_deauthenticate(
4841 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4842 }
4843 ssid = wpa_s->conf->ssid;
4844 while (ssid) {
4845 struct wpa_ssid *remove_ssid = ssid;
4846 int id;
4847
4848 id = ssid->id;
4849 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004850 wpas_notify_network_removed(wpa_s, remove_ssid);
4851 wpa_config_remove_network(wpa_s->conf, id);
4852 }
4853 return 0;
4854}
4855
4856
4857/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004858 * wpa_supplicant_enable_network - Mark a configured network as enabled
4859 * @wpa_s: wpa_supplicant structure for a network interface
4860 * @ssid: wpa_ssid structure for a configured network or %NULL
4861 *
4862 * Enables the specified network or all networks if no network specified.
4863 */
4864void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4865 struct wpa_ssid *ssid)
4866{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004867 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004868 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4869 wpa_supplicant_enable_one_network(wpa_s, ssid);
4870 } else
4871 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004872
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004873 if (wpa_s->reassociate && !wpa_s->disconnected &&
4874 (!wpa_s->current_ssid ||
4875 wpa_s->wpa_state == WPA_DISCONNECTED ||
4876 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004877 if (wpa_s->sched_scanning) {
4878 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4879 "new network to scan filters");
4880 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004881 }
4882
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004883 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4884 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004885 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004886 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004887 }
4888}
4889
4890
4891/**
4892 * wpa_supplicant_disable_network - Mark a configured network as disabled
4893 * @wpa_s: wpa_supplicant structure for a network interface
4894 * @ssid: wpa_ssid structure for a configured network or %NULL
4895 *
4896 * Disables the specified network or all networks if no network specified.
4897 */
4898void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4899 struct wpa_ssid *ssid)
4900{
4901 struct wpa_ssid *other_ssid;
4902 int was_disabled;
4903
4904 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004905 if (wpa_s->sched_scanning)
4906 wpa_supplicant_cancel_sched_scan(wpa_s);
4907
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4909 other_ssid = other_ssid->next) {
4910 was_disabled = other_ssid->disabled;
4911 if (was_disabled == 2)
4912 continue; /* do not change persistent P2P group
4913 * data */
4914
4915 other_ssid->disabled = 1;
4916
4917 if (was_disabled != other_ssid->disabled)
4918 wpas_notify_network_enabled_changed(
4919 wpa_s, other_ssid);
4920 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004921 if (wpa_s->current_ssid) {
4922 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4923 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004924 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004926 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004927 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004928 if (ssid == wpa_s->current_ssid) {
4929 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4930 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004931 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004932 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004933 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004934
4935 was_disabled = ssid->disabled;
4936
4937 ssid->disabled = 1;
4938
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004939 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004940 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004941 if (wpa_s->sched_scanning) {
4942 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4943 "to remove network from filters");
4944 wpa_supplicant_cancel_sched_scan(wpa_s);
4945 wpa_supplicant_req_scan(wpa_s, 0, 0);
4946 }
4947 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004948 }
4949}
4950
4951
4952/**
4953 * wpa_supplicant_select_network - Attempt association with a network
4954 * @wpa_s: wpa_supplicant structure for a network interface
4955 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4956 */
4957void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4958 struct wpa_ssid *ssid)
4959{
4960
4961 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004962 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004963
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004964 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004965 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4966 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004967 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004968 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004969 disconnected = 1;
4970 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004971
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004972 if (ssid)
4973 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004975 /*
4976 * Mark all other networks disabled or mark all networks enabled if no
4977 * network specified.
4978 */
4979 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4980 other_ssid = other_ssid->next) {
4981 int was_disabled = other_ssid->disabled;
4982 if (was_disabled == 2)
4983 continue; /* do not change persistent P2P group data */
4984
4985 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004986 if (was_disabled && !other_ssid->disabled)
4987 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004988
4989 if (was_disabled != other_ssid->disabled)
4990 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4991 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004992
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004993 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4994 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004995 /* We are already associated with the selected network */
4996 wpa_printf(MSG_DEBUG, "Already associated with the "
4997 "selected network - do nothing");
4998 return;
4999 }
5000
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005001 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005002 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005003 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005004 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00005005 (ssid->mode == WPAS_MODE_MESH ||
5006 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005007
5008 /*
5009 * Don't optimize next scan freqs since a new ESS has been
5010 * selected.
5011 */
5012 os_free(wpa_s->next_scan_freqs);
5013 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005014 } else {
5015 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005016 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005017
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005018 wpa_s->disconnected = 0;
5019 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005020 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005021 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005022 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005023 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07005024 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07005025 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005026
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005027 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005028 wpa_supplicant_fast_associate(wpa_s) != 1) {
5029 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005030 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005031 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005032 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005033
5034 if (ssid)
5035 wpas_notify_network_selected(wpa_s, ssid);
5036}
5037
5038
5039/**
Hai Shalomc1a21442022-02-04 13:43:00 -08005040 * wpas_remove_cred - Remove the specified credential and all the network
5041 * entries created based on the removed credential
5042 * @wpa_s: wpa_supplicant structure for a network interface
5043 * @cred: The credential to remove
5044 * Returns: 0 on success, -1 on failure
5045 */
5046int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
5047{
5048 struct wpa_ssid *ssid, *next;
5049 int id;
5050
5051 if (!cred) {
5052 wpa_printf(MSG_DEBUG, "Could not find cred");
5053 return -1;
5054 }
5055
5056 id = cred->id;
5057 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5058 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5059 return -1;
5060 }
5061
5062 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5063
5064 /* Remove any network entry created based on the removed credential */
5065 ssid = wpa_s->conf->ssid;
5066 while (ssid) {
5067 next = ssid->next;
5068
5069 if (ssid->parent_cred == cred) {
5070 wpa_printf(MSG_DEBUG,
5071 "Remove network id %d since it used the removed credential",
5072 ssid->id);
5073 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5074 -1) {
5075 wpa_printf(MSG_DEBUG,
5076 "Could not find network id=%d",
5077 ssid->id);
5078 }
5079 }
5080
5081 ssid = next;
5082 }
5083
5084 return 0;
5085}
5086
5087
5088/**
5089 * wpas_remove_cred - Remove all the Interworking credentials
5090 * @wpa_s: wpa_supplicant structure for a network interface
5091 * Returns: 0 on success, -1 on failure
5092 */
5093int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5094{
5095 int res, ret = 0;
5096 struct wpa_cred *cred, *prev;
5097
5098 cred = wpa_s->conf->cred;
5099 while (cred) {
5100 prev = cred;
5101 cred = cred->next;
5102 res = wpas_remove_cred(wpa_s, prev);
5103 if (res < 0) {
5104 wpa_printf(MSG_DEBUG,
5105 "Removal of all credentials failed - failed to remove credential id=%d",
5106 prev->id);
5107 ret = -1;
5108 }
5109 }
5110
5111 return ret;
5112}
5113
5114
5115/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005116 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5117 * @wpa_s: wpa_supplicant structure for a network interface
5118 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5119 * @pkcs11_module_path: PKCS #11 module path or NULL
5120 * Returns: 0 on success; -1 on failure
5121 *
5122 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5123 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5124 * module path fails the paths will be reset to the default value (NULL).
5125 */
5126int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5127 const char *pkcs11_engine_path,
5128 const char *pkcs11_module_path)
5129{
5130 char *pkcs11_engine_path_copy = NULL;
5131 char *pkcs11_module_path_copy = NULL;
5132
5133 if (pkcs11_engine_path != NULL) {
5134 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5135 if (pkcs11_engine_path_copy == NULL)
5136 return -1;
5137 }
5138 if (pkcs11_module_path != NULL) {
5139 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005140 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005141 os_free(pkcs11_engine_path_copy);
5142 return -1;
5143 }
5144 }
5145
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005146#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005147 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005148 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005149#endif /* CONFIG_PKCS11_ENGINE_PATH */
5150#ifndef CONFIG_PKCS11_MODULE_PATH
5151 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005152 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005153#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005154
5155 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5156 eapol_sm_deinit(wpa_s->eapol);
5157 wpa_s->eapol = NULL;
5158 if (wpa_supplicant_init_eapol(wpa_s)) {
5159 /* Error -> Reset paths to the default value (NULL) once. */
5160 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5161 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5162 NULL);
5163
5164 return -1;
5165 }
5166 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5167
5168 return 0;
5169}
5170
5171
5172/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005173 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5174 * @wpa_s: wpa_supplicant structure for a network interface
5175 * @ap_scan: AP scan mode
5176 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5177 *
5178 */
5179int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5180{
5181
5182 int old_ap_scan;
5183
5184 if (ap_scan < 0 || ap_scan > 2)
5185 return -1;
5186
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005187 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5188 wpa_printf(MSG_INFO,
5189 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5190 }
5191
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005192#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005193 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5194 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5195 wpa_s->wpa_state < WPA_COMPLETED) {
5196 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5197 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005198 return 0;
5199 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005200#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202 old_ap_scan = wpa_s->conf->ap_scan;
5203 wpa_s->conf->ap_scan = ap_scan;
5204
5205 if (old_ap_scan != wpa_s->conf->ap_scan)
5206 wpas_notify_ap_scan_changed(wpa_s);
5207
5208 return 0;
5209}
5210
5211
5212/**
5213 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5214 * @wpa_s: wpa_supplicant structure for a network interface
5215 * @expire_age: Expiration age in seconds
5216 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5217 *
5218 */
5219int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5220 unsigned int bss_expire_age)
5221{
5222 if (bss_expire_age < 10) {
5223 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5224 bss_expire_age);
5225 return -1;
5226 }
5227 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5228 bss_expire_age);
5229 wpa_s->conf->bss_expiration_age = bss_expire_age;
5230
5231 return 0;
5232}
5233
5234
5235/**
5236 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5237 * @wpa_s: wpa_supplicant structure for a network interface
5238 * @expire_count: number of scans after which an unseen BSS is reclaimed
5239 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5240 *
5241 */
5242int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5243 unsigned int bss_expire_count)
5244{
5245 if (bss_expire_count < 1) {
5246 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5247 bss_expire_count);
5248 return -1;
5249 }
5250 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5251 bss_expire_count);
5252 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5253
5254 return 0;
5255}
5256
5257
5258/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005259 * wpa_supplicant_set_scan_interval - Set scan interval
5260 * @wpa_s: wpa_supplicant structure for a network interface
5261 * @scan_interval: scan interval in seconds
5262 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5263 *
5264 */
5265int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5266 int scan_interval)
5267{
5268 if (scan_interval < 0) {
5269 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5270 scan_interval);
5271 return -1;
5272 }
5273 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5274 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005275 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005276
5277 return 0;
5278}
5279
5280
5281/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005282 * wpa_supplicant_set_debug_params - Set global debug params
5283 * @global: wpa_global structure
5284 * @debug_level: debug level
5285 * @debug_timestamp: determines if show timestamp in debug data
5286 * @debug_show_keys: determines if show keys in debug data
5287 * Returns: 0 if succeed or -1 if debug_level has wrong value
5288 */
5289int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5290 int debug_timestamp, int debug_show_keys)
5291{
5292
5293 int old_level, old_timestamp, old_show_keys;
5294
5295 /* check for allowed debuglevels */
5296 if (debug_level != MSG_EXCESSIVE &&
5297 debug_level != MSG_MSGDUMP &&
5298 debug_level != MSG_DEBUG &&
5299 debug_level != MSG_INFO &&
5300 debug_level != MSG_WARNING &&
5301 debug_level != MSG_ERROR)
5302 return -1;
5303
5304 old_level = wpa_debug_level;
5305 old_timestamp = wpa_debug_timestamp;
5306 old_show_keys = wpa_debug_show_keys;
5307
5308 wpa_debug_level = debug_level;
5309 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5310 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5311
5312 if (wpa_debug_level != old_level)
5313 wpas_notify_debug_level_changed(global);
5314 if (wpa_debug_timestamp != old_timestamp)
5315 wpas_notify_debug_timestamp_changed(global);
5316 if (wpa_debug_show_keys != old_show_keys)
5317 wpas_notify_debug_show_keys_changed(global);
5318
5319 return 0;
5320}
5321
5322
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005323#ifdef CONFIG_OWE
5324static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5325 const u8 *entry_ssid, size_t entry_ssid_len)
5326{
5327 const u8 *owe, *pos, *end;
5328 u8 ssid_len;
5329 struct wpa_bss *bss;
5330
5331 /* Check network profile SSID aganst the SSID in the
5332 * OWE Transition Mode element. */
5333
5334 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5335 if (!bss)
5336 return 0;
5337
5338 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5339 if (!owe)
5340 return 0;
5341
5342 pos = owe + 6;
5343 end = owe + 2 + owe[1];
5344
5345 if (end - pos < ETH_ALEN + 1)
5346 return 0;
5347 pos += ETH_ALEN;
5348 ssid_len = *pos++;
5349 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5350 return 0;
5351
5352 return entry_ssid_len == ssid_len &&
5353 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5354}
5355#endif /* CONFIG_OWE */
5356
5357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005358/**
5359 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5360 * @wpa_s: Pointer to wpa_supplicant data
5361 * Returns: A pointer to the current network structure or %NULL on failure
5362 */
5363struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5364{
5365 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005366 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005367 int res;
5368 size_t ssid_len;
5369 u8 bssid[ETH_ALEN];
5370 int wired;
5371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005372 res = wpa_drv_get_ssid(wpa_s, ssid);
5373 if (res < 0) {
5374 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5375 "driver");
5376 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005377 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005378 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005379
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005380 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005381 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5382 "driver");
5383 return NULL;
5384 }
5385
5386 wired = wpa_s->conf->ap_scan == 0 &&
5387 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5388
5389 entry = wpa_s->conf->ssid;
5390 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005391 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005393 (!entry->ssid ||
5394 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5395 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005396 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005397 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005398 return entry;
5399#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005400 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005401 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5402 (entry->ssid == NULL || entry->ssid_len == 0) &&
5403 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005404 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005405 return entry;
5406#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005407
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005408#ifdef CONFIG_OWE
5409 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005410 (entry->ssid &&
5411 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5412 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005413 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005414 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005415 return entry;
5416#endif /* CONFIG_OWE */
5417
Dmitry Shmidt04949592012-07-19 12:16:46 -07005418 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005419 entry->ssid_len == 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005420 ether_addr_equal(bssid, entry->bssid))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005421 return entry;
5422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005423 entry = entry->next;
5424 }
5425
5426 return NULL;
5427}
5428
5429
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005430static int select_driver(struct wpa_supplicant *wpa_s, int i)
5431{
5432 struct wpa_global *global = wpa_s->global;
5433
5434 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005435 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005436 if (global->drv_priv[i] == NULL) {
5437 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5438 "'%s'", wpa_drivers[i]->name);
5439 return -1;
5440 }
5441 }
5442
5443 wpa_s->driver = wpa_drivers[i];
5444 wpa_s->global_drv_priv = global->drv_priv[i];
5445
5446 return 0;
5447}
5448
5449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005450static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5451 const char *name)
5452{
5453 int i;
5454 size_t len;
5455 const char *pos, *driver = name;
5456
5457 if (wpa_s == NULL)
5458 return -1;
5459
5460 if (wpa_drivers[0] == NULL) {
5461 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5462 "wpa_supplicant");
5463 return -1;
5464 }
5465
5466 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005467 /* Default to first successful driver in the list */
5468 for (i = 0; wpa_drivers[i]; i++) {
5469 if (select_driver(wpa_s, i) == 0)
5470 return 0;
5471 }
5472 /* Drivers have each reported failure, so no wpa_msg() here. */
5473 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005474 }
5475
5476 do {
5477 pos = os_strchr(driver, ',');
5478 if (pos)
5479 len = pos - driver;
5480 else
5481 len = os_strlen(driver);
5482
5483 for (i = 0; wpa_drivers[i]; i++) {
5484 if (os_strlen(wpa_drivers[i]->name) == len &&
5485 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005486 0) {
5487 /* First driver that succeeds wins */
5488 if (select_driver(wpa_s, i) == 0)
5489 return 0;
5490 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005491 }
5492
5493 driver = pos + 1;
5494 } while (pos);
5495
5496 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5497 return -1;
5498}
5499
5500
5501/**
5502 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5503 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5504 * with struct wpa_driver_ops::init()
5505 * @src_addr: Source address of the EAPOL frame
5506 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5507 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005508 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005509 *
5510 * This function is called for each received EAPOL frame. Most driver
5511 * interfaces rely on more generic OS mechanism for receiving frames through
5512 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5513 * take care of received EAPOL frames and deliver them to the core supplicant
5514 * code by calling this function.
5515 */
5516void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005517 const u8 *buf, size_t len,
5518 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005519{
5520 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005521 const u8 *connected_addr = wpa_s->valid_links ?
5522 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005523
Sunil8cd6f4d2022-06-28 18:40:46 +00005524 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5525 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005526 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5527
Hai Shalomc1a21442022-02-04 13:43:00 -08005528 if (wpa_s->own_disconnect_req) {
5529 wpa_printf(MSG_DEBUG,
5530 "Drop received EAPOL frame as we are disconnecting");
5531 return;
5532 }
5533
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005534#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005535 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5536 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005537 if (wpa_s->ignore_auth_resp) {
5538 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5539 return;
5540 }
5541#endif /* CONFIG_TESTING_OPTIONS */
5542
Jouni Malinena05074c2012-12-21 21:35:35 +02005543 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5544 (wpa_s->last_eapol_matches_bssid &&
5545#ifdef CONFIG_AP
5546 !wpa_s->ap_iface &&
5547#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005548 !ether_addr_equal(src_addr, connected_addr))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005549 /*
5550 * There is possible race condition between receiving the
5551 * association event and the EAPOL frame since they are coming
5552 * through different paths from the driver. In order to avoid
5553 * issues in trying to process the EAPOL frame before receiving
5554 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005555 * the association event is received. This may also be needed in
5556 * driver-based roaming case, so also use src_addr != BSSID as a
5557 * trigger if we have previously confirmed that the
5558 * Authenticator uses BSSID as the src_addr (which is not the
5559 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005560 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005561 wpa_dbg(wpa_s, MSG_DEBUG,
5562 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5563 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005564 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005565 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566 wpabuf_free(wpa_s->pending_eapol_rx);
5567 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5568 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005569 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005570 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5571 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005572 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573 }
5574 return;
5575 }
5576
Jouni Malinena05074c2012-12-21 21:35:35 +02005577 wpa_s->last_eapol_matches_bssid =
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005578 ether_addr_equal(src_addr, connected_addr);
Jouni Malinena05074c2012-12-21 21:35:35 +02005579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005580#ifdef CONFIG_AP
5581 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005582 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5583 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005584 return;
5585 }
5586#endif /* CONFIG_AP */
5587
5588 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5589 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5590 "no key management is configured");
5591 return;
5592 }
5593
5594 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005595 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005596 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5597 wpa_s->wpa_state != WPA_COMPLETED) &&
5598 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005599 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005600 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005601 int timeout = 10;
5602
5603 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5604 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5605 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5606 /* Use longer timeout for IEEE 802.1X/EAP */
5607 timeout = 70;
5608 }
5609
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005610#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005611 if (wpa_s->current_ssid && wpa_s->current_bss &&
5612 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5613 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5614 /*
5615 * Use shorter timeout if going through WPS AP iteration
5616 * for PIN config method with an AP that does not
5617 * advertise Selected Registrar.
5618 */
5619 struct wpabuf *wps_ie;
5620
5621 wps_ie = wpa_bss_get_vendor_ie_multi(
5622 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5623 if (wps_ie &&
5624 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5625 timeout = 10;
5626 wpabuf_free(wps_ie);
5627 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005628#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005629
5630 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005631 }
5632 wpa_s->eapol_received++;
5633
5634 if (wpa_s->countermeasures) {
5635 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5636 "EAPOL packet");
5637 return;
5638 }
5639
5640#ifdef CONFIG_IBSS_RSN
5641 if (wpa_s->current_ssid &&
5642 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005643 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5644 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645 return;
5646 }
5647#endif /* CONFIG_IBSS_RSN */
5648
5649 /* Source address of the incoming EAPOL frame could be compared to the
5650 * current BSSID. However, it is possible that a centralized
5651 * Authenticator could be using another MAC address than the BSSID of
5652 * an AP, so just allow any address to be used for now. The replies are
5653 * still sent to the current BSSID (if available), though. */
5654
5655 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5656 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005657 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5658 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005659 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5660 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005661 return;
5662 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005663 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005664 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005665 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5666 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005667 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005668 * handshake processing which would normally set portValid. We
5669 * need this to allow the EAPOL state machines to be completed
5670 * without going through EAPOL-Key handshake.
5671 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005672 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005673 }
5674}
5675
5676
Sunil8cd6f4d2022-06-28 18:40:46 +00005677static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5678 const u8 *buf, size_t len)
5679{
5680 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5681 FRAME_ENCRYPTION_UNKNOWN);
5682}
5683
5684
Hai Shalomb755a2a2020-04-23 21:49:02 -07005685static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5686{
5687 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5688 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5689}
5690
5691
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005692int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005693{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005694 u8 prev_mac_addr[ETH_ALEN];
5695
5696 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5697
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005698 if ((!wpa_s->p2p_mgmt ||
5699 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5700 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005701 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005702 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5703 wpa_drv_get_mac_addr(wpa_s),
5704 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005705 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005706 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005707 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005708 if (wpa_s->l2 == NULL)
5709 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005710
5711 if (l2_packet_set_packet_filter(wpa_s->l2,
5712 L2_PACKET_FILTER_PKTTYPE))
5713 wpa_dbg(wpa_s, MSG_DEBUG,
5714 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005715
5716 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5717 wpa_msg(wpa_s, MSG_ERROR,
5718 "Failed to get own L2 address");
5719 return -1;
5720 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005721 } else {
5722 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5723 if (addr)
5724 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5725 }
5726
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005727 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005728 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005729
Hai Shalomc3565922019-10-28 11:58:20 -07005730#ifdef CONFIG_FST
5731 if (wpa_s->fst)
5732 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5733#endif /* CONFIG_FST */
5734
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005735 if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00005736 wpas_notify_mac_address_changed(wpa_s);
5737
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005738 return 0;
5739}
5740
5741
Dmitry Shmidt04949592012-07-19 12:16:46 -07005742static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5743 const u8 *buf, size_t len)
5744{
5745 struct wpa_supplicant *wpa_s = ctx;
5746 const struct l2_ethhdr *eth;
5747
5748 if (len < sizeof(*eth))
5749 return;
5750 eth = (const struct l2_ethhdr *) buf;
5751
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005752 if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005753 !(eth->h_dest[0] & 0x01)) {
5754 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5755 " (bridge - not for this interface - ignore)",
5756 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5757 return;
5758 }
5759
5760 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5761 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5762 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005763 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005764}
5765
5766
Hai Shalom899fcc72020-10-19 14:38:18 -07005767int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5768 const char *bridge_ifname)
5769{
5770 if (wpa_s->wpa_state > WPA_SCANNING)
5771 return -EBUSY;
5772
5773 if (bridge_ifname &&
5774 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5775 return -EINVAL;
5776
5777 if (!bridge_ifname)
5778 bridge_ifname = "";
5779
5780 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5781 return 0;
5782
5783 if (wpa_s->l2_br) {
5784 l2_packet_deinit(wpa_s->l2_br);
5785 wpa_s->l2_br = NULL;
5786 }
5787
5788 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5789 sizeof(wpa_s->bridge_ifname));
5790
5791 if (wpa_s->bridge_ifname[0]) {
5792 wpa_dbg(wpa_s, MSG_DEBUG,
5793 "Receiving packets from bridge interface '%s'",
5794 wpa_s->bridge_ifname);
5795 wpa_s->l2_br = l2_packet_init_bridge(
5796 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5797 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5798 if (!wpa_s->l2_br) {
5799 wpa_msg(wpa_s, MSG_ERROR,
5800 "Failed to open l2_packet connection for the bridge interface '%s'",
5801 wpa_s->bridge_ifname);
5802 goto fail;
5803 }
5804 }
5805
5806#ifdef CONFIG_TDLS
5807 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5808 goto fail;
5809#endif /* CONFIG_TDLS */
5810
5811 return 0;
5812fail:
5813 wpa_s->bridge_ifname[0] = 0;
5814 if (wpa_s->l2_br) {
5815 l2_packet_deinit(wpa_s->l2_br);
5816 wpa_s->l2_br = NULL;
5817 }
5818#ifdef CONFIG_TDLS
5819 if (!wpa_s->p2p_mgmt)
5820 wpa_tdls_init(wpa_s->wpa);
5821#endif /* CONFIG_TDLS */
5822 return -EIO;
5823}
5824
5825
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005826/**
5827 * wpa_supplicant_driver_init - Initialize driver interface parameters
5828 * @wpa_s: Pointer to wpa_supplicant data
5829 * Returns: 0 on success, -1 on failure
5830 *
5831 * This function is called to initialize driver interface parameters.
5832 * wpa_drv_init() must have been called before this function to initialize the
5833 * driver interface.
5834 */
5835int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5836{
5837 static int interface_count = 0;
5838
5839 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5840 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005841
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005842 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5843 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005844 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005845 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5846
Hai Shalomb755a2a2020-04-23 21:49:02 -07005847 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005848 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5849 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005850 wpa_s->l2_br = l2_packet_init_bridge(
5851 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5852 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005853 if (wpa_s->l2_br == NULL) {
5854 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5855 "connection for the bridge interface '%s'",
5856 wpa_s->bridge_ifname);
5857 return -1;
5858 }
5859 }
5860
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005861 if (wpa_s->conf->ap_scan == 2 &&
5862 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5863 wpa_printf(MSG_INFO,
5864 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5865 }
5866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867 wpa_clear_keys(wpa_s, NULL);
5868
5869 /* Make sure that TKIP countermeasures are not left enabled (could
5870 * happen if wpa_supplicant is killed during countermeasures. */
5871 wpa_drv_set_countermeasures(wpa_s, 0);
5872
5873 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5874 wpa_drv_flush_pmkid(wpa_s);
5875
5876 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005877 wpa_s->prev_scan_wildcard = 0;
5878
Dmitry Shmidt04949592012-07-19 12:16:46 -07005879 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005880 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5881 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5882 interface_count = 0;
5883 }
Keith Mok4389c282022-11-23 21:36:48 +00005884#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005885 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005886 wpa_supplicant_delayed_sched_scan(wpa_s,
5887 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005888 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005889 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005890 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005891#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005892 interface_count++;
5893 } else
5894 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5895
5896 return 0;
5897}
5898
5899
5900static int wpa_supplicant_daemon(const char *pid_file)
5901{
5902 wpa_printf(MSG_DEBUG, "Daemonize..");
5903 return os_daemonize(pid_file);
5904}
5905
5906
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005907static struct wpa_supplicant *
5908wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005909{
5910 struct wpa_supplicant *wpa_s;
5911
5912 wpa_s = os_zalloc(sizeof(*wpa_s));
5913 if (wpa_s == NULL)
5914 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005915 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005916 wpa_s->scan_interval = 5;
5917 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005918 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005919 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005920 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005921 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005922
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005923 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005924 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005925#ifdef CONFIG_TESTING_OPTIONS
5926 dl_list_init(&wpa_s->drv_signal_override);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005927 wpa_s->test_assoc_comeback_type = -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07005928#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005929#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08005930 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005931#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005932 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005934 return wpa_s;
5935}
5936
5937
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005938#ifdef CONFIG_HT_OVERRIDES
5939
5940static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5941 struct ieee80211_ht_capabilities *htcaps,
5942 struct ieee80211_ht_capabilities *htcaps_mask,
5943 const char *ht_mcs)
5944{
5945 /* parse ht_mcs into hex array */
5946 int i;
5947 const char *tmp = ht_mcs;
5948 char *end = NULL;
5949
5950 /* If ht_mcs is null, do not set anything */
5951 if (!ht_mcs)
5952 return 0;
5953
5954 /* This is what we are setting in the kernel */
5955 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5956
5957 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5958
5959 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005960 long v;
5961
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005962 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005963 v = strtol(tmp, &end, 16);
5964
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005965 if (errno == 0) {
5966 wpa_msg(wpa_s, MSG_DEBUG,
5967 "htcap value[%i]: %ld end: %p tmp: %p",
5968 i, v, end, tmp);
5969 if (end == tmp)
5970 break;
5971
5972 htcaps->supported_mcs_set[i] = v;
5973 tmp = end;
5974 } else {
5975 wpa_msg(wpa_s, MSG_ERROR,
5976 "Failed to parse ht-mcs: %s, error: %s\n",
5977 ht_mcs, strerror(errno));
5978 return -1;
5979 }
5980 }
5981
5982 /*
5983 * If we were able to parse any values, then set mask for the MCS set.
5984 */
5985 if (i) {
5986 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5987 IEEE80211_HT_MCS_MASK_LEN - 1);
5988 /* skip the 3 reserved bits */
5989 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5990 0x1f;
5991 }
5992
5993 return 0;
5994}
5995
5996
5997static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5998 struct ieee80211_ht_capabilities *htcaps,
5999 struct ieee80211_ht_capabilities *htcaps_mask,
6000 int disabled)
6001{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006002 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006003
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006004 if (disabled == -1)
6005 return 0;
6006
Hai Shalom74f70d42019-02-11 14:42:39 -08006007 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
6008
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006009 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
6010 htcaps_mask->ht_capabilities_info |= msk;
6011 if (disabled)
6012 htcaps->ht_capabilities_info &= msk;
6013 else
6014 htcaps->ht_capabilities_info |= msk;
6015
6016 return 0;
6017}
6018
6019
6020static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
6021 struct ieee80211_ht_capabilities *htcaps,
6022 struct ieee80211_ht_capabilities *htcaps_mask,
6023 int factor)
6024{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006025 if (factor == -1)
6026 return 0;
6027
Hai Shalom74f70d42019-02-11 14:42:39 -08006028 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
6029
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006030 if (factor < 0 || factor > 3) {
6031 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
6032 "Must be 0-3 or -1", factor);
6033 return -EINVAL;
6034 }
6035
6036 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
6037 htcaps->a_mpdu_params &= ~0x3;
6038 htcaps->a_mpdu_params |= factor & 0x3;
6039
6040 return 0;
6041}
6042
6043
6044static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
6045 struct ieee80211_ht_capabilities *htcaps,
6046 struct ieee80211_ht_capabilities *htcaps_mask,
6047 int density)
6048{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006049 if (density == -1)
6050 return 0;
6051
Hai Shalom74f70d42019-02-11 14:42:39 -08006052 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
6053
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006054 if (density < 0 || density > 7) {
6055 wpa_msg(wpa_s, MSG_ERROR,
6056 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6057 density);
6058 return -EINVAL;
6059 }
6060
6061 htcaps_mask->a_mpdu_params |= 0x1C;
6062 htcaps->a_mpdu_params &= ~(0x1C);
6063 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6064
6065 return 0;
6066}
6067
6068
6069static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6070 struct ieee80211_ht_capabilities *htcaps,
6071 struct ieee80211_ht_capabilities *htcaps_mask,
6072 int disabled)
6073{
Hai Shalom74f70d42019-02-11 14:42:39 -08006074 if (disabled)
6075 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006076
Paul Stewart092955c2017-02-06 09:13:09 -08006077 set_disable_ht40(htcaps, disabled);
6078 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006079
6080 return 0;
6081}
6082
6083
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006084static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6085 struct ieee80211_ht_capabilities *htcaps,
6086 struct ieee80211_ht_capabilities *htcaps_mask,
6087 int disabled)
6088{
6089 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006090 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6091 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006092
Hai Shalom74f70d42019-02-11 14:42:39 -08006093 if (disabled)
6094 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006095
6096 if (disabled)
6097 htcaps->ht_capabilities_info &= ~msk;
6098 else
6099 htcaps->ht_capabilities_info |= msk;
6100
6101 htcaps_mask->ht_capabilities_info |= msk;
6102
6103 return 0;
6104}
6105
6106
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006107static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6108 struct ieee80211_ht_capabilities *htcaps,
6109 struct ieee80211_ht_capabilities *htcaps_mask,
6110 int disabled)
6111{
6112 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006113 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006114
Hai Shalom74f70d42019-02-11 14:42:39 -08006115 if (disabled)
6116 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006117
6118 if (disabled)
6119 htcaps->ht_capabilities_info &= ~msk;
6120 else
6121 htcaps->ht_capabilities_info |= msk;
6122
6123 htcaps_mask->ht_capabilities_info |= msk;
6124
6125 return 0;
6126}
6127
6128
Hai Shalom74f70d42019-02-11 14:42:39 -08006129static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6130 struct ieee80211_ht_capabilities *htcaps,
6131 struct ieee80211_ht_capabilities *htcaps_mask,
6132 int tx_stbc)
6133{
6134 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6135
6136 if (tx_stbc == -1)
6137 return 0;
6138
6139 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6140
6141 if (tx_stbc < 0 || tx_stbc > 1) {
6142 wpa_msg(wpa_s, MSG_ERROR,
6143 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6144 return -EINVAL;
6145 }
6146
6147 htcaps_mask->ht_capabilities_info |= msk;
6148 htcaps->ht_capabilities_info &= ~msk;
6149 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6150
6151 return 0;
6152}
6153
6154
6155static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6156 struct ieee80211_ht_capabilities *htcaps,
6157 struct ieee80211_ht_capabilities *htcaps_mask,
6158 int rx_stbc)
6159{
6160 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6161
6162 if (rx_stbc == -1)
6163 return 0;
6164
6165 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6166
6167 if (rx_stbc < 0 || rx_stbc > 3) {
6168 wpa_msg(wpa_s, MSG_ERROR,
6169 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6170 return -EINVAL;
6171 }
6172
6173 htcaps_mask->ht_capabilities_info |= msk;
6174 htcaps->ht_capabilities_info &= ~msk;
6175 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6176
6177 return 0;
6178}
6179
6180
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006181void wpa_supplicant_apply_ht_overrides(
6182 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6183 struct wpa_driver_associate_params *params)
6184{
6185 struct ieee80211_ht_capabilities *htcaps;
6186 struct ieee80211_ht_capabilities *htcaps_mask;
6187
6188 if (!ssid)
6189 return;
6190
6191 params->disable_ht = ssid->disable_ht;
6192 if (!params->htcaps || !params->htcaps_mask)
6193 return;
6194
6195 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6196 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6197 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6198 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6199 ssid->disable_max_amsdu);
6200 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6201 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6202 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006203 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006204 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006205 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6206 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006207
6208 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006209 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006210 htcaps->ht_capabilities_info |= bit;
6211 htcaps_mask->ht_capabilities_info |= bit;
6212 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006213}
6214
6215#endif /* CONFIG_HT_OVERRIDES */
6216
6217
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006218#ifdef CONFIG_VHT_OVERRIDES
6219void wpa_supplicant_apply_vht_overrides(
6220 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6221 struct wpa_driver_associate_params *params)
6222{
6223 struct ieee80211_vht_capabilities *vhtcaps;
6224 struct ieee80211_vht_capabilities *vhtcaps_mask;
6225
6226 if (!ssid)
6227 return;
6228
6229 params->disable_vht = ssid->disable_vht;
6230
6231 vhtcaps = (void *) params->vhtcaps;
6232 vhtcaps_mask = (void *) params->vhtcaps_mask;
6233
6234 if (!vhtcaps || !vhtcaps_mask)
6235 return;
6236
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006237 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6238 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006239
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006240#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006241 if (ssid->disable_sgi) {
6242 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6243 VHT_CAP_SHORT_GI_160);
6244 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6245 VHT_CAP_SHORT_GI_160);
6246 wpa_msg(wpa_s, MSG_DEBUG,
6247 "disable-sgi override specified, vht-caps: 0x%x",
6248 vhtcaps->vht_capabilities_info);
6249 }
6250
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006251 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006252 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6253 int max_ampdu;
6254
6255 max_ampdu = (ssid->vht_capa &
6256 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6257 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006258
6259 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6260 wpa_set_ampdu_factor(wpa_s,
6261 (void *) params->htcaps,
6262 (void *) params->htcaps_mask,
6263 max_ampdu);
6264 }
6265#endif /* CONFIG_HT_OVERRIDES */
6266
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006267#define OVERRIDE_MCS(i) \
6268 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6269 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006270 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006271 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006272 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6273 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006274 } \
6275 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6276 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006277 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006278 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006279 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6280 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006281 }
6282
6283 OVERRIDE_MCS(1);
6284 OVERRIDE_MCS(2);
6285 OVERRIDE_MCS(3);
6286 OVERRIDE_MCS(4);
6287 OVERRIDE_MCS(5);
6288 OVERRIDE_MCS(6);
6289 OVERRIDE_MCS(7);
6290 OVERRIDE_MCS(8);
6291}
6292#endif /* CONFIG_VHT_OVERRIDES */
6293
6294
Hai Shalomfdcde762020-04-02 11:19:20 -07006295#ifdef CONFIG_HE_OVERRIDES
6296void wpa_supplicant_apply_he_overrides(
6297 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6298 struct wpa_driver_associate_params *params)
6299{
6300 if (!ssid)
6301 return;
6302
6303 params->disable_he = ssid->disable_he;
6304}
6305#endif /* CONFIG_HE_OVERRIDES */
6306
6307
Sunil Ravi77d572f2023-01-17 23:58:31 +00006308void wpa_supplicant_apply_eht_overrides(
6309 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6310 struct wpa_driver_associate_params *params)
6311{
6312 if (!ssid)
6313 return;
6314
6315 params->disable_eht = ssid->disable_eht;
6316}
6317
6318
Dmitry Shmidt04949592012-07-19 12:16:46 -07006319static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6320{
6321#ifdef PCSC_FUNCS
6322 size_t len;
6323
6324 if (!wpa_s->conf->pcsc_reader)
6325 return 0;
6326
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006327 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006328 if (!wpa_s->scard)
6329 return 1;
6330
6331 if (wpa_s->conf->pcsc_pin &&
6332 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6333 scard_deinit(wpa_s->scard);
6334 wpa_s->scard = NULL;
6335 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6336 return -1;
6337 }
6338
6339 len = sizeof(wpa_s->imsi) - 1;
6340 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6341 scard_deinit(wpa_s->scard);
6342 wpa_s->scard = NULL;
6343 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6344 return -1;
6345 }
6346 wpa_s->imsi[len] = '\0';
6347
6348 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6349
6350 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6351 wpa_s->imsi, wpa_s->mnc_len);
6352
6353 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6354 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6355#endif /* PCSC_FUNCS */
6356
6357 return 0;
6358}
6359
6360
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006361int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6362{
6363 char *val, *pos;
6364
6365 ext_password_deinit(wpa_s->ext_pw);
6366 wpa_s->ext_pw = NULL;
6367 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6368
6369 if (!wpa_s->conf->ext_password_backend)
6370 return 0;
6371
6372 val = os_strdup(wpa_s->conf->ext_password_backend);
6373 if (val == NULL)
6374 return -1;
6375 pos = os_strchr(val, ':');
6376 if (pos)
6377 *pos++ = '\0';
6378
6379 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6380
6381 wpa_s->ext_pw = ext_password_init(val, pos);
6382 os_free(val);
6383 if (wpa_s->ext_pw == NULL) {
6384 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6385 return -1;
6386 }
6387 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6388
6389 return 0;
6390}
6391
6392
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006393#ifdef CONFIG_FST
6394
6395static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6396{
6397 struct wpa_supplicant *wpa_s = ctx;
6398
6399 return (is_zero_ether_addr(wpa_s->bssid) ||
6400 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6401}
6402
6403
6404static void wpas_fst_get_channel_info_cb(void *ctx,
6405 enum hostapd_hw_mode *hw_mode,
6406 u8 *channel)
6407{
6408 struct wpa_supplicant *wpa_s = ctx;
6409
6410 if (wpa_s->current_bss) {
6411 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6412 channel);
6413 } else if (wpa_s->hw.num_modes) {
6414 *hw_mode = wpa_s->hw.modes[0].mode;
6415 } else {
6416 WPA_ASSERT(0);
6417 *hw_mode = 0;
6418 }
6419}
6420
6421
6422static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6423{
6424 struct wpa_supplicant *wpa_s = ctx;
6425
6426 *modes = wpa_s->hw.modes;
6427 return wpa_s->hw.num_modes;
6428}
6429
6430
6431static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6432{
6433 struct wpa_supplicant *wpa_s = ctx;
6434
6435 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6436 wpa_s->fst_ies = fst_ies;
6437}
6438
6439
6440static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6441{
6442 struct wpa_supplicant *wpa_s = ctx;
6443
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006444 if (!ether_addr_equal(wpa_s->bssid, da)) {
Paul Stewart092955c2017-02-06 09:13:09 -08006445 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6446 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6447 return -1;
6448 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006449 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006450 wpa_s->own_addr, wpa_s->bssid,
6451 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006452 0);
6453}
6454
6455
6456static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6457{
6458 struct wpa_supplicant *wpa_s = ctx;
6459
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006460 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006461 return wpa_s->received_mb_ies;
6462}
6463
6464
6465static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6466 const u8 *buf, size_t size)
6467{
6468 struct wpa_supplicant *wpa_s = ctx;
6469 struct mb_ies_info info;
6470
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006471 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006472
6473 if (!mb_ies_info_by_ies(&info, buf, size)) {
6474 wpabuf_free(wpa_s->received_mb_ies);
6475 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6476 }
6477}
6478
6479
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006480static const u8 * wpas_fst_get_peer_first(void *ctx,
6481 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006482 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006483{
6484 struct wpa_supplicant *wpa_s = ctx;
6485
6486 *get_ctx = NULL;
6487 if (!is_zero_ether_addr(wpa_s->bssid))
6488 return (wpa_s->received_mb_ies || !mb_only) ?
6489 wpa_s->bssid : NULL;
6490 return NULL;
6491}
6492
6493
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006494static const u8 * wpas_fst_get_peer_next(void *ctx,
6495 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006496 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006497{
6498 return NULL;
6499}
6500
6501void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6502 struct fst_wpa_obj *iface_obj)
6503{
Sunil8cd6f4d2022-06-28 18:40:46 +00006504 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006505 iface_obj->ctx = wpa_s;
6506 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6507 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6508 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6509 iface_obj->set_ies = wpas_fst_set_ies_cb;
6510 iface_obj->send_action = wpas_fst_send_action_cb;
6511 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6512 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6513 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6514 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6515}
6516#endif /* CONFIG_FST */
6517
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006518static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006519 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006520{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006521 struct wowlan_triggers *triggers;
6522 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006523
6524 if (!wpa_s->conf->wowlan_triggers)
6525 return 0;
6526
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006527 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6528 if (triggers) {
6529 ret = wpa_drv_wowlan(wpa_s, triggers);
6530 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006531 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006532 return ret;
6533}
6534
6535
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006536enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006537{
6538 if (freq < 3000)
6539 return BAND_2_4_GHZ;
6540 if (freq > 50000)
6541 return BAND_60_GHZ;
6542 return BAND_5_GHZ;
6543}
6544
6545
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006546unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006547{
6548 int i;
6549 unsigned int band = 0;
6550
6551 if (freqs) {
6552 /* freqs are specified for the radio work */
6553 for (i = 0; freqs[i]; i++)
6554 band |= wpas_freq_to_band(freqs[i]);
6555 } else {
6556 /*
6557 * freqs are not specified, implies all
6558 * the supported freqs by HW
6559 */
6560 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6561 if (wpa_s->hw.modes[i].num_channels != 0) {
6562 if (wpa_s->hw.modes[i].mode ==
6563 HOSTAPD_MODE_IEEE80211B ||
6564 wpa_s->hw.modes[i].mode ==
6565 HOSTAPD_MODE_IEEE80211G)
6566 band |= BAND_2_4_GHZ;
6567 else if (wpa_s->hw.modes[i].mode ==
6568 HOSTAPD_MODE_IEEE80211A)
6569 band |= BAND_5_GHZ;
6570 else if (wpa_s->hw.modes[i].mode ==
6571 HOSTAPD_MODE_IEEE80211AD)
6572 band |= BAND_60_GHZ;
6573 else if (wpa_s->hw.modes[i].mode ==
6574 HOSTAPD_MODE_IEEE80211ANY)
6575 band = BAND_2_4_GHZ | BAND_5_GHZ |
6576 BAND_60_GHZ;
6577 }
6578 }
6579 }
6580
6581 return band;
6582}
6583
6584
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006585static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6586 const char *rn)
6587{
6588 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6589 struct wpa_radio *radio;
6590
6591 while (rn && iface) {
6592 radio = iface->radio;
6593 if (radio && os_strcmp(rn, radio->name) == 0) {
6594 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6595 wpa_s->ifname, rn);
6596 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6597 return radio;
6598 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006599
6600 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006601 }
6602
6603 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6604 wpa_s->ifname, rn ? rn : "N/A");
6605 radio = os_zalloc(sizeof(*radio));
6606 if (radio == NULL)
6607 return NULL;
6608
6609 if (rn)
6610 os_strlcpy(radio->name, rn, sizeof(radio->name));
6611 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006612 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006613 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6614
6615 return radio;
6616}
6617
6618
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006619static void radio_work_free(struct wpa_radio_work *work)
6620{
6621 if (work->wpa_s->scan_work == work) {
6622 /* This should not really happen. */
6623 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6624 work->type, work, work->started);
6625 work->wpa_s->scan_work = NULL;
6626 }
6627
6628#ifdef CONFIG_P2P
6629 if (work->wpa_s->p2p_scan_work == work) {
6630 /* This should not really happen. */
6631 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6632 work->type, work, work->started);
6633 work->wpa_s->p2p_scan_work = NULL;
6634 }
6635#endif /* CONFIG_P2P */
6636
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006637 if (work->started) {
6638 work->wpa_s->radio->num_active_works--;
6639 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006640 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006641 work->type, work,
6642 work->wpa_s->radio->num_active_works);
6643 }
6644
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006645 dl_list_del(&work->list);
6646 os_free(work);
6647}
6648
6649
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006650static int radio_work_is_connect(struct wpa_radio_work *work)
6651{
6652 return os_strcmp(work->type, "sme-connect") == 0 ||
6653 os_strcmp(work->type, "connect") == 0;
6654}
6655
6656
6657static int radio_work_is_scan(struct wpa_radio_work *work)
6658{
6659 return os_strcmp(work->type, "scan") == 0 ||
6660 os_strcmp(work->type, "p2p-scan") == 0;
6661}
6662
6663
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006664static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6665{
6666 struct wpa_radio_work *active_work = NULL;
6667 struct wpa_radio_work *tmp;
6668
6669 /* Get the active work to know the type and band. */
6670 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6671 if (tmp->started) {
6672 active_work = tmp;
6673 break;
6674 }
6675 }
6676
6677 if (!active_work) {
6678 /* No active work, start one */
6679 radio->num_active_works = 0;
6680 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6681 list) {
6682 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006683 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006684 (((struct wpa_driver_scan_params *)
6685 tmp->ctx)->only_new_results ||
6686 tmp->wpa_s->clear_driver_scan_cache))
6687 continue;
6688 return tmp;
6689 }
6690 return NULL;
6691 }
6692
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006693 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006694 /*
6695 * If the active work is either connect or sme-connect,
6696 * do not parallelize them with other radio works.
6697 */
6698 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6699 "Do not parallelize radio work with %s",
6700 active_work->type);
6701 return NULL;
6702 }
6703
6704 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6705 if (tmp->started)
6706 continue;
6707
6708 /*
6709 * If connect or sme-connect are enqueued, parallelize only
6710 * those operations ahead of them in the queue.
6711 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006712 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006713 break;
6714
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006715 /* Serialize parallel scan and p2p_scan operations on the same
6716 * interface since the driver_nl80211 mechanism for tracking
6717 * scan cookies does not yet have support for this. */
6718 if (active_work->wpa_s == tmp->wpa_s &&
6719 radio_work_is_scan(active_work) &&
6720 radio_work_is_scan(tmp)) {
6721 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6722 "Do not start work '%s' when another work '%s' is already scheduled",
6723 tmp->type, active_work->type);
6724 continue;
6725 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006726 /*
6727 * Check that the radio works are distinct and
6728 * on different bands.
6729 */
6730 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6731 (active_work->bands != tmp->bands)) {
6732 /*
6733 * If a scan has to be scheduled through nl80211 scan
6734 * interface and if an external scan is already running,
6735 * do not schedule the scan since it is likely to get
6736 * rejected by kernel.
6737 */
6738 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006739 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006740 (((struct wpa_driver_scan_params *)
6741 tmp->ctx)->only_new_results ||
6742 tmp->wpa_s->clear_driver_scan_cache))
6743 continue;
6744
6745 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6746 "active_work:%s new_work:%s",
6747 active_work->type, tmp->type);
6748 return tmp;
6749 }
6750 }
6751
6752 /* Did not find a radio work to schedule in parallel. */
6753 return NULL;
6754}
6755
6756
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006757static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6758{
6759 struct wpa_radio *radio = eloop_ctx;
6760 struct wpa_radio_work *work;
6761 struct os_reltime now, diff;
6762 struct wpa_supplicant *wpa_s;
6763
6764 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006765 if (work == NULL) {
6766 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006767 return;
6768 }
6769
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006770 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6771 radio_list);
6772
6773 if (!(wpa_s &&
6774 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6775 if (work->started)
6776 return; /* already started and still in progress */
6777
Hai Shalom60840252021-02-19 19:02:11 -08006778 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006779 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6780 return;
6781 }
6782 } else {
6783 work = NULL;
6784 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6785 /* get the work to schedule next */
6786 work = radio_work_get_next_work(radio);
6787 }
6788 if (!work)
6789 return;
6790 }
6791
6792 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006793 os_get_reltime(&now);
6794 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006795 wpa_dbg(wpa_s, MSG_DEBUG,
6796 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006797 work->type, work, diff.sec, diff.usec);
6798 work->started = 1;
6799 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006800 radio->num_active_works++;
6801
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006802 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006803
6804 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6805 radio->num_active_works < MAX_ACTIVE_WORKS)
6806 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006807}
6808
6809
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006810/*
6811 * This function removes both started and pending radio works running on
6812 * the provided interface's radio.
6813 * Prior to the removal of the radio work, its callback (cb) is called with
6814 * deinit set to be 1. Each work's callback is responsible for clearing its
6815 * internal data and restoring to a correct state.
6816 * @wpa_s: wpa_supplicant data
6817 * @type: type of works to be removed
6818 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6819 * this interface's works.
6820 */
6821void radio_remove_works(struct wpa_supplicant *wpa_s,
6822 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006823{
6824 struct wpa_radio_work *work, *tmp;
6825 struct wpa_radio *radio = wpa_s->radio;
6826
6827 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6828 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006829 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006830 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006831
6832 /* skip other ifaces' works */
6833 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006834 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006835
6836 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6837 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006838 work->cb(work, 1);
6839 radio_work_free(work);
6840 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006841
6842 /* in case we removed the started work */
6843 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006844}
6845
6846
Roshan Pius3a1667e2018-07-03 15:17:14 -07006847void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6848{
6849 struct wpa_radio_work *work;
6850 struct wpa_radio *radio = wpa_s->radio;
6851
6852 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6853 if (work->ctx != ctx)
6854 continue;
6855 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6856 work->type, work, work->started ? " (started)" : "");
6857 radio_work_free(work);
6858 break;
6859 }
6860}
6861
6862
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006863static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6864{
6865 struct wpa_radio *radio = wpa_s->radio;
6866
6867 if (!radio)
6868 return;
6869
6870 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6871 wpa_s->ifname, radio->name);
6872 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006873 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006874 /* If the interface that triggered the external scan was removed, the
6875 * external scan is no longer running. */
6876 if (wpa_s == radio->external_scan_req_interface)
6877 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006878 wpa_s->radio = NULL;
6879 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006880 return; /* Interfaces remain for this radio */
6881
6882 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006883 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006884 os_free(radio);
6885}
6886
6887
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006888void radio_work_check_next(struct wpa_supplicant *wpa_s)
6889{
6890 struct wpa_radio *radio = wpa_s->radio;
6891
6892 if (dl_list_empty(&radio->work))
6893 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006894 if (wpa_s->ext_work_in_progress) {
6895 wpa_printf(MSG_DEBUG,
6896 "External radio work in progress - delay start of pending item");
6897 return;
6898 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006899 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6900 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6901}
6902
6903
6904/**
6905 * radio_add_work - Add a radio work item
6906 * @wpa_s: Pointer to wpa_supplicant data
6907 * @freq: Frequency of the offchannel operation in MHz or 0
6908 * @type: Unique identifier for each type of work
6909 * @next: Force as the next work to be executed
6910 * @cb: Callback function for indicating when radio is available
6911 * @ctx: Context pointer for the work (work->ctx in cb())
6912 * Returns: 0 on success, -1 on failure
6913 *
6914 * This function is used to request time for an operation that requires
6915 * exclusive radio control. Once the radio is available, the registered callback
6916 * function will be called. radio_work_done() must be called once the exclusive
6917 * radio operation has been completed, so that the radio is freed for other
6918 * operations. The special case of deinit=1 is used to free the context data
6919 * during interface removal. That does not allow the callback function to start
6920 * the radio operation, i.e., it must free any resources allocated for the radio
6921 * work and return.
6922 *
6923 * The @freq parameter can be used to indicate a single channel on which the
6924 * offchannel operation will occur. This may allow multiple radio work
6925 * operations to be performed in parallel if they apply for the same channel.
6926 * Setting this to 0 indicates that the work item may use multiple channels or
6927 * requires exclusive control of the radio.
6928 */
6929int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6930 const char *type, int next,
6931 void (*cb)(struct wpa_radio_work *work, int deinit),
6932 void *ctx)
6933{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006934 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006935 struct wpa_radio_work *work;
6936 int was_empty;
6937
6938 work = os_zalloc(sizeof(*work));
6939 if (work == NULL)
6940 return -1;
6941 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6942 os_get_reltime(&work->time);
6943 work->freq = freq;
6944 work->type = type;
6945 work->wpa_s = wpa_s;
6946 work->cb = cb;
6947 work->ctx = ctx;
6948
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006949 if (freq)
6950 work->bands = wpas_freq_to_band(freq);
6951 else if (os_strcmp(type, "scan") == 0 ||
6952 os_strcmp(type, "p2p-scan") == 0)
6953 work->bands = wpas_get_bands(wpa_s,
6954 ((struct wpa_driver_scan_params *)
6955 ctx)->freqs);
6956 else
6957 work->bands = wpas_get_bands(wpa_s, NULL);
6958
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006959 was_empty = dl_list_empty(&wpa_s->radio->work);
6960 if (next)
6961 dl_list_add(&wpa_s->radio->work, &work->list);
6962 else
6963 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6964 if (was_empty) {
6965 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6966 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006967 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6968 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6969 wpa_dbg(wpa_s, MSG_DEBUG,
6970 "Try to schedule a radio work (num_active_works=%u)",
6971 radio->num_active_works);
6972 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006973 }
6974
6975 return 0;
6976}
6977
6978
6979/**
6980 * radio_work_done - Indicate that a radio work item has been completed
6981 * @work: Completed work
6982 *
6983 * This function is called once the callback function registered with
6984 * radio_add_work() has completed its work.
6985 */
6986void radio_work_done(struct wpa_radio_work *work)
6987{
6988 struct wpa_supplicant *wpa_s = work->wpa_s;
6989 struct os_reltime now, diff;
6990 unsigned int started = work->started;
6991
6992 os_get_reltime(&now);
6993 os_reltime_sub(&now, &work->time, &diff);
6994 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6995 work->type, work, started ? "done" : "canceled",
6996 diff.sec, diff.usec);
6997 radio_work_free(work);
6998 if (started)
6999 radio_work_check_next(wpa_s);
7000}
7001
7002
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007003struct wpa_radio_work *
7004radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007005{
7006 struct wpa_radio_work *work;
7007 struct wpa_radio *radio = wpa_s->radio;
7008
7009 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7010 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007011 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007012 }
7013
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007014 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007015}
7016
7017
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007018static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007019 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007020{
7021 const char *ifname, *driver, *rn;
7022
7023 driver = iface->driver;
7024next_driver:
7025 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
7026 return -1;
7027
7028 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
7029 if (wpa_s->drv_priv == NULL) {
7030 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07007031 int level = MSG_ERROR;
7032
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007033 pos = driver ? os_strchr(driver, ',') : NULL;
7034 if (pos) {
7035 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
7036 "driver interface - try next driver wrapper");
7037 driver = pos + 1;
7038 goto next_driver;
7039 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007040
7041#ifdef CONFIG_MATCH_IFACE
7042 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
7043 level = MSG_DEBUG;
7044#endif /* CONFIG_MATCH_IFACE */
7045 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007046 return -1;
7047 }
7048 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
7049 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
7050 "driver_param '%s'", wpa_s->conf->driver_param);
7051 return -1;
7052 }
7053
7054 ifname = wpa_drv_get_ifname(wpa_s);
7055 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7056 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7057 "interface name with '%s'", ifname);
7058 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7059 }
7060
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007061 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007062 if (rn && rn[0] == '\0')
7063 rn = NULL;
7064
7065 wpa_s->radio = radio_add_interface(wpa_s, rn);
7066 if (wpa_s->radio == NULL)
7067 return -1;
7068
7069 return 0;
7070}
7071
7072
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007073#ifdef CONFIG_GAS_SERVER
7074
7075static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7076 unsigned int freq, const u8 *dst,
7077 const u8 *src, const u8 *bssid,
7078 const u8 *data, size_t data_len,
7079 enum offchannel_send_action_result result)
7080{
7081 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7082 " result=%s",
7083 freq, MAC2STR(dst),
7084 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7085 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7086 "FAILED"));
7087 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7088 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7089}
7090
7091
7092static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7093 struct wpabuf *buf, unsigned int wait_time)
7094{
7095 struct wpa_supplicant *wpa_s = ctx;
7096 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7097
7098 if (wait_time > wpa_s->max_remain_on_chan)
7099 wait_time = wpa_s->max_remain_on_chan;
7100
7101 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7102 wpabuf_head(buf), wpabuf_len(buf),
7103 wait_time, wpas_gas_server_tx_status, 0);
7104}
7105
7106#endif /* CONFIG_GAS_SERVER */
7107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007108static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007109 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007110{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007111 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007112 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007113 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007114
7115 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7116 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7117 iface->confname ? iface->confname : "N/A",
7118 iface->driver ? iface->driver : "default",
7119 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7120 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7121
7122 if (iface->confname) {
7123#ifdef CONFIG_BACKEND_FILE
7124 wpa_s->confname = os_rel2abs_path(iface->confname);
7125 if (wpa_s->confname == NULL) {
7126 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7127 "for configuration file '%s'.",
7128 iface->confname);
7129 return -1;
7130 }
7131 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7132 iface->confname, wpa_s->confname);
7133#else /* CONFIG_BACKEND_FILE */
7134 wpa_s->confname = os_strdup(iface->confname);
7135#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007136 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007137 if (wpa_s->conf == NULL) {
7138 wpa_printf(MSG_ERROR, "Failed to read or parse "
7139 "configuration '%s'.", wpa_s->confname);
7140 return -1;
7141 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007142 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007143 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007144 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007145 wpa_printf(MSG_ERROR,
7146 "Failed to read or parse configuration '%s'.",
7147 wpa_s->confanother);
7148 return -1;
7149 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007150
7151 /*
7152 * Override ctrl_interface and driver_param if set on command
7153 * line.
7154 */
7155 if (iface->ctrl_interface) {
7156 os_free(wpa_s->conf->ctrl_interface);
7157 wpa_s->conf->ctrl_interface =
7158 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007159 if (!wpa_s->conf->ctrl_interface) {
7160 wpa_printf(MSG_ERROR,
7161 "Failed to duplicate control interface '%s'.",
7162 iface->ctrl_interface);
7163 return -1;
7164 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007165 }
7166
7167 if (iface->driver_param) {
7168 os_free(wpa_s->conf->driver_param);
7169 wpa_s->conf->driver_param =
7170 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007171 if (!wpa_s->conf->driver_param) {
7172 wpa_printf(MSG_ERROR,
7173 "Failed to duplicate driver param '%s'.",
7174 iface->driver_param);
7175 return -1;
7176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007177 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007178
7179 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7180 os_free(wpa_s->conf->ctrl_interface);
7181 wpa_s->conf->ctrl_interface = NULL;
7182 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007183 } else
7184 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7185 iface->driver_param);
7186
7187 if (wpa_s->conf == NULL) {
7188 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7189 return -1;
7190 }
7191
7192 if (iface->ifname == NULL) {
7193 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7194 return -1;
7195 }
7196 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7197 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7198 iface->ifname);
7199 return -1;
7200 }
7201 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007202#ifdef CONFIG_MATCH_IFACE
7203 wpa_s->matched = iface->matched;
7204#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007205
7206 if (iface->bridge_ifname) {
7207 if (os_strlen(iface->bridge_ifname) >=
7208 sizeof(wpa_s->bridge_ifname)) {
7209 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7210 "name '%s'.", iface->bridge_ifname);
7211 return -1;
7212 }
7213 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7214 sizeof(wpa_s->bridge_ifname));
7215 }
7216
7217 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007218 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7219 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007220
7221 /* Initialize driver interface and register driver event handler before
7222 * L2 receive handler so that association events are processed before
7223 * EAPOL-Key packets if both become available for the same select()
7224 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007225 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007226 return -1;
7227
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007228 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7229 return -1;
7230
7231 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7232 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7233 NULL);
7234 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7235
7236 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7237 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7238 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7239 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7240 "dot11RSNAConfigPMKLifetime");
7241 return -1;
7242 }
7243
7244 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7245 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7246 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7247 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7248 "dot11RSNAConfigPMKReauthThreshold");
7249 return -1;
7250 }
7251
7252 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7253 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7254 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7255 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7256 "dot11RSNAConfigSATimeout");
7257 return -1;
7258 }
7259
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007260 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
7261 wpa_s->conf->ft_prepend_pmkid);
7262
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007263 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7264 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007265 &wpa_s->hw.flags,
7266 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007267 if (wpa_s->hw.modes) {
7268 u16 i;
7269
7270 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7271 if (wpa_s->hw.modes[i].vht_capab) {
7272 wpa_s->hw_capab = CAPAB_VHT;
7273 break;
7274 }
7275
7276 if (wpa_s->hw.modes[i].ht_capab &
7277 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7278 wpa_s->hw_capab = CAPAB_HT40;
7279 else if (wpa_s->hw.modes[i].ht_capab &&
7280 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7281 wpa_s->hw_capab = CAPAB_HT;
7282 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007283 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007284 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007285
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007286 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7287 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007288 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007289 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007290 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007291 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007292 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007293 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007294 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007296 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007297 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7298 wpa_s->max_sched_scan_plan_interval =
7299 capa.max_sched_scan_plan_interval;
7300 wpa_s->max_sched_scan_plan_iterations =
7301 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007302 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7303 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007304 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7305 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007306 wpa_s->extended_capa = capa.extended_capa;
7307 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7308 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007309 wpa_s->num_multichan_concurrent =
7310 capa.num_multichan_concurrent;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007311#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007312 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007313#endif /* CONFIG_NO_WMM_AC */
Sunil Ravi89eba102022-09-13 21:04:37 -07007314 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007315
7316 if (capa.mac_addr_rand_scan_supported)
7317 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7318 if (wpa_s->sched_scan_supported &&
7319 capa.mac_addr_rand_sched_scan_supported)
7320 wpa_s->mac_addr_rand_supported |=
7321 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007322
7323 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7324 if (wpa_s->extended_capa &&
7325 wpa_s->extended_capa_len >= 3 &&
7326 wpa_s->extended_capa[2] & 0x40)
7327 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007328 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007329#ifdef CONFIG_PASN
7330 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7331#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007332 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7333 !!(wpa_s->drv_flags &
7334 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007335 if (wpa_s->max_remain_on_chan == 0)
7336 wpa_s->max_remain_on_chan = 1000;
7337
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007338 /*
7339 * Only take p2p_mgmt parameters when P2P Device is supported.
7340 * Doing it here as it determines whether l2_packet_init() will be done
7341 * during wpa_supplicant_driver_init().
7342 */
7343 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7344 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007345
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007346 if (wpa_s->num_multichan_concurrent == 0)
7347 wpa_s->num_multichan_concurrent = 1;
7348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007349 if (wpa_supplicant_driver_init(wpa_s) < 0)
7350 return -1;
7351
7352#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007353 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007354 return -1;
7355#endif /* CONFIG_TDLS */
7356
7357 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7358 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7359 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7360 return -1;
7361 }
7362
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007363#ifdef CONFIG_FST
7364 if (wpa_s->conf->fst_group_id) {
7365 struct fst_iface_cfg cfg;
7366 struct fst_wpa_obj iface_obj;
7367
7368 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7369 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7370 sizeof(cfg.group_id));
7371 cfg.priority = wpa_s->conf->fst_priority;
7372 cfg.llt = wpa_s->conf->fst_llt;
7373
7374 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7375 &iface_obj, &cfg);
7376 if (!wpa_s->fst) {
7377 wpa_msg(wpa_s, MSG_ERROR,
7378 "FST: Cannot attach iface %s to group %s",
7379 wpa_s->ifname, cfg.group_id);
7380 return -1;
7381 }
7382 }
7383#endif /* CONFIG_FST */
7384
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007385 if (wpas_wps_init(wpa_s))
7386 return -1;
7387
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007388#ifdef CONFIG_GAS_SERVER
7389 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7390 if (!wpa_s->gas_server) {
7391 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7392 return -1;
7393 }
7394#endif /* CONFIG_GAS_SERVER */
7395
7396#ifdef CONFIG_DPP
7397 if (wpas_dpp_init(wpa_s) < 0)
7398 return -1;
7399#endif /* CONFIG_DPP */
7400
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007401#ifdef CONFIG_NAN_USD
7402 if (wpas_nan_usd_init(wpa_s) < 0)
7403 return -1;
7404#endif /* CONFIG_NAN_USD */
7405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007406 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7407 return -1;
7408 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7409
7410 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7411 if (wpa_s->ctrl_iface == NULL) {
7412 wpa_printf(MSG_ERROR,
7413 "Failed to initialize control interface '%s'.\n"
7414 "You may have another wpa_supplicant process "
7415 "already running or the file was\n"
7416 "left by an unclean termination of wpa_supplicant "
7417 "in which case you will need\n"
7418 "to manually remove this file before starting "
7419 "wpa_supplicant again.\n",
7420 wpa_s->conf->ctrl_interface);
7421 return -1;
7422 }
7423
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007424 wpa_s->gas = gas_query_init(wpa_s);
7425 if (wpa_s->gas == NULL) {
7426 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7427 return -1;
7428 }
7429
Roshan Pius3a1667e2018-07-03 15:17:14 -07007430 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7431 wpa_s->p2p_mgmt) &&
7432 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007433 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7434 return -1;
7435 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007436
7437 if (wpa_bss_init(wpa_s) < 0)
7438 return -1;
7439
Paul Stewart092955c2017-02-06 09:13:09 -08007440#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7441#ifdef CONFIG_MESH
7442 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7443#endif /* CONFIG_MESH */
7444#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7445
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007446 /*
7447 * Set Wake-on-WLAN triggers, if configured.
7448 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7449 * have effect anyway when the interface is down).
7450 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007451 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007452 return -1;
7453
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007454#ifdef CONFIG_EAP_PROXY
7455{
7456 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007457 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7458 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007459 if (wpa_s->mnc_len > 0) {
7460 wpa_s->imsi[len] = '\0';
7461 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7462 wpa_s->imsi, wpa_s->mnc_len);
7463 } else {
7464 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7465 }
7466}
7467#endif /* CONFIG_EAP_PROXY */
7468
Dmitry Shmidt04949592012-07-19 12:16:46 -07007469 if (pcsc_reader_init(wpa_s) < 0)
7470 return -1;
7471
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007472 if (wpas_init_ext_pw(wpa_s) < 0)
7473 return -1;
7474
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007475#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007476 wpas_rrm_reset(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007477#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007478
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007479 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7480
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007481#ifdef CONFIG_HS20
7482 hs20_init(wpa_s);
7483#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007484#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007485 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007486 if ((wpa_s->conf->oce & OCE_STA) &&
7487 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7488 wpa_s->enable_oce = OCE_STA;
7489 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7490 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7491 /* TODO: Need to add STA-CFON support */
7492 wpa_printf(MSG_ERROR,
7493 "OCE STA-CFON feature is not yet supported");
7494 }
7495 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007496 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7497#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007498
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007499 wpa_supplicant_set_default_scan_ies(wpa_s);
7500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007501 return 0;
7502}
7503
7504
7505static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007506 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007507{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007508 struct wpa_global *global = wpa_s->global;
7509 struct wpa_supplicant *iface, *prev;
7510
Jimmy Chen0e73c002021-08-18 13:21:30 +08007511 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007512 wpas_p2p_group_remove(wpa_s, "*");
7513
7514 iface = global->ifaces;
7515 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007516 if (iface->p2pdev == wpa_s)
7517 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007518 if (iface == wpa_s || iface->parent != wpa_s) {
7519 iface = iface->next;
7520 continue;
7521 }
7522 wpa_printf(MSG_DEBUG,
7523 "Remove remaining child interface %s from parent %s",
7524 iface->ifname, wpa_s->ifname);
7525 prev = iface;
7526 iface = iface->next;
7527 wpa_supplicant_remove_iface(global, prev, terminate);
7528 }
7529
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007530 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007531 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007532 /*
7533 * Don't deauthenticate if WoWLAN is enable and not explicitly
7534 * been configured to disconnect.
7535 */
7536 if (!wpa_drv_get_wowlan(wpa_s) ||
7537 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007538 wpa_supplicant_deauthenticate(
7539 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007540
Hai Shalomfdcde762020-04-02 11:19:20 -07007541 wpa_drv_set_countermeasures(wpa_s, 0);
7542 wpa_clear_keys(wpa_s, NULL);
7543 } else {
7544 wpa_msg(wpa_s, MSG_INFO,
7545 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7546 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007547 }
7548
7549 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007550 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007551
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007552 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007553 radio_remove_interface(wpa_s);
7554
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007555#ifdef CONFIG_FST
7556 if (wpa_s->fst) {
7557 fst_detach(wpa_s->fst);
7558 wpa_s->fst = NULL;
7559 }
7560 if (wpa_s->received_mb_ies) {
7561 wpabuf_free(wpa_s->received_mb_ies);
7562 wpa_s->received_mb_ies = NULL;
7563 }
7564#endif /* CONFIG_FST */
7565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007566 if (wpa_s->drv_priv)
7567 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007568
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007569 if (notify)
7570 wpas_notify_iface_removed(wpa_s);
7571
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007572 if (terminate)
7573 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007574
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007575 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7576 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007577
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007578#ifdef CONFIG_MESH
7579 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007580 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007581 wpa_s->ifmsh = NULL;
7582 }
7583#endif /* CONFIG_MESH */
7584
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007585 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007586 wpa_config_free(wpa_s->conf);
7587 wpa_s->conf = NULL;
7588 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007589
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007590 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007591 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007592
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007593 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007594}
7595
7596
Dmitry Shmidte4663042016-04-04 10:07:49 -07007597#ifdef CONFIG_MATCH_IFACE
7598
7599/**
7600 * wpa_supplicant_match_iface - Match an interface description to a name
7601 * @global: Pointer to global data from wpa_supplicant_init()
7602 * @ifname: Name of the interface to match
7603 * Returns: Pointer to the created interface description or %NULL on failure
7604 */
7605struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7606 const char *ifname)
7607{
7608 int i;
7609 struct wpa_interface *iface, *miface;
7610
7611 for (i = 0; i < global->params.match_iface_count; i++) {
7612 miface = &global->params.match_ifaces[i];
7613 if (!miface->ifname ||
7614 fnmatch(miface->ifname, ifname, 0) == 0) {
7615 iface = os_zalloc(sizeof(*iface));
7616 if (!iface)
7617 return NULL;
7618 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007619 if (!miface->ifname)
7620 iface->matched = WPA_IFACE_MATCHED_NULL;
7621 else
7622 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007623 iface->ifname = ifname;
7624 return iface;
7625 }
7626 }
7627
7628 return NULL;
7629}
7630
7631
7632/**
7633 * wpa_supplicant_match_existing - Match existing interfaces
7634 * @global: Pointer to global data from wpa_supplicant_init()
7635 * Returns: 0 on success, -1 on failure
7636 */
7637static int wpa_supplicant_match_existing(struct wpa_global *global)
7638{
7639 struct if_nameindex *ifi, *ifp;
7640 struct wpa_supplicant *wpa_s;
7641 struct wpa_interface *iface;
7642
7643 ifp = if_nameindex();
7644 if (!ifp) {
7645 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7646 return -1;
7647 }
7648
7649 for (ifi = ifp; ifi->if_name; ifi++) {
7650 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7651 if (wpa_s)
7652 continue;
7653 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7654 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007655 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007656 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007657 }
7658 }
7659
7660 if_freenameindex(ifp);
7661 return 0;
7662}
7663
7664#endif /* CONFIG_MATCH_IFACE */
7665
7666
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007667/**
7668 * wpa_supplicant_add_iface - Add a new network interface
7669 * @global: Pointer to global data from wpa_supplicant_init()
7670 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007671 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007672 * Returns: Pointer to the created interface or %NULL on failure
7673 *
7674 * This function is used to add new network interfaces for %wpa_supplicant.
7675 * This can be called before wpa_supplicant_run() to add interfaces before the
7676 * main event loop has been started. In addition, new interfaces can be added
7677 * dynamically while %wpa_supplicant is already running. This could happen,
7678 * e.g., when a hotplug network adapter is inserted.
7679 */
7680struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007681 struct wpa_interface *iface,
7682 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007683{
7684 struct wpa_supplicant *wpa_s;
7685 struct wpa_interface t_iface;
7686 struct wpa_ssid *ssid;
7687
7688 if (global == NULL || iface == NULL)
7689 return NULL;
7690
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007691 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007692 if (wpa_s == NULL)
7693 return NULL;
7694
7695 wpa_s->global = global;
7696
7697 t_iface = *iface;
7698 if (global->params.override_driver) {
7699 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7700 "('%s' -> '%s')",
7701 iface->driver, global->params.override_driver);
7702 t_iface.driver = global->params.override_driver;
7703 }
7704 if (global->params.override_ctrl_interface) {
7705 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7706 "ctrl_interface ('%s' -> '%s')",
7707 iface->ctrl_interface,
7708 global->params.override_ctrl_interface);
7709 t_iface.ctrl_interface =
7710 global->params.override_ctrl_interface;
7711 }
7712 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7713 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7714 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007715 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007716 return NULL;
7717 }
7718
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007719 /* Notify the control interfaces about new iface */
7720 if (wpas_notify_iface_added(wpa_s)) {
7721 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7722 return NULL;
7723 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007724
Jimmy Chene2206be2022-07-10 10:25:21 +08007725 /* Notify the control interfaces about new networks */
7726 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7727 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007728 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007729 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7730 && os_strncmp((const char *) ssid->ssid,
7731 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7732 wpas_notify_persistent_group_added(wpa_s, ssid);
7733 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007734 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007735
7736 wpa_s->next = global->ifaces;
7737 global->ifaces = wpa_s;
7738
7739 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007740 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007741
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007742#ifdef CONFIG_P2P
7743 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007744 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007745 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007746 wpas_p2p_add_p2pdev_interface(
7747 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007748 wpa_printf(MSG_INFO,
7749 "P2P: Failed to enable P2P Device interface");
7750 /* Try to continue without. P2P will be disabled. */
7751 }
7752#endif /* CONFIG_P2P */
7753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007754 return wpa_s;
7755}
7756
7757
7758/**
7759 * wpa_supplicant_remove_iface - Remove a network interface
7760 * @global: Pointer to global data from wpa_supplicant_init()
7761 * @wpa_s: Pointer to the network interface to be removed
7762 * Returns: 0 if interface was removed, -1 if interface was not found
7763 *
7764 * This function can be used to dynamically remove network interfaces from
7765 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7766 * addition, this function is used to remove all remaining interfaces when
7767 * %wpa_supplicant is terminated.
7768 */
7769int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007770 struct wpa_supplicant *wpa_s,
7771 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007772{
7773 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007774#ifdef CONFIG_MESH
7775 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7776 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007777 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007778#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007779
7780 /* Remove interface from the global list of interfaces */
7781 prev = global->ifaces;
7782 if (prev == wpa_s) {
7783 global->ifaces = wpa_s->next;
7784 } else {
7785 while (prev && prev->next != wpa_s)
7786 prev = prev->next;
7787 if (prev == NULL)
7788 return -1;
7789 prev->next = wpa_s->next;
7790 }
7791
7792 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7793
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007794#ifdef CONFIG_MESH
7795 if (mesh_if_created) {
7796 ifname = os_strdup(wpa_s->ifname);
7797 if (ifname == NULL) {
7798 wpa_dbg(wpa_s, MSG_ERROR,
7799 "mesh: Failed to malloc ifname");
7800 return -1;
7801 }
7802 }
7803#endif /* CONFIG_MESH */
7804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007805 if (global->p2p_group_formation == wpa_s)
7806 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007807 if (global->p2p_invite_group == wpa_s)
7808 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007809 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007810
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007811#ifdef CONFIG_MESH
7812 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007813 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007814 os_free(ifname);
7815 }
7816#endif /* CONFIG_MESH */
7817
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818 return 0;
7819}
7820
7821
7822/**
7823 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7824 * @wpa_s: Pointer to the network interface
7825 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7826 */
7827const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7828{
7829 const char *eapol_method;
7830
7831 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7832 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7833 return "NO-EAP";
7834 }
7835
7836 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7837 if (eapol_method == NULL)
7838 return "UNKNOWN-EAP";
7839
7840 return eapol_method;
7841}
7842
7843
7844/**
7845 * wpa_supplicant_get_iface - Get a new network interface
7846 * @global: Pointer to global data from wpa_supplicant_init()
7847 * @ifname: Interface name
7848 * Returns: Pointer to the interface or %NULL if not found
7849 */
7850struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7851 const char *ifname)
7852{
7853 struct wpa_supplicant *wpa_s;
7854
7855 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7856 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7857 return wpa_s;
7858 }
7859 return NULL;
7860}
7861
7862
7863#ifndef CONFIG_NO_WPA_MSG
7864static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7865{
7866 struct wpa_supplicant *wpa_s = ctx;
7867 if (wpa_s == NULL)
7868 return NULL;
7869 return wpa_s->ifname;
7870}
7871#endif /* CONFIG_NO_WPA_MSG */
7872
7873
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007874#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7875#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7876#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7877
7878/* Periodic cleanup tasks */
7879static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7880{
7881 struct wpa_global *global = eloop_ctx;
7882 struct wpa_supplicant *wpa_s;
7883
7884 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7885 wpas_periodic, global, NULL);
7886
7887#ifdef CONFIG_P2P
7888 if (global->p2p)
7889 p2p_expire_peers(global->p2p);
7890#endif /* CONFIG_P2P */
7891
7892 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7893 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7894#ifdef CONFIG_AP
7895 ap_periodic(wpa_s);
7896#endif /* CONFIG_AP */
7897 }
7898}
7899
7900
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007901/**
7902 * wpa_supplicant_init - Initialize %wpa_supplicant
7903 * @params: Parameters for %wpa_supplicant
7904 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7905 *
7906 * This function is used to initialize %wpa_supplicant. After successful
7907 * initialization, the returned data pointer can be used to add and remove
7908 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7909 */
7910struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7911{
7912 struct wpa_global *global;
7913 int ret, i;
7914
7915 if (params == NULL)
7916 return NULL;
7917
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007918#ifdef CONFIG_DRIVER_NDIS
7919 {
7920 void driver_ndis_init_ops(void);
7921 driver_ndis_init_ops();
7922 }
7923#endif /* CONFIG_DRIVER_NDIS */
7924
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007925#ifndef CONFIG_NO_WPA_MSG
7926 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7927#endif /* CONFIG_NO_WPA_MSG */
7928
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007929 if (params->wpa_debug_file_path)
7930 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007931 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007932 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007933 if (params->wpa_debug_syslog)
7934 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007935 if (params->wpa_debug_tracing) {
7936 ret = wpa_debug_open_linux_tracing();
7937 if (ret) {
7938 wpa_printf(MSG_ERROR,
7939 "Failed to enable trace logging");
7940 return NULL;
7941 }
7942 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007943
7944 ret = eap_register_methods();
7945 if (ret) {
7946 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7947 if (ret == -2)
7948 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7949 "the same EAP type.");
7950 return NULL;
7951 }
7952
7953 global = os_zalloc(sizeof(*global));
7954 if (global == NULL)
7955 return NULL;
7956 dl_list_init(&global->p2p_srv_bonjour);
7957 dl_list_init(&global->p2p_srv_upnp);
7958 global->params.daemonize = params->daemonize;
7959 global->params.wait_for_monitor = params->wait_for_monitor;
7960 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007961
7962 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007963 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007964 if (!global->params.pid_file) {
7965 wpa_supplicant_deinit(global);
7966 return NULL;
7967 }
7968 }
7969
7970 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007971 global->params.ctrl_interface =
7972 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007973 if (!global->params.ctrl_interface) {
7974 wpa_supplicant_deinit(global);
7975 return NULL;
7976 }
7977 }
7978
7979 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007980 global->params.ctrl_interface_group =
7981 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007982 if (!global->params.ctrl_interface_group) {
7983 wpa_supplicant_deinit(global);
7984 return NULL;
7985 }
7986 }
7987
7988 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007989 global->params.override_driver =
7990 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007991 if (!global->params.override_driver) {
7992 wpa_supplicant_deinit(global);
7993 return NULL;
7994 }
7995 }
7996
7997 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007998 global->params.override_ctrl_interface =
7999 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008000 if (!global->params.override_ctrl_interface) {
8001 wpa_supplicant_deinit(global);
8002 return NULL;
8003 }
8004 }
8005
Dmitry Shmidte4663042016-04-04 10:07:49 -07008006#ifdef CONFIG_MATCH_IFACE
8007 global->params.match_iface_count = params->match_iface_count;
8008 if (params->match_iface_count) {
8009 global->params.match_ifaces =
8010 os_calloc(params->match_iface_count,
8011 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00008012 if (!global->params.match_ifaces) {
8013 wpa_printf(MSG_ERROR,
8014 "Failed to allocate match interfaces");
8015 wpa_supplicant_deinit(global);
8016 return NULL;
8017 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07008018 os_memcpy(global->params.match_ifaces,
8019 params->match_ifaces,
8020 params->match_iface_count *
8021 sizeof(struct wpa_interface));
8022 }
8023#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008024#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00008025 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008026 global->params.conf_p2p_dev =
8027 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008028 if (!global->params.conf_p2p_dev) {
8029 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
8030 wpa_supplicant_deinit(global);
8031 return NULL;
8032 }
8033 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008034#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008035 wpa_debug_level = global->params.wpa_debug_level =
8036 params->wpa_debug_level;
8037 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
8038 params->wpa_debug_show_keys;
8039 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
8040 params->wpa_debug_timestamp;
8041
Hai Shalomfdcde762020-04-02 11:19:20 -07008042 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008043
8044 if (eloop_init()) {
8045 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
8046 wpa_supplicant_deinit(global);
8047 return NULL;
8048 }
8049
Jouni Malinen75ecf522011-06-27 15:19:46 -07008050 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008051
8052 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
8053 if (global->ctrl_iface == NULL) {
8054 wpa_supplicant_deinit(global);
8055 return NULL;
8056 }
8057
8058 if (wpas_notify_supplicant_initialized(global)) {
8059 wpa_supplicant_deinit(global);
8060 return NULL;
8061 }
8062
8063 for (i = 0; wpa_drivers[i]; i++)
8064 global->drv_count++;
8065 if (global->drv_count == 0) {
8066 wpa_printf(MSG_ERROR, "No drivers enabled");
8067 wpa_supplicant_deinit(global);
8068 return NULL;
8069 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008070 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008071 if (global->drv_priv == NULL) {
8072 wpa_supplicant_deinit(global);
8073 return NULL;
8074 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008075
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008076#ifdef CONFIG_WIFI_DISPLAY
8077 if (wifi_display_init(global) < 0) {
8078 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8079 wpa_supplicant_deinit(global);
8080 return NULL;
8081 }
8082#endif /* CONFIG_WIFI_DISPLAY */
8083
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008084 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8085 wpas_periodic, global, NULL);
8086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008087 return global;
8088}
8089
8090
8091/**
8092 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8093 * @global: Pointer to global data from wpa_supplicant_init()
8094 * Returns: 0 after successful event loop run, -1 on failure
8095 *
8096 * This function starts the main event loop and continues running as long as
8097 * there are any remaining events. In most cases, this function is running as
8098 * long as the %wpa_supplicant process in still in use.
8099 */
8100int wpa_supplicant_run(struct wpa_global *global)
8101{
8102 struct wpa_supplicant *wpa_s;
8103
8104 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008105 (wpa_supplicant_daemon(global->params.pid_file) ||
8106 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008107 return -1;
8108
Dmitry Shmidte4663042016-04-04 10:07:49 -07008109#ifdef CONFIG_MATCH_IFACE
8110 if (wpa_supplicant_match_existing(global))
8111 return -1;
8112#endif
8113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008114 if (global->params.wait_for_monitor) {
8115 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008116 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008117 wpa_supplicant_ctrl_iface_wait(
8118 wpa_s->ctrl_iface);
8119 }
8120
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008121#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008122 // If daemonize is enabled, initialize AIDL here.
8123 if (global->params.daemonize) {
8124 global->aidl = wpas_aidl_init(global);
8125 if (!global->aidl)
8126 return -1;
8127 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008128#endif /* CONFIG_AIDL */
8129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008130 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8131 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8132
8133 eloop_run();
8134
8135 return 0;
8136}
8137
8138
8139/**
8140 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8141 * @global: Pointer to global data from wpa_supplicant_init()
8142 *
8143 * This function is called to deinitialize %wpa_supplicant and to free all
8144 * allocated resources. Remaining network interfaces will also be removed.
8145 */
8146void wpa_supplicant_deinit(struct wpa_global *global)
8147{
8148 int i;
8149
8150 if (global == NULL)
8151 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008152
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008153 eloop_cancel_timeout(wpas_periodic, global, NULL);
8154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008155#ifdef CONFIG_WIFI_DISPLAY
8156 wifi_display_deinit(global);
8157#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008158
8159 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008160 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008161
8162 if (global->ctrl_iface)
8163 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8164
8165 wpas_notify_supplicant_deinitialized(global);
8166
8167 eap_peer_unregister_methods();
8168#ifdef CONFIG_AP
8169 eap_server_unregister_methods();
8170#endif /* CONFIG_AP */
8171
8172 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8173 if (!global->drv_priv[i])
8174 continue;
8175 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8176 }
8177 os_free(global->drv_priv);
8178
8179 random_deinit();
8180
8181 eloop_destroy();
8182
8183 if (global->params.pid_file) {
8184 os_daemonize_terminate(global->params.pid_file);
8185 os_free(global->params.pid_file);
8186 }
8187 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008188 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008189 os_free(global->params.override_driver);
8190 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008191#ifdef CONFIG_MATCH_IFACE
8192 os_free(global->params.match_ifaces);
8193#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008194#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008195 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008196#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008197
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008198 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008199 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008200 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008202 os_free(global);
8203 wpa_debug_close_syslog();
8204 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008205 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008206}
8207
8208
8209void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8210{
8211 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8212 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8213 char country[3];
8214 country[0] = wpa_s->conf->country[0];
8215 country[1] = wpa_s->conf->country[1];
8216 country[2] = '\0';
8217 if (wpa_drv_set_country(wpa_s, country) < 0) {
8218 wpa_printf(MSG_ERROR, "Failed to set country code "
8219 "'%s'", country);
8220 }
8221 }
8222
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008223 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8224 wpas_init_ext_pw(wpa_s);
8225
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008226 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8227 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8228
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008229 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8230 struct wpa_driver_capa capa;
8231 int res = wpa_drv_get_capa(wpa_s, &capa);
8232
8233 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8234 wpa_printf(MSG_ERROR,
8235 "Failed to update wowlan_triggers to '%s'",
8236 wpa_s->conf->wowlan_triggers);
8237 }
8238
Hai Shalom81f62d82019-07-22 12:10:00 -07008239 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8240 wpa_supplicant_set_default_scan_ies(wpa_s);
8241
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008242 if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
8243 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
8244 wpa_s->conf->ft_prepend_pmkid);
8245
Hai Shalom899fcc72020-10-19 14:38:18 -07008246#ifdef CONFIG_BGSCAN
8247 /*
8248 * We default to global bgscan parameters only when per-network bgscan
8249 * parameters aren't set. Only bother resetting bgscan parameters if
8250 * this is the case.
8251 */
8252 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8253 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8254 wpa_s->wpa_state == WPA_COMPLETED)
8255 wpa_supplicant_reset_bgscan(wpa_s);
8256#endif /* CONFIG_BGSCAN */
8257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008258#ifdef CONFIG_WPS
8259 wpas_wps_update_config(wpa_s);
8260#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008261 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008262 wpa_s->conf->changed_parameters = 0;
8263}
8264
8265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008266void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008267{
8268 int i;
8269
8270 for (i = 0; i < *num_freqs; i++) {
8271 if (freqs[i] == freq)
8272 return;
8273 }
8274
8275 freqs[*num_freqs] = freq;
8276 (*num_freqs)++;
8277}
8278
8279
8280static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8281{
8282 struct wpa_bss *bss, *cbss;
8283 const int max_freqs = 10;
8284 int *freqs;
8285 int num_freqs = 0;
8286
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008287 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008288 if (freqs == NULL)
8289 return NULL;
8290
8291 cbss = wpa_s->current_bss;
8292
8293 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8294 if (bss == cbss)
8295 continue;
8296 if (bss->ssid_len == cbss->ssid_len &&
8297 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008298 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008299 add_freq(freqs, &num_freqs, bss->freq);
8300 if (num_freqs == max_freqs)
8301 break;
8302 }
8303 }
8304
8305 if (num_freqs == 0) {
8306 os_free(freqs);
8307 freqs = NULL;
8308 }
8309
8310 return freqs;
8311}
8312
8313
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008314void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
8315 const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008316{
8317 int timeout;
8318 int count;
8319 int *freqs = NULL;
8320
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008321 wpas_connect_work_done(wpa_s);
8322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008323 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008324 * Remove possible authentication timeout since the connection failed.
8325 */
8326 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8327
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008328 /*
Hai Shalom60840252021-02-19 19:02:11 -08008329 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008330 * generated based on local request to disconnect.
8331 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008332 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008333 wpa_s->own_disconnect_req = 0;
8334 wpa_dbg(wpa_s, MSG_DEBUG,
8335 "Ignore connection failure due to local request to disconnect");
8336 return;
8337 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008338 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008339 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8340 "indication since interface has been put into "
8341 "disconnected state");
8342 return;
8343 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008344 if (wpa_s->auto_reconnect_disabled) {
8345 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8346 "indication since auto connect is disabled");
8347 return;
8348 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008349
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008350 /* Also mark links as failed */
8351 while (link_bssids && *link_bssids) {
8352 wpa_bssid_ignore_add(wpa_s, *link_bssids);
8353 link_bssids++;
8354 }
8355
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008356 /*
Hai Shalom60840252021-02-19 19:02:11 -08008357 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008358 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008359 */
Hai Shalom60840252021-02-19 19:02:11 -08008360 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008361 if (count == 1 && wpa_s->current_bss) {
8362 /*
Hai Shalom60840252021-02-19 19:02:11 -08008363 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008364 * another BSS available for the same ESS, we should try that
8365 * next. Otherwise, we may as well try this one once more
8366 * before allowing other, likely worse, ESSes to be considered.
8367 */
8368 freqs = get_bss_freqs_in_ess(wpa_s);
8369 if (freqs) {
8370 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8371 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008372 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008373 /*
8374 * On the next scan, go through only the known channels
8375 * used in this ESS based on previous scans to speed up
8376 * common load balancing use case.
8377 */
8378 os_free(wpa_s->next_scan_freqs);
8379 wpa_s->next_scan_freqs = freqs;
8380 }
8381 }
8382
Hai Shalom899fcc72020-10-19 14:38:18 -07008383 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008384
Hai Shalom899fcc72020-10-19 14:38:18 -07008385 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008386 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8387 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008388 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008389 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008390 /*
8391 * Multiple consecutive connection failures mean that other APs are
8392 * either not available or have already been tried, so we can start
8393 * increasing the delay here to avoid constant scanning.
8394 */
8395 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008396 case 1:
8397 timeout = 100;
8398 break;
8399 case 2:
8400 timeout = 500;
8401 break;
8402 case 3:
8403 timeout = 1000;
8404 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008405 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008406 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008407 break;
8408 default:
8409 timeout = 10000;
8410 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008411 }
8412
Hai Shalom899fcc72020-10-19 14:38:18 -07008413 wpa_dbg(wpa_s, MSG_DEBUG,
8414 "Consecutive connection failures: %d --> request scan in %d ms",
8415 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008417 /*
8418 * TODO: if more than one possible AP is available in scan results,
8419 * could try the other ones before requesting a new scan.
8420 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008421
8422 /* speed up the connection attempt with normal scan */
8423 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008424 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8425 1000 * (timeout % 1000));
8426}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008427
8428
Hai Shalomce48b4a2018-09-05 11:41:35 -07008429#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008430
8431void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8432{
8433 struct wpa_ssid *ssid = wpa_s->current_ssid;
8434 const u8 *realm, *username, *rrk;
8435 size_t realm_len, username_len, rrk_len;
8436 u16 next_seq_num;
8437
8438 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8439 * Check for ERP keys existing to limit when this can be done since
8440 * the rejection response is not protected and such triggers should
8441 * really not allow internal state to be modified unless required to
8442 * avoid significant issues in functionality. In addition, drop
8443 * externally configure PMKSA entries even without ERP keys since it
8444 * is possible for an external component to add PMKSA entries for FILS
8445 * authentication without restoring previously generated ERP keys.
8446 *
8447 * In this case, this is needed to allow recovery from cases where the
8448 * AP or authentication server has dropped PMKSAs and ERP keys. */
8449 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8450 return;
8451
8452 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8453 &username, &username_len,
8454 &realm, &realm_len, &next_seq_num,
8455 &rrk, &rrk_len) != 0 ||
8456 !realm) {
8457 wpa_dbg(wpa_s, MSG_DEBUG,
8458 "FILS: Drop external PMKSA cache entry");
8459 wpa_sm_aborted_external_cached(wpa_s->wpa);
8460 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8461 return;
8462 }
8463
8464 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8465 wpa_sm_aborted_cached(wpa_s->wpa);
8466 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8467}
8468
8469
Hai Shalomce48b4a2018-09-05 11:41:35 -07008470void fils_connection_failure(struct wpa_supplicant *wpa_s)
8471{
8472 struct wpa_ssid *ssid = wpa_s->current_ssid;
8473 const u8 *realm, *username, *rrk;
8474 size_t realm_len, username_len, rrk_len;
8475 u16 next_seq_num;
8476
8477 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8478 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8479 &username, &username_len,
8480 &realm, &realm_len, &next_seq_num,
8481 &rrk, &rrk_len) != 0 ||
8482 !realm)
8483 return;
8484
8485 wpa_hexdump_ascii(MSG_DEBUG,
8486 "FILS: Store last connection failure realm",
8487 realm, realm_len);
8488 os_free(wpa_s->last_con_fail_realm);
8489 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8490 if (wpa_s->last_con_fail_realm) {
8491 wpa_s->last_con_fail_realm_len = realm_len;
8492 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8493 }
8494}
8495#endif /* CONFIG_FILS */
8496
8497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008498int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8499{
8500 return wpa_s->conf->ap_scan == 2 ||
8501 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8502}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008503
Dmitry Shmidt04949592012-07-19 12:16:46 -07008504
Gabriel Biren57ededa2021-09-03 16:08:50 +00008505#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008506int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8507 struct wpa_ssid *ssid,
8508 const char *field,
8509 const char *value)
8510{
8511#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008512 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008513
8514 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8515 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8516 (const u8 *) value, os_strlen(value));
8517
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008518 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008519 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008520#else /* IEEE8021X_EAPOL */
8521 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8522 return -1;
8523#endif /* IEEE8021X_EAPOL */
8524}
8525
8526int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8527 struct wpa_ssid *ssid,
8528 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008529 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008530{
8531#ifdef IEEE8021X_EAPOL
8532 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008533 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008534
8535 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008536 case WPA_CTRL_REQ_EAP_IDENTITY:
8537 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008538 os_free(eap->imsi_identity);
8539 if (value == NULL)
8540 return -1;
8541 identity = os_strchr(value, ':');
8542 if (identity == NULL) {
8543 /* plain identity */
8544 eap->identity = (u8 *)os_strdup(value);
8545 eap->identity_len = os_strlen(value);
8546 } else {
8547 /* have both plain identity and encrypted identity */
8548 imsi_identity = value;
8549 *identity++ = '\0';
8550 /* plain identity */
8551 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8552 eap->imsi_identity_len = strlen(imsi_identity);
8553 /* encrypted identity */
8554 eap->identity = (u8 *)dup_binstr(identity,
8555 value_len - strlen(imsi_identity) - 1);
8556 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8557 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008558 eap->pending_req_identity = 0;
8559 if (ssid == wpa_s->current_ssid)
8560 wpa_s->reassociate = 1;
8561 break;
8562 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008563 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008564 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008565 if (!eap->password)
8566 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008567 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008568 eap->pending_req_password = 0;
8569 if (ssid == wpa_s->current_ssid)
8570 wpa_s->reassociate = 1;
8571 break;
8572 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008573 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008574 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008575 if (!eap->new_password)
8576 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008577 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008578 eap->pending_req_new_password = 0;
8579 if (ssid == wpa_s->current_ssid)
8580 wpa_s->reassociate = 1;
8581 break;
8582 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008583 str_clear_free(eap->cert.pin);
8584 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008585 if (!eap->cert.pin)
8586 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008587 eap->pending_req_pin = 0;
8588 if (ssid == wpa_s->current_ssid)
8589 wpa_s->reassociate = 1;
8590 break;
8591 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008592 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008593 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008594 if (!eap->otp)
8595 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008596 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008597 os_free(eap->pending_req_otp);
8598 eap->pending_req_otp = NULL;
8599 eap->pending_req_otp_len = 0;
8600 break;
8601 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008602 str_clear_free(eap->cert.private_key_passwd);
8603 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008604 if (!eap->cert.private_key_passwd)
8605 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008606 eap->pending_req_passphrase = 0;
8607 if (ssid == wpa_s->current_ssid)
8608 wpa_s->reassociate = 1;
8609 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008610 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008611 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008612 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008613 if (!eap->external_sim_resp)
8614 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008615 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008616 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008617 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8618 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8619 return -1;
8620 ssid->mem_only_psk = 1;
8621 if (ssid->passphrase)
8622 wpa_config_update_psk(ssid);
8623 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8624 wpa_supplicant_req_scan(wpa_s, 0, 0);
8625 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008626 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8627 if (eap->pending_ext_cert_check != PENDING_CHECK)
8628 return -1;
8629 if (os_strcmp(value, "good") == 0)
8630 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8631 else if (os_strcmp(value, "bad") == 0)
8632 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8633 else
8634 return -1;
8635 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008636 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008637 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008638 return -1;
8639 }
8640
8641 return 0;
8642#else /* IEEE8021X_EAPOL */
8643 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8644 return -1;
8645#endif /* IEEE8021X_EAPOL */
8646}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008647#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008648
8649
8650int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8651{
Hai Shalomfdcde762020-04-02 11:19:20 -07008652#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008653 int i;
8654 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008655#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008656
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008657 if (wpa_s->p2p_mgmt)
8658 return 1; /* no normal network profiles on p2p_mgmt interface */
8659
Dmitry Shmidt04949592012-07-19 12:16:46 -07008660 if (ssid == NULL)
8661 return 1;
8662
8663 if (ssid->disabled)
8664 return 1;
8665
Hai Shalomfdcde762020-04-02 11:19:20 -07008666#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008667 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008668 drv_enc = wpa_s->drv_enc;
8669 else
8670 drv_enc = (unsigned int) -1;
8671
8672 for (i = 0; i < NUM_WEP_KEYS; i++) {
8673 size_t len = ssid->wep_key_len[i];
8674 if (len == 0)
8675 continue;
8676 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8677 continue;
8678 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8679 continue;
8680 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8681 continue;
8682 return 1; /* invalid WEP key */
8683 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008684#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008685
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008686 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008687 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008688 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008689 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008690 return 1;
8691
Sunil Ravi89eba102022-09-13 21:04:37 -07008692#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008693#ifdef CRYPTO_RSA_OAEP_SHA256
8694 if (ssid->eap.imsi_privacy_cert) {
8695 struct crypto_rsa_key *key;
8696 bool failed = false;
8697
8698 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8699 if (!key)
8700 failed = true;
8701 crypto_rsa_key_free(key);
8702 if (failed) {
8703 wpa_printf(MSG_DEBUG,
8704 "Invalid imsi_privacy_cert (%s) - disable network",
8705 ssid->eap.imsi_privacy_cert);
8706 return 1;
8707 }
8708 }
8709#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008710#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008711
Dmitry Shmidt04949592012-07-19 12:16:46 -07008712 return 0;
8713}
8714
8715
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008716int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8717{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008718 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8719 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8720 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8721 /*
8722 * Driver does not support BIP -- ignore pmf=1 default
8723 * since the connection with PMF would fail and the
8724 * configuration does not require PMF to be enabled.
8725 */
8726 return NO_MGMT_FRAME_PROTECTION;
8727 }
8728
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008729 if (ssid &&
8730 (ssid->key_mgmt &
8731 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8732 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8733 /*
8734 * Do not use the default PMF value for non-RSN networks
8735 * since PMF is available only with RSN and pmf=2
8736 * configuration would otherwise prevent connections to
8737 * all open networks.
8738 */
8739 return NO_MGMT_FRAME_PROTECTION;
8740 }
8741
Sunil Ravi77d572f2023-01-17 23:58:31 +00008742#ifdef CONFIG_OCV
8743 /* Enable PMF if OCV is being enabled */
8744 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8745 ssid && ssid->ocv)
8746 return MGMT_FRAME_PROTECTION_OPTIONAL;
8747#endif /* CONFIG_OCV */
8748
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008749 return wpa_s->conf->pmf;
8750 }
8751
8752 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008753}
8754
8755
Sunil Ravi77d572f2023-01-17 23:58:31 +00008756#ifdef CONFIG_SAE
8757bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8758 struct wpa_ssid *ssid,
8759 const struct wpa_ie_data *ie)
8760{
8761 return wpa_s->conf->sae_check_mfp &&
8762 (!(ie->capabilities &
8763 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8764 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8765}
8766#endif /* CONFIG_SAE */
8767
8768
Hai Shalomc1a21442022-02-04 13:43:00 -08008769int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8770{
8771 if (wpa_s->current_ssid == NULL ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008772 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
Hai Shalomc1a21442022-02-04 13:43:00 -08008773 return 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008774 if (wpa_s->valid_links) {
8775 if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
8776 !wpas_ap_link_address(wpa_s, addr))
8777 return 0;
8778 } else {
8779 if (!ether_addr_equal(addr, wpa_s->bssid))
8780 return 0;
8781 }
Hai Shalomc1a21442022-02-04 13:43:00 -08008782 return wpa_sm_pmf_enabled(wpa_s->wpa);
8783}
8784
8785
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008786int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008787{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008788 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008789 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008790 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008791 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008792 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008793}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008794
8795
Sunil Ravi77d572f2023-01-17 23:58:31 +00008796void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8797 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008798{
8799 struct wpa_ssid *ssid = wpa_s->current_ssid;
8800 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008801 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008802
8803 if (ssid == NULL) {
8804 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8805 "SSID block");
8806 return;
8807 }
8808
8809 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8810 return;
8811
8812 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008813
8814#ifdef CONFIG_P2P
8815 if (ssid->p2p_group &&
8816 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8817 /*
8818 * Skip the wait time since there is a short timeout on the
8819 * connection to a P2P group.
8820 */
8821 return;
8822 }
8823#endif /* CONFIG_P2P */
8824
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008825 if (ssid->auth_failures > 50)
8826 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008827 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008828 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008829 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008830 dur = 90;
8831 else if (ssid->auth_failures > 3)
8832 dur = 60;
8833 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008834 dur = 30;
8835 else if (ssid->auth_failures > 1)
8836 dur = 20;
8837 else
8838 dur = 10;
8839
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008840 if (ssid->auth_failures > 1 &&
8841 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8842 dur += os_random() % (ssid->auth_failures * 10);
8843
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008844 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008845 if (now.sec + dur <= ssid->disabled_until.sec)
8846 return;
8847
8848 ssid->disabled_until.sec = now.sec + dur;
8849
8850 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008851 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008852 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008853 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008854
8855 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8856 int msg_len = snprintf(NULL, 0, format_str,
8857 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8858 ssid->auth_failures, dur, reason) + 1;
8859 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308860 if (!msg)
8861 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008862 snprintf(msg, msg_len, format_str,
8863 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8864 ssid->auth_failures, dur, reason);
8865 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8866 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008867
8868 if (bssid)
8869 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008870}
8871
8872
8873void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8874 struct wpa_ssid *ssid, int clear_failures)
8875{
8876 if (ssid == NULL)
8877 return;
8878
8879 if (ssid->disabled_until.sec) {
8880 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8881 "id=%d ssid=\"%s\"",
8882 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8883 }
8884 ssid->disabled_until.sec = 0;
8885 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008886 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008887 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008888 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8889 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8890 " ignored to allow a lower priority BSS, if any, to be tried next",
8891 MAC2STR(ssid->disabled_due_to));
8892 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8893 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8894 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008895}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008896
8897
8898int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8899{
8900 size_t i;
8901
8902 if (wpa_s->disallow_aps_bssid == NULL)
8903 return 0;
8904
8905 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008906 if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8907 bssid))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008908 return 1;
8909 }
8910
8911 return 0;
8912}
8913
8914
8915int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8916 size_t ssid_len)
8917{
8918 size_t i;
8919
8920 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8921 return 0;
8922
8923 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8924 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8925 if (ssid_len == s->ssid_len &&
8926 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8927 return 1;
8928 }
8929
8930 return 0;
8931}
8932
8933
8934/**
8935 * wpas_request_connection - Request a new connection
8936 * @wpa_s: Pointer to the network interface
8937 *
8938 * This function is used to request a new connection to be found. It will mark
8939 * the interface to allow reassociation and request a new scan to find a
8940 * suitable network to connect to.
8941 */
8942void wpas_request_connection(struct wpa_supplicant *wpa_s)
8943{
8944 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008945 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008946 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008947 wpa_s->disconnected = 0;
8948 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008949 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008950
8951 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8952 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008953 else
8954 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008955}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008956
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008957
Roshan Pius02242d72016-08-09 15:31:48 -07008958/**
8959 * wpas_request_disconnection - Request disconnection
8960 * @wpa_s: Pointer to the network interface
8961 *
8962 * This function is used to request disconnection from the currently connected
8963 * network. This will stop any ongoing scans and initiate deauthentication.
8964 */
8965void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8966{
8967#ifdef CONFIG_SME
8968 wpa_s->sme.prev_bssid_set = 0;
8969#endif /* CONFIG_SME */
8970 wpa_s->reassociate = 0;
8971 wpa_s->disconnected = 1;
8972 wpa_supplicant_cancel_sched_scan(wpa_s);
8973 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008974 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008975 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8976 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008977 radio_remove_works(wpa_s, "connect", 0);
8978 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008979 wpa_s->roam_in_progress = false;
8980#ifdef CONFIG_WNM
8981 wpa_s->bss_trans_mgmt_in_progress = false;
8982#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008983}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008984
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008985
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008986void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8987 struct wpa_used_freq_data *freqs_data,
8988 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008989{
8990 unsigned int i;
8991
8992 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8993 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008994 for (i = 0; i < len; i++) {
8995 struct wpa_used_freq_data *cur = &freqs_data[i];
8996 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8997 i, cur->freq, cur->flags);
8998 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008999}
9000
9001
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009002/*
9003 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009004 * are using the same radio as the current interface, and in addition, get
9005 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009006 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009007int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
9008 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009009 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009010{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009011 struct wpa_supplicant *ifs;
9012 u8 bssid[ETH_ALEN];
9013 int freq;
9014 unsigned int idx = 0, i;
9015
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009016 wpa_dbg(wpa_s, MSG_DEBUG,
9017 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009018 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009019
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009020 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
9021 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009022 if (idx == len)
9023 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009024
Sunil Ravi77d572f2023-01-17 23:58:31 +00009025 if (exclude_current && ifs == wpa_s)
9026 continue;
9027
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009028 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
9029 continue;
9030
9031 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009032 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
9033 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009034 freq = ifs->current_ssid->frequency;
9035 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
9036 freq = ifs->assoc_freq;
9037 else
9038 continue;
9039
9040 /* Hold only distinct freqs */
9041 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009042 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009043 break;
9044
9045 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009046 freqs_data[idx++].freq = freq;
9047
9048 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009049 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009050 WPA_FREQ_USED_BY_P2P_CLIENT :
9051 WPA_FREQ_USED_BY_INFRA_STATION;
9052 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009053 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009054
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009055 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009056 return idx;
9057}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009058
9059
9060/*
9061 * Find the operating frequencies of any of the virtual interfaces that
9062 * are using the same radio as the current interface.
9063 */
9064int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009065 int *freq_array, unsigned int len,
9066 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009067{
9068 struct wpa_used_freq_data *freqs_data;
9069 int num, i;
9070
9071 os_memset(freq_array, 0, sizeof(int) * len);
9072
9073 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
9074 if (!freqs_data)
9075 return -1;
9076
Sunil Ravi77d572f2023-01-17 23:58:31 +00009077 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
9078 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009079 for (i = 0; i < num; i++)
9080 freq_array[i] = freqs_data[i].freq;
9081
9082 os_free(freqs_data);
9083
9084 return num;
9085}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009086
9087
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009088struct wpa_supplicant *
9089wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9090{
9091 switch (frame) {
9092#ifdef CONFIG_P2P
9093 case VENDOR_ELEM_PROBE_REQ_P2P:
9094 case VENDOR_ELEM_PROBE_RESP_P2P:
9095 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9096 case VENDOR_ELEM_BEACON_P2P_GO:
9097 case VENDOR_ELEM_P2P_PD_REQ:
9098 case VENDOR_ELEM_P2P_PD_RESP:
9099 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9100 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9101 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9102 case VENDOR_ELEM_P2P_INV_REQ:
9103 case VENDOR_ELEM_P2P_INV_RESP:
9104 case VENDOR_ELEM_P2P_ASSOC_REQ:
9105 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009106 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009107#endif /* CONFIG_P2P */
9108 default:
9109 return wpa_s;
9110 }
9111}
9112
9113
9114void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9115{
9116 unsigned int i;
9117 char buf[30];
9118
9119 wpa_printf(MSG_DEBUG, "Update vendor elements");
9120
9121 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9122 if (wpa_s->vendor_elem[i]) {
9123 int res;
9124
9125 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9126 if (!os_snprintf_error(sizeof(buf), res)) {
9127 wpa_hexdump_buf(MSG_DEBUG, buf,
9128 wpa_s->vendor_elem[i]);
9129 }
9130 }
9131 }
9132
9133#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009134 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009135 wpa_s->global->p2p &&
9136 !wpa_s->global->p2p_disabled)
9137 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9138#endif /* CONFIG_P2P */
9139}
9140
9141
9142int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9143 const u8 *elem, size_t len)
9144{
9145 u8 *ie, *end;
9146
9147 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9148 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9149
9150 for (; ie + 1 < end; ie += 2 + ie[1]) {
9151 if (ie + len > end)
9152 break;
9153 if (os_memcmp(ie, elem, len) != 0)
9154 continue;
9155
9156 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9157 wpabuf_free(wpa_s->vendor_elem[frame]);
9158 wpa_s->vendor_elem[frame] = NULL;
9159 } else {
9160 os_memmove(ie, ie + len, end - (ie + len));
9161 wpa_s->vendor_elem[frame]->used -= len;
9162 }
9163 wpas_vendor_elem_update(wpa_s);
9164 return 0;
9165 }
9166
9167 return -1;
9168}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009169
9170
9171struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009172 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009173 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009174{
9175 u16 i;
9176
Hai Shalomc1a21442022-02-04 13:43:00 -08009177 if (!modes)
9178 return NULL;
9179
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009180 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009181 if (modes[i].mode != mode ||
9182 !modes[i].num_channels || !modes[i].channels)
9183 continue;
Sunil Ravi99c035e2024-07-12 01:42:03 +00009184 if (is_6ghz == modes[i].is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009185 return &modes[i];
9186 }
9187
9188 return NULL;
9189}
9190
9191
Hai Shalomc1a21442022-02-04 13:43:00 -08009192struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9193 u16 num_modes, int freq)
9194{
9195 int i, j;
9196
9197 for (i = 0; i < num_modes; i++) {
9198 for (j = 0; j < modes[i].num_channels; j++) {
9199 if (freq == modes[i].channels[j].freq)
9200 return &modes[i];
9201 }
9202 }
9203
9204 return NULL;
9205}
9206
9207
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009208static struct
9209wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9210 const u8 *bssid)
9211{
9212 struct wpa_bss_tmp_disallowed *bss;
9213
9214 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9215 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009216 if (ether_addr_equal(bssid, bss->bssid))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009217 return bss;
9218 }
9219
9220 return NULL;
9221}
9222
9223
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009224static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9225{
9226 struct wpa_bss_tmp_disallowed *tmp;
9227 unsigned int num_bssid = 0;
9228 u8 *bssids;
9229 int ret;
9230
9231 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9232 if (!bssids)
9233 return -1;
9234 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9235 struct wpa_bss_tmp_disallowed, list) {
9236 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9237 ETH_ALEN);
9238 num_bssid++;
9239 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009240 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009241 os_free(bssids);
9242 return ret;
9243}
9244
9245
9246static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9247{
9248 struct wpa_supplicant *wpa_s = eloop_ctx;
9249 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9250
9251 /* Make sure the bss is not already freed */
9252 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9253 struct wpa_bss_tmp_disallowed, list) {
9254 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009255 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009256 wpa_set_driver_tmp_disallow_list(wpa_s);
9257 break;
9258 }
9259 }
9260}
9261
9262
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009263void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009264 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009265{
9266 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009267
9268 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9269 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009270 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009271 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009272 }
9273
9274 bss = os_malloc(sizeof(*bss));
9275 if (!bss) {
9276 wpa_printf(MSG_DEBUG,
9277 "Failed to allocate memory for temp disallow BSS");
9278 return;
9279 }
9280
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009281 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9282 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009283 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009284
9285finish:
9286 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009287 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9288 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009289}
9290
9291
Hai Shalom74f70d42019-02-11 14:42:39 -08009292int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9293 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009294{
Hai Shalom74f70d42019-02-11 14:42:39 -08009295 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009296
9297 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9298 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009299 if (ether_addr_equal(bss->bssid, tmp->bssid)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009300 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009301 break;
9302 }
9303 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009304 if (!disallowed)
9305 return 0;
9306
9307 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009308 bss->level > disallowed->rssi_threshold) {
9309 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9310 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009311 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009312 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009313
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009314 return 1;
9315}
Hai Shalom81f62d82019-07-22 12:10:00 -07009316
9317
9318int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9319 unsigned int type, const u8 *addr,
9320 const u8 *mask)
9321{
9322 if ((addr && !mask) || (!addr && mask)) {
9323 wpa_printf(MSG_INFO,
9324 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9325 return -1;
9326 }
9327
9328 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9329 wpa_printf(MSG_INFO,
9330 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9331 return -1;
9332 }
9333
9334 if (type & MAC_ADDR_RAND_SCAN) {
9335 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9336 addr, mask))
9337 return -1;
9338 }
9339
9340 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9341 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9342 addr, mask))
9343 return -1;
9344
9345 if (wpa_s->sched_scanning && !wpa_s->pno)
9346 wpas_scan_restart_sched_scan(wpa_s);
9347 }
9348
9349 if (type & MAC_ADDR_RAND_PNO) {
9350 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9351 addr, mask))
9352 return -1;
9353
9354 if (wpa_s->pno) {
9355 wpas_stop_pno(wpa_s);
9356 wpas_start_pno(wpa_s);
9357 }
9358 }
9359
9360 return 0;
9361}
9362
9363
9364int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9365 unsigned int type)
9366{
9367 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9368 if (wpa_s->pno) {
9369 if (type & MAC_ADDR_RAND_PNO) {
9370 wpas_stop_pno(wpa_s);
9371 wpas_start_pno(wpa_s);
9372 }
9373 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9374 wpas_scan_restart_sched_scan(wpa_s);
9375 }
9376
9377 return 0;
9378}
Hai Shalomfdcde762020-04-02 11:19:20 -07009379
9380
9381int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9382 struct wpa_signal_info *si)
9383{
9384 int res;
9385
9386 if (!wpa_s->driver->signal_poll)
9387 return -1;
9388
9389 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9390
9391#ifdef CONFIG_TESTING_OPTIONS
9392 if (res == 0) {
9393 struct driver_signal_override *dso;
9394
9395 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9396 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009397 if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009398 continue;
9399 wpa_printf(MSG_DEBUG,
9400 "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 +00009401 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009402 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009403 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009404 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009405 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009406 dso->si_avg_beacon_signal,
9407 si->current_noise,
9408 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009409 si->data.signal = dso->si_current_signal;
9410 si->data.avg_signal = dso->si_avg_signal;
9411 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009412 si->current_noise = dso->si_current_noise;
9413 break;
9414 }
9415 }
9416#endif /* CONFIG_TESTING_OPTIONS */
9417
9418 return res;
9419}
9420
9421
9422struct wpa_scan_results *
Sunil Ravi99c035e2024-07-12 01:42:03 +00009423wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07009424{
9425 struct wpa_scan_results *scan_res;
9426#ifdef CONFIG_TESTING_OPTIONS
9427 size_t idx;
9428#endif /* CONFIG_TESTING_OPTIONS */
9429
Sunil Ravi99c035e2024-07-12 01:42:03 +00009430 if (wpa_s->driver->get_scan_results)
9431 scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
9432 bssid);
9433 else if (wpa_s->driver->get_scan_results2)
9434 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9435 else
Hai Shalomfdcde762020-04-02 11:19:20 -07009436 return NULL;
9437
Hai Shalomfdcde762020-04-02 11:19:20 -07009438
9439#ifdef CONFIG_TESTING_OPTIONS
9440 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9441 struct driver_signal_override *dso;
9442 struct wpa_scan_res *res = scan_res->res[idx];
9443
9444 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9445 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009446 if (!ether_addr_equal(res->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009447 continue;
9448 wpa_printf(MSG_DEBUG,
9449 "Override driver scan signal level %d->%d for "
9450 MACSTR,
9451 res->level, dso->scan_level,
9452 MAC2STR(res->bssid));
9453 res->flags |= WPA_SCAN_QUAL_INVALID;
9454 if (dso->scan_level < 0)
9455 res->flags |= WPA_SCAN_LEVEL_DBM;
9456 else
9457 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9458 res->level = dso->scan_level;
9459 break;
9460 }
9461 }
9462#endif /* CONFIG_TESTING_OPTIONS */
9463
9464 return scan_res;
9465}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009466
9467
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009468bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009469{
9470 int i;
9471
9472 if (!wpa_s->valid_links)
9473 return false;
9474
Sunil Ravi99c035e2024-07-12 01:42:03 +00009475 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009476 if (ether_addr_equal(wpa_s->links[i].bssid, addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00009477 return true;
9478 }
9479
9480 return false;
9481}
9482
9483
9484int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9485 unsigned int wait, const u8 *dst, const u8 *src,
9486 const u8 *bssid, const u8 *data, size_t data_len,
9487 int no_cck)
9488{
9489 if (!wpa_s->driver->send_action)
9490 return -1;
9491
9492 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9493 if (wpas_ap_link_address(wpa_s, dst))
9494 dst = wpa_s->ap_mld_addr;
9495
9496 if (wpas_ap_link_address(wpa_s, bssid))
9497 bssid = wpa_s->ap_mld_addr;
9498 }
9499
9500 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9501 bssid, data, data_len, no_cck);
9502}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009503
9504
9505bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9506{
9507 struct hostapd_channel_data *chnl;
9508 int i, j;
9509
9510 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9511 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9512 chnl = wpa_s->hw.modes[i].channels;
9513 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9514 if (only_enabled &&
9515 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9516 continue;
9517 if (is_6ghz_freq(chnl[j].freq))
9518 return true;
9519 }
9520 }
9521 }
9522
9523 return false;
9524}