blob: a851024587750c3705bebd14cb26289a4f9475ca [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 Ravi88611412024-06-28 17:34:56 +0000681#ifdef CONFIG_WNM
682 wnm_deallocate_memory(wpa_s);
683#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700684
685 ext_password_deinit(wpa_s->ext_pw);
686 wpa_s->ext_pw = NULL;
687
688 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800689 wpa_s->last_gas_resp = NULL;
690 wpabuf_free(wpa_s->prev_gas_resp);
691 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700692
693 os_free(wpa_s->last_scan_res);
694 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800695
696#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700697 if (wpa_s->drv_priv)
698 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700699 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800700#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700701
702 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
703 wpabuf_free(wpa_s->vendor_elem[i]);
704 wpa_s->vendor_elem[i] = NULL;
705 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800706
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000707#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800708 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000709#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800710
711 wpa_s->sched_scan_plans_num = 0;
712 os_free(wpa_s->sched_scan_plans);
713 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800714
715#ifdef CONFIG_MBO
716 wpa_s->non_pref_chan_num = 0;
717 os_free(wpa_s->non_pref_chan);
718 wpa_s->non_pref_chan = NULL;
719#endif /* CONFIG_MBO */
720
721 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700722
723 wpabuf_free(wpa_s->lci);
724 wpa_s->lci = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000725#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800726 wpas_clear_beacon_rep_data(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000727#endif /* CONFIG_NO_RRM */
Paul Stewart092955c2017-02-06 09:13:09 -0800728
729#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
730#ifdef CONFIG_MESH
731 {
732 struct external_pmksa_cache *entry;
733
734 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
735 struct external_pmksa_cache,
736 list)) != NULL) {
737 dl_list_del(&entry->list);
738 os_free(entry->pmksa_cache);
739 os_free(entry);
740 }
741 }
742#endif /* CONFIG_MESH */
743#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
744
745 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800746
747 wpabuf_free(wpa_s->ric_ies);
748 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700749
750#ifdef CONFIG_DPP
751 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700752 dpp_global_deinit(wpa_s->dpp);
753 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700754#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800755
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000756#ifdef CONFIG_NAN_USD
757 wpas_nan_usd_deinit(wpa_s);
758#endif /* CONFIG_NAN_USD */
759
Hai Shalom60840252021-02-19 19:02:11 -0800760#ifdef CONFIG_PASN
761 wpas_pasn_auth_stop(wpa_s);
762#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000763#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -0800764 wpas_scs_deinit(wpa_s);
765 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000766#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000767
768#ifdef CONFIG_OWE
769 os_free(wpa_s->owe_trans_scan_freq);
770 wpa_s->owe_trans_scan_freq = NULL;
771#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772}
773
774
775/**
776 * wpa_clear_keys - Clear keys configured for the driver
777 * @wpa_s: Pointer to wpa_supplicant data
778 * @addr: Previously used BSSID or %NULL if not available
779 *
780 * This function clears the encryption keys that has been previously configured
781 * for the driver.
782 */
783void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
784{
Hai Shalomc3565922019-10-28 11:58:20 -0700785 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786
787 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800788 for (i = 0; i < max; i++) {
789 if (wpa_s->keys_cleared & BIT(i))
790 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000791 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700792 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800793 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700794 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
795 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800796 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700797 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000798 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
799 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700800 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000801 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
802 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 /* MLME-SETPROTECTION.request(None) */
804 wpa_drv_mlme_setprotection(
805 wpa_s, addr,
806 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
807 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
808 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800809 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700810}
811
812
813/**
814 * wpa_supplicant_state_txt - Get the connection state name as a text string
815 * @state: State (wpa_state; WPA_*)
816 * Returns: The state name as a printable text string
817 */
818const char * wpa_supplicant_state_txt(enum wpa_states state)
819{
820 switch (state) {
821 case WPA_DISCONNECTED:
822 return "DISCONNECTED";
823 case WPA_INACTIVE:
824 return "INACTIVE";
825 case WPA_INTERFACE_DISABLED:
826 return "INTERFACE_DISABLED";
827 case WPA_SCANNING:
828 return "SCANNING";
829 case WPA_AUTHENTICATING:
830 return "AUTHENTICATING";
831 case WPA_ASSOCIATING:
832 return "ASSOCIATING";
833 case WPA_ASSOCIATED:
834 return "ASSOCIATED";
835 case WPA_4WAY_HANDSHAKE:
836 return "4WAY_HANDSHAKE";
837 case WPA_GROUP_HANDSHAKE:
838 return "GROUP_HANDSHAKE";
839 case WPA_COMPLETED:
840 return "COMPLETED";
841 default:
842 return "UNKNOWN";
843 }
844}
845
846
847#ifdef CONFIG_BGSCAN
848
Hai Shalom899fcc72020-10-19 14:38:18 -0700849static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
850{
851 if (wpa_s->bgscan_ssid) {
852 bgscan_deinit(wpa_s);
853 wpa_s->bgscan_ssid = NULL;
854 }
855}
856
857
858/**
859 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
860 * @wpa_s: Pointer to the wpa_supplicant data
861 *
862 * Stop, start, or reconfigure the scan parameters depending on the method.
863 */
864void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700865{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800866 const char *name;
867
868 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
869 name = wpa_s->current_ssid->bgscan;
870 else
871 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700872 if (!name || name[0] == '\0') {
873 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800874 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700875 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800876 if (wpas_driver_bss_selection(wpa_s))
877 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800878#ifdef CONFIG_P2P
879 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
880 return;
881#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882
883 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800884 if (wpa_s->current_ssid) {
885 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700886 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
887 "bgscan");
888 /*
889 * Live without bgscan; it is only used as a roaming
890 * optimization, so the initial connection is not
891 * affected.
892 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700893 } else {
894 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700896 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
Sunil Ravi88611412024-06-28 17:34:56 +0000897 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700898 if (scan_res) {
899 bgscan_notify_scan(wpa_s, scan_res);
900 wpa_scan_results_free(scan_res);
901 }
902 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700903 } else
904 wpa_s->bgscan_ssid = NULL;
905}
906
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700907#endif /* CONFIG_BGSCAN */
908
909
Dmitry Shmidt04949592012-07-19 12:16:46 -0700910static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
911{
912 if (autoscan_init(wpa_s, 0))
913 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
914}
915
916
917static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
918{
919 autoscan_deinit(wpa_s);
920}
921
922
923void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
924{
925 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
926 wpa_s->wpa_state == WPA_SCANNING) {
927 autoscan_deinit(wpa_s);
928 wpa_supplicant_start_autoscan(wpa_s);
929 }
930}
931
932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933/**
934 * wpa_supplicant_set_state - Set current connection state
935 * @wpa_s: Pointer to wpa_supplicant data
936 * @state: The new connection state
937 *
938 * This function is called whenever the connection state changes, e.g.,
939 * association is completed for WPA/WPA2 4-Way Handshake is started.
940 */
941void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
942 enum wpa_states state)
943{
944 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700945#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700946 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700947#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948
949 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
950 wpa_supplicant_state_txt(wpa_s->wpa_state),
951 wpa_supplicant_state_txt(state));
952
Hai Shalom74f70d42019-02-11 14:42:39 -0800953 if (state == WPA_COMPLETED &&
954 os_reltime_initialized(&wpa_s->roam_start)) {
955 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
956 wpa_s->roam_start.sec = 0;
957 wpa_s->roam_start.usec = 0;
958 wpas_notify_auth_changed(wpa_s);
959 wpas_notify_roam_time(wpa_s);
960 wpas_notify_roam_complete(wpa_s);
961 } else if (state == WPA_DISCONNECTED &&
962 os_reltime_initialized(&wpa_s->roam_start)) {
963 wpa_s->roam_start.sec = 0;
964 wpa_s->roam_start.usec = 0;
965 wpa_s->roam_time.sec = 0;
966 wpa_s->roam_time.usec = 0;
967 wpas_notify_roam_complete(wpa_s);
968 }
969
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800970 if (state == WPA_INTERFACE_DISABLED) {
971 /* Assure normal scan when interface is restored */
972 wpa_s->normal_scans = 0;
973 }
974
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700975 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800976 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700977 /* Reinitialize normal_scan counter */
978 wpa_s->normal_scans = 0;
979 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800980
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700981#ifdef CONFIG_P2P
982 /*
983 * P2PS client has to reply to Probe Request frames received on the
984 * group operating channel. Enable Probe Request frame reporting for
985 * P2P connected client in case p2p_cli_probe configuration property is
986 * set to 1.
987 */
988 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
989 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
990 wpa_s->current_ssid->p2p_group) {
991 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
992 wpa_dbg(wpa_s, MSG_DEBUG,
993 "P2P: Enable CLI Probe Request RX reporting");
994 wpa_s->p2p_cli_probe =
995 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
996 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
997 wpa_dbg(wpa_s, MSG_DEBUG,
998 "P2P: Disable CLI Probe Request RX reporting");
999 wpa_s->p2p_cli_probe = 0;
1000 wpa_drv_probe_req_report(wpa_s, 0);
1001 }
1002 }
1003#endif /* CONFIG_P2P */
1004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005 if (state != WPA_SCANNING)
1006 wpa_supplicant_notify_scanning(wpa_s, 0);
1007
1008 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001010 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001011 char mld_addr[50];
1012
1013 mld_addr[0] = '\0';
1014 if (wpa_s->valid_links)
1015 os_snprintf(mld_addr, sizeof(mld_addr),
1016 " ap_mld_addr=" MACSTR,
1017 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018
1019#ifdef CONFIG_SME
1020 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1021 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1022 fils_hlp_sent = 1;
1023#endif /* CONFIG_SME */
1024 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1025 wpa_auth_alg_fils(wpa_s->auth_alg))
1026 fils_hlp_sent = 1;
1027
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001028#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001030 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001031 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001033 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001034 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001036 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001037 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 wpa_drv_set_operstate(wpa_s, 1);
1040#ifndef IEEE8021X_EAPOL
1041 wpa_drv_set_supp_port(wpa_s, 1);
1042#endif /* IEEE8021X_EAPOL */
1043 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001044 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001046
1047 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001048
1049#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1050 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001051 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001052#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001053#ifdef CONFIG_OWE
1054 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1055 wpas_update_owe_connect_params(wpa_s);
1056#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001057#ifdef CONFIG_HS20
1058 hs20_configure_frame_filters(wpa_s);
1059#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1061 state == WPA_ASSOCIATED) {
1062 wpa_s->new_connection = 1;
1063 wpa_drv_set_operstate(wpa_s, 0);
1064#ifndef IEEE8021X_EAPOL
1065 wpa_drv_set_supp_port(wpa_s, 0);
1066#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001067 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 }
1069 wpa_s->wpa_state = state;
1070
1071#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001072 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1073 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001074 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 wpa_supplicant_stop_bgscan(wpa_s);
1076#endif /* CONFIG_BGSCAN */
1077
Hai Shalom5f92bc92019-04-18 11:54:11 -07001078 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001079 wpa_supplicant_stop_autoscan(wpa_s);
1080
1081 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1082 wpa_supplicant_start_autoscan(wpa_s);
1083
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001084#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001085 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1086 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001087#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 if (wpa_s->wpa_state != old_state) {
1090 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1091
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001092 /*
1093 * Notify the P2P Device interface about a state change in one
1094 * of the interfaces.
1095 */
1096 wpas_p2p_indicate_state_change(wpa_s);
1097
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 if (wpa_s->wpa_state == WPA_COMPLETED ||
1099 old_state == WPA_COMPLETED)
1100 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001101#ifdef CONFIG_DPP2
1102 if (wpa_s->wpa_state == WPA_COMPLETED)
1103 wpas_dpp_connected(wpa_s);
1104#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 }
Hai Shalomc3565922019-10-28 11:58:20 -07001106#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1107 if (update_fils_connect_params)
1108 wpas_update_fils_connect_params(wpa_s);
1109#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110}
1111
1112
1113void wpa_supplicant_terminate_proc(struct wpa_global *global)
1114{
1115 int pending = 0;
1116#ifdef CONFIG_WPS
1117 struct wpa_supplicant *wpa_s = global->ifaces;
1118 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001119 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001120 if (wpas_wps_terminate_pending(wpa_s) == 1)
1121 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001122#ifdef CONFIG_P2P
1123 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1124 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1125 wpas_p2p_disconnect(wpa_s);
1126#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001127 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128 }
1129#endif /* CONFIG_WPS */
1130 if (pending)
1131 return;
1132 eloop_terminate();
1133}
1134
1135
1136static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1137{
1138 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 wpa_supplicant_terminate_proc(global);
1140}
1141
1142
1143void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1144{
1145 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001146 enum wpa_states new_state;
1147
1148 if (old_state == WPA_SCANNING)
1149 new_state = WPA_SCANNING;
1150 else
1151 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152
1153 wpa_s->pairwise_cipher = 0;
1154 wpa_s->group_cipher = 0;
1155 wpa_s->mgmt_group_cipher = 0;
1156 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001157 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001159 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160
1161 if (wpa_s->wpa_state != old_state)
1162 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1163}
1164
1165
1166/**
1167 * wpa_supplicant_reload_configuration - Reload configuration data
1168 * @wpa_s: Pointer to wpa_supplicant data
1169 * Returns: 0 on success or -1 if configuration parsing failed
1170 *
1171 * This function can be used to request that the configuration data is reloaded
1172 * (e.g., after configuration file change). This function is reloading
1173 * configuration only for one interface, so this may need to be called multiple
1174 * times if %wpa_supplicant is controlling multiple interfaces and all
1175 * interfaces need reconfiguration.
1176 */
1177int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1178{
1179 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001180 int reconf_ctrl;
1181 int old_ap_scan;
1182
1183 if (wpa_s->confname == NULL)
1184 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001185 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186 if (conf == NULL) {
1187 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1188 "file '%s' - exiting", wpa_s->confname);
1189 return -1;
1190 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001191 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001192 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001193 wpa_msg(wpa_s, MSG_ERROR,
1194 "Failed to parse the configuration file '%s' - exiting",
1195 wpa_s->confanother);
1196 return -1;
1197 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001198
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 conf->changed_parameters = (unsigned int) -1;
1200
1201 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1202 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1203 os_strcmp(conf->ctrl_interface,
1204 wpa_s->conf->ctrl_interface) != 0);
1205
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001206 if (reconf_ctrl) {
1207 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001208 wpa_s->ctrl_iface = NULL;
1209 }
1210
1211 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001212 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001213 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1214 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001215 wpa_supplicant_deauthenticate(wpa_s,
1216 WLAN_REASON_DEAUTH_LEAVING);
1217 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218
1219 /*
1220 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001221 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001223 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1224 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1225 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226 /*
1227 * Clear forced success to clear EAP state for next
1228 * authentication.
1229 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001230 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231 }
1232 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1233 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001234 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1236 rsn_preauth_deinit(wpa_s->wpa);
1237
1238 old_ap_scan = wpa_s->conf->ap_scan;
1239 wpa_config_free(wpa_s->conf);
1240 wpa_s->conf = conf;
1241 if (old_ap_scan != wpa_s->conf->ap_scan)
1242 wpas_notify_ap_scan_changed(wpa_s);
1243
1244 if (reconf_ctrl)
1245 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1246
1247 wpa_supplicant_update_config(wpa_s);
1248
1249 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001250 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001251 wpa_s->reassociate = 1;
1252 wpa_supplicant_req_scan(wpa_s, 0, 0);
1253 }
Hai Shalom60840252021-02-19 19:02:11 -08001254 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1256 return 0;
1257}
1258
1259
1260static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1261{
1262 struct wpa_global *global = signal_ctx;
1263 struct wpa_supplicant *wpa_s;
1264 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1265 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1266 sig);
1267 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1268 wpa_supplicant_terminate_proc(global);
1269 }
1270 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001271
1272 if (wpa_debug_reopen_file() < 0) {
1273 /* Ignore errors since we cannot really do much to fix this */
1274 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1275 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276}
1277
1278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1280 struct wpa_ssid *ssid,
1281 struct wpa_ie_data *ie)
1282{
1283 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1284 if (ret) {
1285 if (ret == -2) {
1286 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1287 "from association info");
1288 }
1289 return -1;
1290 }
1291
1292 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1293 "cipher suites");
1294 if (!(ie->group_cipher & ssid->group_cipher)) {
1295 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1296 "cipher 0x%x (mask 0x%x) - reject",
1297 ie->group_cipher, ssid->group_cipher);
1298 return -1;
1299 }
1300 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1301 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1302 "cipher 0x%x (mask 0x%x) - reject",
1303 ie->pairwise_cipher, ssid->pairwise_cipher);
1304 return -1;
1305 }
1306 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1307 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1308 "management 0x%x (mask 0x%x) - reject",
1309 ie->key_mgmt, ssid->key_mgmt);
1310 return -1;
1311 }
1312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001314 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1316 "that does not support management frame protection - "
1317 "reject");
1318 return -1;
1319 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320
1321 return 0;
1322}
1323
1324
Hai Shalom021b0b52019-04-10 11:17:58 -07001325static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1326 int freq)
1327{
1328 if (!ie->has_group)
1329 ie->group_cipher = wpa_default_rsn_cipher(freq);
1330 if (!ie->has_pairwise)
1331 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1332 return (ie->group_cipher & ssid->group_cipher) &&
1333 (ie->pairwise_cipher & ssid->pairwise_cipher);
1334}
1335
1336
Hai Shalomc1a21442022-02-04 13:43:00 -08001337void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1338 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1339{
1340 int sel;
1341
1342 sel = ie->mgmt_group_cipher;
1343 if (ssid->group_mgmt_cipher)
1344 sel &= ssid->group_mgmt_cipher;
1345 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1346 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1347 sel = 0;
1348 wpa_dbg(wpa_s, MSG_DEBUG,
1349 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1350 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1351 if (sel & WPA_CIPHER_AES_128_CMAC) {
1352 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1353 wpa_dbg(wpa_s, MSG_DEBUG,
1354 "WPA: using MGMT group cipher AES-128-CMAC");
1355 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1356 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1357 wpa_dbg(wpa_s, MSG_DEBUG,
1358 "WPA: using MGMT group cipher BIP-GMAC-128");
1359 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1360 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1361 wpa_dbg(wpa_s, MSG_DEBUG,
1362 "WPA: using MGMT group cipher BIP-GMAC-256");
1363 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1364 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1365 wpa_dbg(wpa_s, MSG_DEBUG,
1366 "WPA: using MGMT group cipher BIP-CMAC-256");
1367 } else {
1368 wpa_s->mgmt_group_cipher = 0;
1369 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1370 }
1371 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1372 wpa_s->mgmt_group_cipher);
1373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1374 wpas_get_ssid_pmf(wpa_s, ssid));
1375}
1376
Sunil Ravi77d572f2023-01-17 23:58:31 +00001377/**
1378 * wpa_supplicant_get_psk - Get PSK from config or external database
1379 * @wpa_s: Pointer to wpa_supplicant data
1380 * @bss: Scan results for the selected BSS, or %NULL if not available
1381 * @ssid: Configuration data for the selected network
1382 * @psk: Buffer for the PSK
1383 * Returns: 0 on success or -1 if configuration parsing failed
1384 *
1385 * This function obtains the PSK for a network, either included inline in the
1386 * config or retrieved from an external database.
1387 */
1388static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1389 struct wpa_bss *bss, struct wpa_ssid *ssid,
1390 u8 *psk)
1391{
1392 if (ssid->psk_set) {
1393 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1394 ssid->psk, PMK_LEN);
1395 os_memcpy(psk, ssid->psk, PMK_LEN);
1396 return 0;
1397 }
1398
1399#ifndef CONFIG_NO_PBKDF2
1400 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1401 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1402 4096, psk, PMK_LEN) != 0) {
1403 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1404 return -1;
1405 }
1406 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1407 psk, PMK_LEN);
1408 return 0;
1409 }
1410#endif /* CONFIG_NO_PBKDF2 */
1411
1412#ifdef CONFIG_EXT_PASSWORD
1413 if (ssid->ext_psk) {
1414 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1415 ssid->ext_psk);
1416 char pw_str[64 + 1];
1417
1418 if (!pw) {
1419 wpa_msg(wpa_s, MSG_INFO,
1420 "EXT PW: No PSK found from external storage");
1421 return -1;
1422 }
1423
1424 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1425 wpa_msg(wpa_s, MSG_INFO,
1426 "EXT PW: Unexpected PSK length %d in external storage",
1427 (int) wpabuf_len(pw));
1428 ext_password_free(pw);
1429 return -1;
1430 }
1431
1432 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1433 pw_str[wpabuf_len(pw)] = '\0';
1434
1435#ifndef CONFIG_NO_PBKDF2
1436 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1437 {
1438 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1439 4096, psk, PMK_LEN) != 0) {
1440 wpa_msg(wpa_s, MSG_WARNING,
1441 "Error in pbkdf2_sha1()");
1442 forced_memzero(pw_str, sizeof(pw_str));
1443 ext_password_free(pw);
1444 return -1;
1445 }
1446 wpa_hexdump_key(MSG_MSGDUMP,
1447 "PSK (from external passphrase)",
1448 psk, PMK_LEN);
1449 } else
1450#endif /* CONFIG_NO_PBKDF2 */
1451 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1452 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1453 wpa_msg(wpa_s, MSG_INFO,
1454 "EXT PW: Invalid PSK hex string");
1455 forced_memzero(pw_str, sizeof(pw_str));
1456 ext_password_free(pw);
1457 return -1;
1458 }
1459 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1460 psk, PMK_LEN);
1461 } else {
1462 wpa_msg(wpa_s, MSG_INFO,
1463 "EXT PW: No suitable PSK available");
1464 forced_memzero(pw_str, sizeof(pw_str));
1465 ext_password_free(pw);
1466 return -1;
1467 }
1468
1469 forced_memzero(pw_str, sizeof(pw_str));
1470 ext_password_free(pw);
1471
1472 return 0;
1473 }
1474#endif /* CONFIG_EXT_PASSWORD */
1475
1476 return -1;
1477}
1478
Hai Shalomc1a21442022-02-04 13:43:00 -08001479
Sunil Ravi89eba102022-09-13 21:04:37 -07001480static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1481 struct wpa_ssid *ssid)
1482{
1483 int akm_count = wpa_s->max_num_akms;
1484 u8 capab = 0;
1485
1486 if (akm_count < 2)
1487 return;
1488
1489 akm_count--;
1490 wpa_s->allowed_key_mgmts = 0;
1491 switch (wpa_s->key_mgmt) {
1492 case WPA_KEY_MGMT_PSK:
1493 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1494 akm_count--;
1495 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1496 }
1497 if (!akm_count)
1498 break;
1499 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1500 akm_count--;
1501 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1502 }
1503 if (!akm_count)
1504 break;
1505 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1506 wpa_s->allowed_key_mgmts |=
1507 WPA_KEY_MGMT_PSK_SHA256;
1508 break;
1509 case WPA_KEY_MGMT_PSK_SHA256:
1510 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1511 akm_count--;
1512 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1513 }
1514 if (!akm_count)
1515 break;
1516 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1517 akm_count--;
1518 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1519 }
1520 if (!akm_count)
1521 break;
1522 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1523 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1524 break;
1525 case WPA_KEY_MGMT_SAE:
1526 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1527 akm_count--;
1528 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1529 }
1530 if (!akm_count)
1531 break;
1532 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1533 akm_count--;
1534 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1535 }
1536 if (!akm_count)
1537 break;
1538 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1539 wpa_s->allowed_key_mgmts |=
1540 WPA_KEY_MGMT_PSK_SHA256;
1541 break;
1542 case WPA_KEY_MGMT_SAE_EXT_KEY:
1543 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1544 akm_count--;
1545 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1546 }
1547 if (!akm_count)
1548 break;
1549 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1550 akm_count--;
1551 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1552 }
1553 if (!akm_count)
1554 break;
1555 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1556 wpa_s->allowed_key_mgmts |=
1557 WPA_KEY_MGMT_PSK_SHA256;
1558 break;
1559 default:
1560 return;
1561 }
1562
Sunil Ravi77d572f2023-01-17 23:58:31 +00001563 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1564 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001565 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1566#ifdef CONFIG_SAE_PK
1567 if (ssid->sae_pk)
1568 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1569#endif /* CONFIG_SAE_PK */
1570
1571 if (!((wpa_s->allowed_key_mgmts &
1572 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1573 return;
1574
1575 if (!wpa_s->rsnxe_len) {
1576 wpa_s->rsnxe_len = 3;
1577 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1578 wpa_s->rsnxe[1] = 1;
1579 wpa_s->rsnxe[2] = 0;
1580 }
1581
1582 wpa_s->rsnxe[2] |= capab;
1583}
1584
1585
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001586/**
1587 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1588 * @wpa_s: Pointer to wpa_supplicant data
1589 * @bss: Scan results for the selected BSS, or %NULL if not available
1590 * @ssid: Configuration data for the selected network
1591 * @wpa_ie: Buffer for the WPA/RSN IE
1592 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1593 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001594 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001595 * Returns: 0 on success or -1 on failure
1596 *
1597 * This function is used to configure authentication and encryption parameters
1598 * based on the network configuration and scan result for the selected BSS (if
1599 * available).
1600 */
1601int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1602 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001603 u8 *wpa_ie, size_t *wpa_ie_len,
1604 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605{
1606 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001607 int sel, proto;
1608 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001609 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001610 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611
1612 if (bss) {
1613 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1614 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001615 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001616 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001617 } else {
1618 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1619 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620
1621 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1622 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001623 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001624 (ie.key_mgmt & ssid->key_mgmt)) {
1625 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1626 proto = WPA_PROTO_RSN;
1627 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001628 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 (ie.group_cipher & ssid->group_cipher) &&
1630 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1631 (ie.key_mgmt & ssid->key_mgmt)) {
1632 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1633 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001634#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001635 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1636 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1637 (ie.group_cipher & ssid->group_cipher) &&
1638 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1639 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001640 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001641 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001642 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1643 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1644 (ie.group_cipher & ssid->group_cipher) &&
1645 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1646 (ie.key_mgmt & ssid->key_mgmt)) {
1647 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1648 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001649#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001650 } else if (bss) {
1651 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001652 wpa_dbg(wpa_s, MSG_DEBUG,
1653 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1654 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1655 ssid->key_mgmt);
1656 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1657 MAC2STR(bss->bssid),
1658 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1659 bss_wpa ? " WPA" : "",
1660 bss_rsn ? " RSN" : "",
1661 bss_osen ? " OSEN" : "");
1662 if (bss_rsn) {
1663 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1664 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1665 wpa_dbg(wpa_s, MSG_DEBUG,
1666 "Could not parse RSN element");
1667 } else {
1668 wpa_dbg(wpa_s, MSG_DEBUG,
1669 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1670 ie.pairwise_cipher, ie.group_cipher,
1671 ie.key_mgmt);
1672 }
1673 }
1674 if (bss_wpa) {
1675 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1676 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1677 wpa_dbg(wpa_s, MSG_DEBUG,
1678 "Could not parse WPA element");
1679 } else {
1680 wpa_dbg(wpa_s, MSG_DEBUG,
1681 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1682 ie.pairwise_cipher, ie.group_cipher,
1683 ie.key_mgmt);
1684 }
1685 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001686 return -1;
1687 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001688 if (ssid->proto & WPA_PROTO_OSEN)
1689 proto = WPA_PROTO_OSEN;
1690 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691 proto = WPA_PROTO_RSN;
1692 else
1693 proto = WPA_PROTO_WPA;
1694 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1695 os_memset(&ie, 0, sizeof(ie));
1696 ie.group_cipher = ssid->group_cipher;
1697 ie.pairwise_cipher = ssid->pairwise_cipher;
1698 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001699 ie.mgmt_group_cipher = 0;
1700 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1701 if (ssid->group_mgmt_cipher &
1702 WPA_CIPHER_BIP_GMAC_256)
1703 ie.mgmt_group_cipher =
1704 WPA_CIPHER_BIP_GMAC_256;
1705 else if (ssid->group_mgmt_cipher &
1706 WPA_CIPHER_BIP_CMAC_256)
1707 ie.mgmt_group_cipher =
1708 WPA_CIPHER_BIP_CMAC_256;
1709 else if (ssid->group_mgmt_cipher &
1710 WPA_CIPHER_BIP_GMAC_128)
1711 ie.mgmt_group_cipher =
1712 WPA_CIPHER_BIP_GMAC_128;
1713 else
1714 ie.mgmt_group_cipher =
1715 WPA_CIPHER_AES_128_CMAC;
1716 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001717#ifdef CONFIG_OWE
1718 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1719 !ssid->owe_only &&
1720 !bss_wpa && !bss_rsn && !bss_osen) {
1721 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1722 wpa_s->wpa_proto = 0;
1723 *wpa_ie_len = 0;
1724 return 0;
1725 }
1726#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1728 "based on configuration");
1729 } else
1730 proto = ie.proto;
1731 }
1732
1733 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1734 "pairwise %d key_mgmt %d proto %d",
1735 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 if (ssid->ieee80211w) {
1737 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1738 ie.mgmt_group_cipher);
1739 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001740
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001741 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001742 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1743 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001744 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745
1746 if (bss || !wpa_s->ap_ies_from_associnfo) {
1747 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1748 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1749 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001750 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1751 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1752 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753 return -1;
1754 }
1755
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001756#ifdef CONFIG_NO_WPA
1757 wpa_s->group_cipher = WPA_CIPHER_NONE;
1758 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1759#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001761 wpa_dbg(wpa_s, MSG_DEBUG,
1762 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1763 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001764 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1765 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1767 "cipher");
1768 return -1;
1769 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001770 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1771 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772
1773 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001774 wpa_dbg(wpa_s, MSG_DEBUG,
1775 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1776 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001777 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1778 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1780 "cipher");
1781 return -1;
1782 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001783 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1784 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001785#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001786
1787 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001788#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001789 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1790 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001791 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001792 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1793 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001794#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001795#ifdef CONFIG_IEEE80211R
1796 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1797 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1798 sel &= ~WPA_KEY_MGMT_FT;
1799#endif /* CONFIG_IEEE80211R */
1800 wpa_dbg(wpa_s, MSG_DEBUG,
1801 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1802 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001803 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001804#ifdef CONFIG_IEEE80211R
1805#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001806 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1807 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001808 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1809 wpa_dbg(wpa_s, MSG_DEBUG,
1810 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001811 if (!ssid->ft_eap_pmksa_caching &&
1812 pmksa_cache_get_current(wpa_s->wpa)) {
1813 /* PMKSA caching with FT may have interoperability
1814 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001815 wpa_dbg(wpa_s, MSG_DEBUG,
1816 "WPA: Disable PMKSA caching for FT/802.1X connection");
1817 pmksa_cache_clear_current(wpa_s->wpa);
1818 }
1819#endif /* CONFIG_SHA384 */
1820#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001821#ifdef CONFIG_SUITEB192
1822 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1823 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1824 wpa_dbg(wpa_s, MSG_DEBUG,
1825 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1826#endif /* CONFIG_SUITEB192 */
1827#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001828 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1829 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1830 wpa_dbg(wpa_s, MSG_DEBUG,
1831 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001832#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001833#ifdef CONFIG_SHA384
1834 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1835 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1836 wpa_dbg(wpa_s, MSG_DEBUG,
1837 "WPA: using KEY_MGMT 802.1X with SHA384");
1838#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001839#ifdef CONFIG_FILS
1840#ifdef CONFIG_IEEE80211R
1841 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1842 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1843 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001844#endif /* CONFIG_IEEE80211R */
1845 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1846 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1847 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001848#ifdef CONFIG_IEEE80211R
1849 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1850 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1851 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1852#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001853 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1854 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1855 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1856#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001857#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001858 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1859 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1861 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001862 if (!ssid->ft_eap_pmksa_caching &&
1863 pmksa_cache_get_current(wpa_s->wpa)) {
1864 /* PMKSA caching with FT may have interoperability
1865 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001866 wpa_dbg(wpa_s, MSG_DEBUG,
1867 "WPA: Disable PMKSA caching for FT/802.1X connection");
1868 pmksa_cache_clear_current(wpa_s->wpa);
1869 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001870#endif /* CONFIG_IEEE80211R */
1871#ifdef CONFIG_DPP
1872 } else if (sel & WPA_KEY_MGMT_DPP) {
1873 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1874 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1875#endif /* CONFIG_DPP */
1876#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001877 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1878 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1879 wpa_dbg(wpa_s, MSG_DEBUG,
1880 "RSN: using KEY_MGMT FT/SAE (ext key)");
1881 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1882 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1883 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001884 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1885 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1886 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1887 } else if (sel & WPA_KEY_MGMT_SAE) {
1888 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1889 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1890#endif /* CONFIG_SAE */
1891#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1893 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1894 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1895#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001896 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1897 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1898 wpa_dbg(wpa_s, MSG_DEBUG,
1899 "WPA: using KEY_MGMT 802.1X with SHA256");
1900 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1901 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1902 wpa_dbg(wpa_s, MSG_DEBUG,
1903 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1905 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1906 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1907 } else if (sel & WPA_KEY_MGMT_PSK) {
1908 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1909 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1910 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1911 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1912 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001913#ifdef CONFIG_HS20
1914 } else if (sel & WPA_KEY_MGMT_OSEN) {
1915 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1916 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1917#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001918#ifdef CONFIG_OWE
1919 } else if (sel & WPA_KEY_MGMT_OWE) {
1920 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1921 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1922#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 } else {
1924 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1925 "authenticated key management type");
1926 return -1;
1927 }
1928
1929 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1930 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1931 wpa_s->pairwise_cipher);
1932 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1933
Hai Shalomc3565922019-10-28 11:58:20 -07001934 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001935 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1936 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001937 wpa_msg(wpa_s, MSG_INFO,
1938 "RSN: Management frame protection required but the selected AP does not enable it");
1939 return -1;
1940 }
1941
Hai Shalomc1a21442022-02-04 13:43:00 -08001942 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001943#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001944 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1945 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1946 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001947#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001948 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001949 if ((ssid->sae_password_id ||
1950 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001951 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1952 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1953 if (bss && is_6ghz_freq(bss->freq) &&
1954 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1955 wpa_dbg(wpa_s, MSG_DEBUG,
1956 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1957 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001958 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001959 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001960#ifdef CONFIG_SAE_PK
1961 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1962 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1963 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1964 ((ssid->sae_password &&
1965 sae_pk_valid_password(ssid->sae_password)) ||
1966 (!ssid->sae_password && ssid->passphrase &&
1967 sae_pk_valid_password(ssid->passphrase))));
1968#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001969 if (bss && is_6ghz_freq(bss->freq) &&
1970 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1971 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1972 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1973 MGMT_FRAME_PROTECTION_REQUIRED);
1974 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001975#ifdef CONFIG_TESTING_OPTIONS
1976 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1977 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001978 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1979 wpa_s->oci_freq_override_eapol);
1980 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1981 wpa_s->oci_freq_override_eapol_g2);
1982 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1983 wpa_s->oci_freq_override_ft_assoc);
1984 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1985 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001986 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1987 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001988#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001989
1990 /* Extended Key ID is only supported in infrastructure BSS so far */
1991 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1992 (ssid->proto & WPA_PROTO_RSN) &&
1993 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1994 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1995 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1996 int use_ext_key_id = 0;
1997
1998 wpa_msg(wpa_s, MSG_DEBUG,
1999 "WPA: Enable Extended Key ID support");
2000 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
2001 wpa_s->conf->extended_key_id);
2002 if (bss_rsn &&
2003 wpa_s->conf->extended_key_id &&
2004 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
2005 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
2006 use_ext_key_id = 1;
2007 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
2008 use_ext_key_id);
2009 } else {
2010 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
2011 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
2012 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013
Sunil Ravi640215c2023-06-28 23:08:09 +00002014 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2015 * appropriate advertisement of the supported number of PTKSA receive
2016 * counters. In theory, this could be based on a driver capability, but
2017 * in practice all cases using WMM support at least eight replay
2018 * counters, so use a hardcoded value for now since there is no explicit
2019 * driver capability indication for this.
2020 *
2021 * In addition, claim WMM to be enabled if the AP supports it since it
2022 * is far more likely for any current device to support WMM. */
2023 wmm = wpa_s->connection_set &&
2024 (wpa_s->connection_ht || wpa_s->connection_vht ||
2025 wpa_s->connection_he || wpa_s->connection_eht);
2026 if (!wmm && bss)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002027 wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002028 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2029
Sunil Ravi77d572f2023-01-17 23:58:31 +00002030 if (!skip_default_rsne) {
2031 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2032 wpa_ie_len)) {
2033 wpa_msg(wpa_s, MSG_WARNING,
2034 "RSN: Failed to generate RSNE/WPA IE");
2035 return -1;
2036 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037
Sunil Ravi77d572f2023-01-17 23:58:31 +00002038 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2039 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2040 &wpa_s->rsnxe_len)) {
2041 wpa_msg(wpa_s, MSG_WARNING,
2042 "RSN: Failed to generate RSNXE");
2043 return -1;
2044 }
Hai Shalomc3565922019-10-28 11:58:20 -07002045 }
2046
Hai Shalom021b0b52019-04-10 11:17:58 -07002047 if (0) {
2048#ifdef CONFIG_DPP
2049 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2050 /* Use PMK from DPP network introduction (PMKSA entry) */
2051 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002052#ifdef CONFIG_DPP2
2053 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2054#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002055#endif /* CONFIG_DPP */
2056 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002057 int psk_set = 0;
2058
Sunil Ravi77d572f2023-01-17 23:58:31 +00002059 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2060 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002061
Sunil Ravi77d572f2023-01-17 23:58:31 +00002062 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2063 psk) == 0) {
2064 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2065 NULL);
2066 psk_set = 1;
2067 }
2068 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002069 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002070
Roshan Pius3a1667e2018-07-03 15:17:14 -07002071 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002072 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002073 psk_set = 1;
2074
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002075 if (!psk_set) {
2076 wpa_msg(wpa_s, MSG_INFO,
2077 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002078 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002079 return -1;
2080 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002081#ifdef CONFIG_OWE
2082 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2083 /* OWE Diffie-Hellman exchange in (Re)Association
2084 * Request/Response frames set the PMK, so do not override it
2085 * here. */
2086#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002087 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002088 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2089
Hai Shalomfdcde762020-04-02 11:19:20 -07002090 if (ssid->mode != WPAS_MODE_IBSS &&
2091 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2092 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2093 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2094 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2095 wpa_msg(wpa_s, MSG_INFO,
2096 "Disable PTK0 rekey support - replaced with reconnect");
2097 wpa_s->deny_ptk0_rekey = 1;
2098 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2099 } else {
2100 wpa_s->deny_ptk0_rekey = 0;
2101 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2102 }
2103
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002104#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2105 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302106 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002107 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2108 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002109 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2110 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302111 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2112 wpa_dbg(wpa_s, MSG_INFO,
2113 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2114 }
Sunil Ravif42be322022-11-04 03:31:21 +00002115#else
2116 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2117 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2118 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002119#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2120 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002122 return 0;
2123}
2124
2125
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002126static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2127 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002128{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002129#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002130 bool scs = true, mscs = true;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002131#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08002132
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002133 *pos = 0x00;
2134
2135 switch (idx) {
2136 case 0: /* Bits 0-7 */
2137 break;
2138 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002139 if (wpa_s->conf->coloc_intf_reporting) {
2140 /* Bit 13 - Collocated Interference Reporting */
2141 *pos |= 0x20;
2142 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002143 break;
2144 case 2: /* Bits 16-23 */
2145#ifdef CONFIG_WNM
2146 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002147 if ((wpas_driver_bss_selection(wpa_s) ||
2148 !wpa_s->disable_mbo_oce) &&
2149 !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002150 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002151#endif /* CONFIG_WNM */
2152 break;
2153 case 3: /* Bits 24-31 */
2154#ifdef CONFIG_WNM
2155 *pos |= 0x02; /* Bit 25 - SSID List */
2156#endif /* CONFIG_WNM */
2157#ifdef CONFIG_INTERWORKING
2158 if (wpa_s->conf->interworking)
2159 *pos |= 0x80; /* Bit 31 - Interworking */
2160#endif /* CONFIG_INTERWORKING */
2161 break;
2162 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002163#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002164 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002165 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002166#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002167 break;
2168 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002169#ifdef CONFIG_HS20
2170 if (wpa_s->conf->hs20)
2171 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2172#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002173#ifdef CONFIG_MBO
2174 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2175#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002176 break;
2177 case 6: /* Bits 48-55 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002178#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002179#ifdef CONFIG_TESTING_OPTIONS
2180 if (wpa_s->disable_scs_support)
2181 scs = false;
2182#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002183 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2184 /* Drop own SCS capability indication since the AP does
2185 * not support it. This is needed to avoid
2186 * interoperability issues with APs that get confused
2187 * with Extended Capabilities element. */
2188 scs = false;
2189 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002190 if (scs)
2191 *pos |= 0x40; /* Bit 54 - SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002192#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002193 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002194 case 7: /* Bits 56-63 */
2195 break;
2196 case 8: /* Bits 64-71 */
2197 if (wpa_s->conf->ftm_responder)
2198 *pos |= 0x40; /* Bit 70 - FTM responder */
2199 if (wpa_s->conf->ftm_initiator)
2200 *pos |= 0x80; /* Bit 71 - FTM initiator */
2201 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002202 case 9: /* Bits 72-79 */
2203#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002204 if (!wpa_s->disable_fils)
2205 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002206#endif /* CONFIG_FILS */
2207 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002208 case 10: /* Bits 80-87 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002209#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002210#ifdef CONFIG_TESTING_OPTIONS
2211 if (wpa_s->disable_mscs_support)
2212 mscs = false;
2213#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002214 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2215 /* Drop own MSCS capability indication since the AP does
2216 * not support it. This is needed to avoid
2217 * interoperability issues with APs that get confused
2218 * with Extended Capabilities element. */
2219 mscs = false;
2220 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002221 if (mscs)
2222 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002223#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002224 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002225 }
2226}
2227
2228
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002229int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2230 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002231{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002232 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002233 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002234
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002235 if (len < wpa_s->extended_capa_len)
2236 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002237 if (buflen < (size_t) len + 2) {
2238 wpa_printf(MSG_INFO,
2239 "Not enough room for building extended capabilities element");
2240 return -1;
2241 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002242
2243 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002244 *pos++ = len;
2245 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002246 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002247
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002248 if (i < wpa_s->extended_capa_len) {
2249 *pos &= ~wpa_s->extended_capa_mask[i];
2250 *pos |= wpa_s->extended_capa[i];
2251 }
2252 }
2253
2254 while (len > 0 && buf[1 + len] == 0) {
2255 len--;
2256 buf[1] = len;
2257 }
2258 if (len == 0)
2259 return 0;
2260
2261 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002262}
2263
2264
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002265static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2266 struct wpa_bss *test_bss)
2267{
2268 struct wpa_bss *bss;
2269
2270 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2271 if (bss == test_bss)
2272 return 1;
2273 }
2274
2275 return 0;
2276}
2277
2278
2279static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2280 struct wpa_ssid *test_ssid)
2281{
2282 struct wpa_ssid *ssid;
2283
2284 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2285 if (ssid == test_ssid)
2286 return 1;
2287 }
2288
2289 return 0;
2290}
2291
2292
2293int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2294 struct wpa_ssid *test_ssid)
2295{
2296 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2297 return 0;
2298
2299 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2300}
2301
2302
2303void wpas_connect_work_free(struct wpa_connect_work *cwork)
2304{
2305 if (cwork == NULL)
2306 return;
2307 os_free(cwork);
2308}
2309
2310
2311void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2312{
2313 struct wpa_connect_work *cwork;
2314 struct wpa_radio_work *work = wpa_s->connect_work;
2315
2316 if (!work)
2317 return;
2318
2319 wpa_s->connect_work = NULL;
2320 cwork = work->ctx;
2321 work->ctx = NULL;
2322 wpas_connect_work_free(cwork);
2323 radio_work_done(work);
2324}
2325
2326
Sunil Ravi77d572f2023-01-17 23:58:31 +00002327int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2328 enum wpas_mac_addr_style style,
2329 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002330{
2331 struct os_reltime now;
2332 u8 addr[ETH_ALEN];
2333
2334 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002335 /* Random addresses are valid within a given ESS so check
2336 * expiration/value only when continuing to use the same ESS. */
2337 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2338 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2339 /* Pregenerated addresses do not expire but their value
2340 * might have changed, so let's check that. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002341 if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
Sunil Ravi77d572f2023-01-17 23:58:31 +00002342 return 0;
2343 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2344 wpa_s->last_mac_addr_change.usec != 0) &&
2345 !os_reltime_expired(
2346 &now,
2347 &wpa_s->last_mac_addr_change,
2348 wpa_s->conf->rand_addr_lifetime)) {
2349 wpa_msg(wpa_s, MSG_DEBUG,
2350 "Previously selected random MAC address has not yet expired");
2351 return 0;
2352 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002353 }
2354
2355 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002356 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002357 if (random_mac_addr(addr) < 0)
2358 return -1;
2359 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002360 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002361 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2362 if (random_mac_addr_keep_oui(addr) < 0)
2363 return -1;
2364 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002365 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2366 if (!ssid) {
2367 wpa_msg(wpa_s, MSG_INFO,
2368 "Invalid 'ssid' for address policy 3");
2369 return -1;
2370 }
2371 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2372 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002373 default:
2374 return -1;
2375 }
2376
2377 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2378 wpa_msg(wpa_s, MSG_INFO,
2379 "Failed to set random MAC address");
2380 return -1;
2381 }
2382
2383 os_get_reltime(&wpa_s->last_mac_addr_change);
2384 wpa_s->mac_addr_changed = 1;
2385 wpa_s->last_mac_addr_style = style;
2386
2387 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2388 wpa_msg(wpa_s, MSG_INFO,
2389 "Could not update MAC address information");
2390 return -1;
2391 }
2392
2393 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2394 MAC2STR(addr));
2395
Sunil Ravi77d572f2023-01-17 23:58:31 +00002396 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002397}
2398
2399
2400int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2401{
2402 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2403 !wpa_s->conf->preassoc_mac_addr)
2404 return 0;
2405
Sunil Ravi77d572f2023-01-17 23:58:31 +00002406 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2407 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002408}
2409
2410
Sunil Ravi036cec52023-03-29 11:35:17 -07002411void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2412 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002413{
2414#ifdef CONFIG_SAE
2415 int *groups = conf->sae_groups;
2416 int default_groups[] = { 19, 20, 21, 0 };
2417 const char *password;
2418
2419 if (!groups || groups[0] <= 0)
2420 groups = default_groups;
2421
2422 password = ssid->sae_password;
2423 if (!password)
2424 password = ssid->passphrase;
2425
Hai Shalom899fcc72020-10-19 14:38:18 -07002426 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002427 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002428 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002429 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002430 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002431 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002432 /* PT derivation not needed */
2433 sae_deinit_pt(ssid->pt);
2434 ssid->pt = NULL;
2435 return;
2436 }
2437
2438 if (ssid->pt)
2439 return; /* PT already derived */
2440 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2441 (const u8 *) password, os_strlen(password),
2442 ssid->sae_password_id);
2443#endif /* CONFIG_SAE */
2444}
2445
2446
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002447static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2448{
2449#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2450 os_free(wpa_s->sme.sae_rejected_groups);
2451 wpa_s->sme.sae_rejected_groups = NULL;
2452#ifdef CONFIG_TESTING_OPTIONS
2453 if (wpa_s->extra_sae_rejected_groups) {
2454 int i, *groups = wpa_s->extra_sae_rejected_groups;
2455
2456 for (i = 0; groups[i]; i++) {
2457 wpa_printf(MSG_DEBUG,
2458 "TESTING: Indicate rejection of an extra SAE group %d",
2459 groups[i]);
2460 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2461 groups[i]);
2462 }
2463 }
2464#endif /* CONFIG_TESTING_OPTIONS */
2465#endif /* CONFIG_SAE && CONFIG_SME */
2466}
2467
2468
Hai Shalom60840252021-02-19 19:02:11 -08002469int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2470{
2471 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2472 wpa_msg(wpa_s, MSG_INFO,
2473 "Could not restore permanent MAC address");
2474 return -1;
2475 }
2476 wpa_s->mac_addr_changed = 0;
2477 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2478 wpa_msg(wpa_s, MSG_INFO,
2479 "Could not update MAC address information");
2480 return -1;
2481 }
2482 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2483 return 0;
2484}
2485
2486
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002487static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489/**
2490 * wpa_supplicant_associate - Request association
2491 * @wpa_s: Pointer to wpa_supplicant data
2492 * @bss: Scan results for the selected BSS, or %NULL if not available
2493 * @ssid: Configuration data for the selected network
2494 *
2495 * This function is used to request %wpa_supplicant to associate with a BSS.
2496 */
2497void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2498 struct wpa_bss *bss, struct wpa_ssid *ssid)
2499{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002500 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002501 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002502
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002503 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002504 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002505
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002506 /*
2507 * If we are starting a new connection, any previously pending EAPOL
2508 * RX cannot be valid anymore.
2509 */
2510 wpabuf_free(wpa_s->pending_eapol_rx);
2511 wpa_s->pending_eapol_rx = NULL;
2512
Sunil Ravi77d572f2023-01-17 23:58:31 +00002513 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002514 rand_style = wpa_s->conf->mac_addr;
2515 else
2516 rand_style = ssid->mac_addr;
2517
Sunil Ravia04bd252022-05-02 22:54:18 -07002518 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002519 wpa_s->multi_ap_ie = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002520#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002521 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002522#endif /* CONFIG_NO_WMM_AC */
2523#ifdef CONFIG_WNM
2524 wpa_s->wnm_mode = 0;
2525#endif /* CONFIG_WNM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002526 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002527 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002528#ifdef CONFIG_TESTING_OPTIONS
2529 wpa_s->testing_resend_assoc = 0;
2530#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002531
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002532 if (wpa_s->last_ssid == ssid) {
2533 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002534 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002535 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002536#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002537 wmm_ac_save_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002538#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002539 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002540 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2541 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002542 }
Hai Shalomc3565922019-10-28 11:58:20 -07002543 } else {
2544#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002545 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002546#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002547 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002548#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002549 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002550#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002551
Sunil Ravi77d572f2023-01-17 23:58:31 +00002552 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2553 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2554
2555 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002556 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002557 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2558 status > 0) /* MAC changed */
2559 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2560 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2561 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002562 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002563 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002564 }
2565 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566
2567#ifdef CONFIG_IBSS_RSN
2568 ibss_rsn_deinit(wpa_s->ibss_rsn);
2569 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002570#else /* CONFIG_IBSS_RSN */
2571 if (ssid->mode == WPAS_MODE_IBSS &&
2572 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2573 wpa_msg(wpa_s, MSG_INFO,
2574 "IBSS RSN not supported in the build");
2575 return;
2576 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577#endif /* CONFIG_IBSS_RSN */
2578
2579 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2580 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2581#ifdef CONFIG_AP
2582 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2583 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2584 "mode");
2585 return;
2586 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002587 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2588 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302589 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2590 ssid->mode == WPAS_MODE_P2P_GO) {
2591 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002592 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302593 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002594 return;
2595 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596 wpa_s->current_bss = bss;
2597#else /* CONFIG_AP */
2598 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2599 "the build");
2600#endif /* CONFIG_AP */
2601 return;
2602 }
2603
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002604 if (ssid->mode == WPAS_MODE_MESH) {
2605#ifdef CONFIG_MESH
2606 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2607 wpa_msg(wpa_s, MSG_INFO,
2608 "Driver does not support mesh mode");
2609 return;
2610 }
2611 if (bss)
2612 ssid->frequency = bss->freq;
2613 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002614 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002615 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2616 return;
2617 }
2618 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002619#else /* CONFIG_MESH */
2620 wpa_msg(wpa_s, MSG_ERROR,
2621 "mesh mode support not included in the build");
2622#endif /* CONFIG_MESH */
2623 return;
2624 }
2625
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002626 /*
2627 * Set WPA state machine configuration to match the selected network now
2628 * so that the information is available before wpas_start_assoc_cb()
2629 * gets called. This is needed at least for RSN pre-authentication where
2630 * candidate APs are added to a list based on scan result processing
2631 * before completion of the first association.
2632 */
2633 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2634
2635#ifdef CONFIG_DPP
2636 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2637 return;
2638#endif /* CONFIG_DPP */
2639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640#ifdef CONFIG_TDLS
2641 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002642 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643#endif /* CONFIG_TDLS */
2644
Hai Shalomc3565922019-10-28 11:58:20 -07002645#ifdef CONFIG_MBO
2646 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2647#endif /* CONFIG_MBO */
2648
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002650 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 sme_authenticate(wpa_s, bss, ssid);
2652 return;
2653 }
2654
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002655 if (wpa_s->connect_work) {
2656 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2657 return;
2658 }
2659
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002660 if (radio_work_pending(wpa_s, "connect")) {
2661 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2662 return;
2663 }
2664
Dmitry Shmidt29333592017-01-09 12:27:11 -08002665#ifdef CONFIG_SME
2666 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2667 /* Clear possibly set auth_alg, if any, from last attempt. */
2668 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2669 }
2670#endif /* CONFIG_SME */
2671
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002672 wpas_abort_ongoing_scan(wpa_s);
2673
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002674 cwork = os_zalloc(sizeof(*cwork));
2675 if (cwork == NULL)
2676 return;
2677
2678 cwork->bss = bss;
2679 cwork->ssid = ssid;
2680
2681 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2682 wpas_start_assoc_cb, cwork) < 0) {
2683 os_free(cwork);
2684 }
2685}
2686
2687
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002688static int bss_is_ibss(struct wpa_bss *bss)
2689{
2690 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2691 IEEE80211_CAP_IBSS;
2692}
2693
2694
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002695static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2696 const struct wpa_ssid *ssid)
2697{
2698 enum hostapd_hw_mode hw_mode;
2699 struct hostapd_hw_modes *mode = NULL;
2700 u8 channel;
2701 int i;
2702
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002703 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2704 if (hw_mode == NUM_HOSTAPD_MODES)
2705 return 0;
2706 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2707 if (wpa_s->hw.modes[i].mode == hw_mode) {
2708 mode = &wpa_s->hw.modes[i];
2709 break;
2710 }
2711 }
2712
2713 if (!mode)
2714 return 0;
2715
2716 return mode->vht_capab != 0;
2717}
2718
2719
Hai Shalomc1a21442022-02-04 13:43:00 -08002720static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2721{
2722 int i;
2723
2724 for (i = channel; i < channel + 16; i += 4) {
2725 struct hostapd_channel_data *chan;
2726
2727 chan = hw_get_channel_chan(mode, i, NULL);
2728 if (!chan ||
2729 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2730 return false;
2731 }
2732
2733 return true;
2734}
2735
2736
Sunil Ravi036cec52023-03-29 11:35:17 -07002737static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2738 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002739{
Sunil Ravi036cec52023-03-29 11:35:17 -07002740 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002741
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002742 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2743 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2744
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002745 if (!bss_is_ibss(bss))
2746 continue;
2747
2748 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002749 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2750 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002751 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002752 return NULL;
2753}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002754
Sunil Ravi036cec52023-03-29 11:35:17 -07002755
2756static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2757 const struct wpa_ssid *ssid,
2758 struct hostapd_hw_modes *mode)
2759{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002760 /* For IBSS check HT_IBSS flag */
2761 if (ssid->mode == WPAS_MODE_IBSS &&
2762 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002763 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002764
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002765 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2766 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2767 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2768 wpa_printf(MSG_DEBUG,
2769 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002770 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002771 }
2772
Sunil Ravi036cec52023-03-29 11:35:17 -07002773 if (!ht_supported(mode))
2774 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002775
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002776#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002777 if (ssid->disable_ht)
2778 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002779#endif /* CONFIG_HT_OVERRIDES */
2780
Sunil Ravi036cec52023-03-29 11:35:17 -07002781 return true;
2782}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002783
Sunil Ravi036cec52023-03-29 11:35:17 -07002784
2785static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2786 const struct wpa_ssid *ssid,
2787 struct hostapd_hw_modes *mode)
2788{
2789 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2790 return false;
2791
2792 if (!drv_supports_vht(wpa_s, ssid))
2793 return false;
2794
2795 /* For IBSS check VHT_IBSS flag */
2796 if (ssid->mode == WPAS_MODE_IBSS &&
2797 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2798 return false;
2799
2800 if (!vht_supported(mode))
2801 return false;
2802
2803#ifdef CONFIG_VHT_OVERRIDES
2804 if (ssid->disable_vht)
2805 return false;
2806#endif /* CONFIG_VHT_OVERRIDES */
2807
2808 return true;
2809}
2810
2811
2812static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2813 const struct wpa_ssid *ssid,
2814 const struct hostapd_hw_modes *mode,
2815 int ieee80211_mode)
2816{
Hai Shalomfdcde762020-04-02 11:19:20 -07002817#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002818 if (ssid->disable_he)
2819 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002820#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002821
Sunil Ravi036cec52023-03-29 11:35:17 -07002822 switch (mode->mode) {
2823 case HOSTAPD_MODE_IEEE80211G:
2824 case HOSTAPD_MODE_IEEE80211B:
2825 case HOSTAPD_MODE_IEEE80211A:
2826 return mode->he_capab[ieee80211_mode].he_supported;
2827 default:
2828 return false;
2829 }
2830}
2831
2832
2833static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2834 const struct wpa_ssid *ssid,
2835 const struct hostapd_hw_modes *mode,
2836 int ieee80211_mode)
2837{
2838 if (ssid->disable_eht)
2839 return false;
2840
2841 switch(mode->mode) {
2842 case HOSTAPD_MODE_IEEE80211G:
2843 case HOSTAPD_MODE_IEEE80211B:
2844 case HOSTAPD_MODE_IEEE80211A:
2845 return mode->eht_capab[ieee80211_mode].eht_supported;
2846 default:
2847 return false;
2848 }
2849}
2850
2851
2852static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2853 const struct wpa_ssid *ssid,
2854 struct hostapd_hw_modes *mode,
2855 struct hostapd_freq_params *freq,
2856 int obss_scan) {
2857 int chan_idx;
2858 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2859 int i, res;
2860 unsigned int j;
2861 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002862 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2863 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002864 };
2865 int ht40 = -1;
2866
2867 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002868 return;
2869
2870 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2871 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002872 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002873 break;
2874 pri_chan = NULL;
2875 }
2876 if (!pri_chan)
2877 return;
2878
2879 /* Check primary channel flags */
2880 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2881 return;
2882
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002883#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002884 if (ssid->disable_ht40)
2885 return;
2886#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002887
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002888 /* Check/setup HT40+/HT40- */
2889 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002890 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002891 ht40 = 1;
2892 break;
2893 }
2894 }
2895
2896 /* Find secondary channel */
2897 for (i = 0; i < mode->num_channels; i++) {
2898 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002899 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002900 break;
2901 sec_chan = NULL;
2902 }
2903 if (!sec_chan)
2904 return;
2905
2906 /* Check secondary channel flags */
2907 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2908 return;
2909
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002910 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002911 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2912 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002913 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002914 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2915 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002916 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002917 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002918
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002919 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002920 struct wpa_scan_results *scan_res;
2921
Sunil Ravi88611412024-06-28 17:34:56 +00002922 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002923 if (scan_res == NULL) {
2924 /* Back to HT20 */
2925 freq->sec_channel_offset = 0;
2926 return;
2927 }
2928
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002929 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002930 switch (res) {
2931 case 0:
2932 /* Back to HT20 */
2933 freq->sec_channel_offset = 0;
2934 break;
2935 case 1:
2936 /* Configuration allowed */
2937 break;
2938 case 2:
2939 /* Switch pri/sec channels */
2940 freq->freq = hw_get_freq(mode, sec_chan->chan);
2941 freq->sec_channel_offset = -freq->sec_channel_offset;
2942 freq->channel = sec_chan->chan;
2943 break;
2944 default:
2945 freq->sec_channel_offset = 0;
2946 break;
2947 }
2948
2949 wpa_scan_results_free(scan_res);
2950 }
2951
2952 wpa_printf(MSG_DEBUG,
2953 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2954 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002955}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002956
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002957
Sunil Ravi036cec52023-03-29 11:35:17 -07002958static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2959 const struct wpa_ssid *ssid,
2960 struct hostapd_hw_modes *mode,
2961 struct hostapd_freq_params *freq,
2962 int ieee80211_mode, bool is_6ghz) {
2963 static const int bw80[] = {
2964 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2965 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2966 6515, 6595, 6675, 6755, 6835, 6915, 6995
2967 };
2968 static const int bw160[] = {
2969 5955, 6115, 6275, 6435, 6595, 6755, 6915
2970 };
2971 struct hostapd_freq_params vht_freq;
2972 int i;
2973 unsigned int j, k;
2974 int chwidth, seg0, seg1;
2975 u32 vht_caps = 0;
2976 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002977
Sunil Ravi036cec52023-03-29 11:35:17 -07002978 if (!freq->vht_enabled && !freq->he_enabled)
2979 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002980
Hai Shalomc1a21442022-02-04 13:43:00 -08002981 vht_freq = *freq;
2982
Sunil Ravi036cec52023-03-29 11:35:17 -07002983 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2984 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2985 seg1 = 0;
2986 if (freq->sec_channel_offset == 0) {
2987 seg0 = 0;
2988 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2989 if (freq->ht_enabled && !is_6ghz)
2990 goto skip_80mhz;
2991 }
2992 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2993 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002994
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002995 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002996 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2997 if (freq->freq >= bw80[j] &&
2998 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002999 break;
3000 }
3001
Hai Shalomc1a21442022-02-04 13:43:00 -08003002 if (j == ARRAY_SIZE(bw80) ||
3003 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003004 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003005
Sunil Ravi036cec52023-03-29 11:35:17 -07003006 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08003007 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07003008 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003009
Sunil8cd6f4d2022-06-28 18:40:46 +00003010 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003011 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003012 seg1 = 0;
3013
Sunil Ravi036cec52023-03-29 11:35:17 -07003014 /* In 160 MHz, the initial four 20 MHz channels were validated
3015 * above. If 160 MHz is supported, check the remaining four 20 MHz
3016 * channels for the total of 160 MHz bandwidth for 6 GHz.
3017 */
Hai Shalomc1a21442022-02-04 13:43:00 -08003018 if ((mode->he_capab[ieee80211_mode].phy_cap[
3019 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07003020 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
3021 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003022 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
3023 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003024 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003025 seg0 = channel + 14;
3026 break;
3027 }
3028 }
3029 }
3030
Sunil8cd6f4d2022-06-28 18:40:46 +00003031 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003032 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003033 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003034 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003035 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003036 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003037
3038 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3039 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003040 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003041
3042 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003043 struct hostapd_channel_data *chan;
3044
3045 chan = hw_get_channel_chan(mode, i, NULL);
3046 if (!chan)
3047 continue;
3048
3049 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3050 HOSTAPD_CHAN_NO_IR |
3051 HOSTAPD_CHAN_RADAR))
3052 continue;
3053
3054 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003055 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003056 if (!is_6ghz)
3057 vht_caps |=
3058 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3059 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003060 }
3061
Sunil8cd6f4d2022-06-28 18:40:46 +00003062 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003063 break;
3064 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003065 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003066 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003067 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003068 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3069 seg0 = 50;
3070 } else if (freq->freq == 5520) {
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 = 114;
3074 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003075 }
3076
Sunil Ravi036cec52023-03-29 11:35:17 -07003077skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003078 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003079 freq->channel, ssid->enable_edmg,
3080 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003081 freq->vht_enabled, freq->he_enabled,
3082 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003083 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003084 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003085 &mode->he_capab[ieee80211_mode],
Sunil Ravi88611412024-06-28 17:34:56 +00003086 &mode->eht_capab[ieee80211_mode]) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003087 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003088
3089 *freq = vht_freq;
3090
3091 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3092 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003093 return true;
3094}
3095
3096
3097void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3098 const struct wpa_ssid *ssid,
3099 struct hostapd_freq_params *freq)
3100{
3101 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3102 enum hostapd_hw_mode hw_mode;
3103 struct hostapd_hw_modes *mode = NULL;
3104 int i, obss_scan = 1;
3105 u8 channel;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003106 bool is_6ghz, is_24ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003107
3108 freq->freq = ssid->frequency;
3109
3110 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3111 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3112
3113 if (bss) {
3114 wpa_printf(MSG_DEBUG,
3115 "IBSS already found in scan results, adjust control freq: %d",
3116 bss->freq);
3117 freq->freq = bss->freq;
3118 obss_scan = 0;
3119 }
3120 }
3121
3122 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3123 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3124 if (wpa_s->hw.modes[i].mode == hw_mode &&
3125 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3126 NULL) != NULL) {
3127 mode = &wpa_s->hw.modes[i];
3128 break;
3129 }
3130 }
3131
3132 if (!mode)
3133 return;
3134
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003135 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
3136 hw_mode == HOSTAPD_MODE_IEEE80211B;
3137
Sunil Ravi036cec52023-03-29 11:35:17 -07003138 is_6ghz = is_6ghz_freq(freq->freq);
3139
3140 freq->ht_enabled = 0;
3141 freq->vht_enabled = 0;
3142 freq->he_enabled = 0;
3143 freq->eht_enabled = 0;
3144
3145 if (!is_6ghz)
3146 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3147 if (freq->ht_enabled)
3148 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003149 if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003150 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3151 ieee80211_mode);
3152 freq->channel = channel;
3153 /* Setup higher BW only for 5 GHz */
3154 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3155 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3156 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3157 ieee80211_mode, is_6ghz))
3158 freq->he_enabled = freq->vht_enabled = false;
3159 }
3160
3161 if (freq->he_enabled)
3162 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3163 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003164}
3165
3166
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003167#ifdef CONFIG_FILS
3168static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3169 size_t ie_buf_len)
3170{
3171 struct fils_hlp_req *req;
3172 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3173 const u8 *pos;
3174 u8 *buf = ie_buf;
3175
3176 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3177 list) {
3178 rem_len = ie_buf_len - ie_len;
3179 pos = wpabuf_head(req->pkt);
3180 hdr_len = 1 + 2 * ETH_ALEN + 6;
3181 hlp_len = wpabuf_len(req->pkt);
3182
3183 if (rem_len < 2 + hdr_len + hlp_len) {
3184 wpa_printf(MSG_ERROR,
3185 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3186 (unsigned long) rem_len,
3187 (unsigned long) (2 + hdr_len + hlp_len));
3188 break;
3189 }
3190
3191 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3192 /* Element ID */
3193 *buf++ = WLAN_EID_EXTENSION;
3194 /* Length */
3195 *buf++ = len;
3196 /* Element ID Extension */
3197 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3198 /* Destination MAC address */
3199 os_memcpy(buf, req->dst, ETH_ALEN);
3200 buf += ETH_ALEN;
3201 /* Source MAC address */
3202 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3203 buf += ETH_ALEN;
3204 /* LLC/SNAP Header */
3205 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3206 buf += 6;
3207 /* HLP Packet */
3208 os_memcpy(buf, pos, len - hdr_len);
3209 buf += len - hdr_len;
3210 pos += len - hdr_len;
3211
3212 hlp_len -= len - hdr_len;
3213 ie_len += 2 + len;
3214 rem_len -= 2 + len;
3215
3216 while (hlp_len) {
3217 len = (hlp_len > 255) ? 255 : hlp_len;
3218 if (rem_len < 2 + len)
3219 break;
3220 *buf++ = WLAN_EID_FRAGMENT;
3221 *buf++ = len;
3222 os_memcpy(buf, pos, len);
3223 buf += len;
3224 pos += len;
3225
3226 hlp_len -= len;
3227 ie_len += 2 + len;
3228 rem_len -= 2 + len;
3229 }
3230 }
3231
3232 return ie_len;
3233}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003234
3235
3236int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3237{
3238 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3239 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3240 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3241 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3242}
3243
3244
3245int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3246{
3247#ifdef CONFIG_FILS_SK_PFS
3248 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3249 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3250#else /* CONFIG_FILS_SK_PFS */
3251 return 0;
3252#endif /* CONFIG_FILS_SK_PFS */
3253}
3254
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003255#endif /* CONFIG_FILS */
3256
3257
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003258bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3259{
3260 const u8 *wfa_capa;
3261
3262 if (!bss)
3263 return false;
3264
3265 /* Get WFA capability from Beacon or Probe Response frame elements */
3266 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3267 if (!wfa_capa)
3268 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3269 bss, WFA_CAPA_IE_VENDOR_TYPE);
3270
3271 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3272 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3273 /* AP does not enable QM non EHT traffic description policy */
3274 return false;
3275 }
3276
3277 return true;
3278}
3279
3280
Hai Shalomc1a21442022-02-04 13:43:00 -08003281static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3282 struct wpa_bss *bss,
3283 u8 *wpa_ie, size_t wpa_ie_len,
3284 size_t max_wpa_ie_len)
3285{
3286 struct wpabuf *wfa_ie = NULL;
3287 u8 wfa_capa[1];
3288 size_t wfa_ie_len, buf_len;
3289
3290 os_memset(wfa_capa, 0, sizeof(wfa_capa));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003291#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003292 if (wpa_s->enable_dscp_policy_capa)
3293 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003294#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003295
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003296 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3297 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3298
Hai Shalomc1a21442022-02-04 13:43:00 -08003299 if (!wfa_capa[0])
3300 return wpa_ie_len;
3301
3302 /* Wi-Fi Alliance element */
3303 buf_len = 1 + /* Element ID */
3304 1 + /* Length */
3305 3 + /* OUI */
3306 1 + /* OUI Type */
3307 1 + /* Capabilities Length */
3308 sizeof(wfa_capa); /* Capabilities */
3309 wfa_ie = wpabuf_alloc(buf_len);
3310 if (!wfa_ie)
3311 return wpa_ie_len;
3312
3313 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3314 wpabuf_put_u8(wfa_ie, buf_len - 2);
3315 wpabuf_put_be24(wfa_ie, OUI_WFA);
3316 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3317 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3318 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3319
3320 wfa_ie_len = wpabuf_len(wfa_ie);
3321 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3322 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3323 wfa_ie);
3324 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3325 wfa_ie_len);
3326 wpa_ie_len += wfa_ie_len;
3327 }
3328
3329 wpabuf_free(wfa_ie);
3330 return wpa_ie_len;
3331}
3332
3333
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003334static u8 * wpas_populate_assoc_ies(
3335 struct wpa_supplicant *wpa_s,
3336 struct wpa_bss *bss, struct wpa_ssid *ssid,
3337 struct wpa_driver_associate_params *params,
3338 enum wpa_drv_update_connect_params_mask *mask)
3339{
3340 u8 *wpa_ie;
3341 size_t max_wpa_ie_len = 500;
3342 size_t wpa_ie_len;
3343 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003344#ifdef CONFIG_MBO
3345 const u8 *mbo_ie;
3346#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303347#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3348 int pmksa_cached = 0;
3349#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003350#ifdef CONFIG_FILS
3351 const u8 *realm, *username, *rrk;
3352 size_t realm_len, username_len, rrk_len;
3353 u16 next_seq_num;
3354 struct fils_hlp_req *req;
3355
3356 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3357 list) {
3358 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3359 2 + 2 * wpabuf_len(req->pkt) / 255;
3360 }
3361#endif /* CONFIG_FILS */
3362
3363 wpa_ie = os_malloc(max_wpa_ie_len);
3364 if (!wpa_ie) {
3365 wpa_printf(MSG_ERROR,
3366 "Failed to allocate connect IE buffer for %lu bytes",
3367 (unsigned long) max_wpa_ie_len);
3368 return NULL;
3369 }
3370
3371 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3372 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3373 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3374 int try_opportunistic;
3375 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003376 const u8 *addr = bss->bssid;
3377
Sunil Ravi036cec52023-03-29 11:35:17 -07003378 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3379 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3380 !is_zero_ether_addr(bss->mld_addr))
3381 addr = bss->mld_addr;
3382
3383 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3384 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003385 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003386
3387 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3388 wpa_s->conf->okc :
3389 ssid->proactive_key_caching) &&
3390 (ssid->proto & WPA_PROTO_RSN);
3391#ifdef CONFIG_FILS
3392 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3393 cache_id = wpa_bss_get_fils_cache_id(bss);
3394#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003395 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003396 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003397 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003398 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303399#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3400 pmksa_cached = 1;
3401#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003402 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003403 wpa_ie_len = max_wpa_ie_len;
3404 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003405 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003406 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3407 "key management and encryption suites");
3408 os_free(wpa_ie);
3409 return NULL;
3410 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003411#ifdef CONFIG_HS20
3412 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3413 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3414 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3415 wpa_ie_len = max_wpa_ie_len;
3416 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003417 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003418 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3419 "key management and encryption suites");
3420 os_free(wpa_ie);
3421 return NULL;
3422 }
3423#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003424 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3425 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3426 /*
3427 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3428 * use non-WPA since the scan results did not indicate that the
3429 * AP is using WPA or WPA2.
3430 */
3431 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3432 wpa_ie_len = 0;
3433 wpa_s->wpa_proto = 0;
3434 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3435 wpa_ie_len = max_wpa_ie_len;
3436 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003437 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003438 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3439 "key management and encryption suites (no "
3440 "scan results)");
3441 os_free(wpa_ie);
3442 return NULL;
3443 }
3444#ifdef CONFIG_WPS
3445 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3446 struct wpabuf *wps_ie;
3447 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3448 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3449 wpa_ie_len = wpabuf_len(wps_ie);
3450 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3451 } else
3452 wpa_ie_len = 0;
3453 wpabuf_free(wps_ie);
3454 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3455 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3456 params->wps = WPS_MODE_PRIVACY;
3457 else
3458 params->wps = WPS_MODE_OPEN;
3459 wpa_s->wpa_proto = 0;
3460#endif /* CONFIG_WPS */
3461 } else {
3462 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3463 wpa_ie_len = 0;
3464 wpa_s->wpa_proto = 0;
3465 }
3466
3467#ifdef IEEE8021X_EAPOL
3468 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3469 if (ssid->leap) {
3470 if (ssid->non_leap == 0)
3471 algs = WPA_AUTH_ALG_LEAP;
3472 else
3473 algs |= WPA_AUTH_ALG_LEAP;
3474 }
3475 }
3476
3477#ifdef CONFIG_FILS
3478 /* Clear FILS association */
3479 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3480
3481 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3482 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3483 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3484 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003485 &next_seq_num, &rrk, &rrk_len) == 0 &&
3486 (!wpa_s->last_con_fail_realm ||
3487 wpa_s->last_con_fail_realm_len != realm_len ||
3488 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003489 algs = WPA_AUTH_ALG_FILS;
3490 params->fils_erp_username = username;
3491 params->fils_erp_username_len = username_len;
3492 params->fils_erp_realm = realm;
3493 params->fils_erp_realm_len = realm_len;
3494 params->fils_erp_next_seq_num = next_seq_num;
3495 params->fils_erp_rrk = rrk;
3496 params->fils_erp_rrk_len = rrk_len;
3497
3498 if (mask)
3499 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303500 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3501 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3502 pmksa_cached) {
3503 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003504 }
3505#endif /* CONFIG_FILS */
3506#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003507#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003508 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003509 algs = WPA_AUTH_ALG_SAE;
3510#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003511
3512 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3513 if (ssid->auth_alg) {
3514 algs = ssid->auth_alg;
3515 wpa_dbg(wpa_s, MSG_DEBUG,
3516 "Overriding auth_alg selection: 0x%x", algs);
3517 }
3518
Hai Shalom5f92bc92019-04-18 11:54:11 -07003519#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303520 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003521 wpa_dbg(wpa_s, MSG_DEBUG,
3522 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3523 algs = WPA_AUTH_ALG_OPEN;
3524 }
3525#endif /* CONFIG_SAE */
3526
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003527#ifdef CONFIG_P2P
3528 if (wpa_s->global->p2p) {
3529 u8 *pos;
3530 size_t len;
3531 int res;
3532 pos = wpa_ie + wpa_ie_len;
3533 len = max_wpa_ie_len - wpa_ie_len;
3534 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3535 ssid->p2p_group);
3536 if (res >= 0)
3537 wpa_ie_len += res;
3538 }
3539
3540 wpa_s->cross_connect_disallowed = 0;
3541 if (bss) {
3542 struct wpabuf *p2p;
3543 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3544 if (p2p) {
3545 wpa_s->cross_connect_disallowed =
3546 p2p_get_cross_connect_disallowed(p2p);
3547 wpabuf_free(p2p);
3548 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3549 "connection",
3550 wpa_s->cross_connect_disallowed ?
3551 "disallows" : "allows");
3552 }
3553 }
3554
3555 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3556#endif /* CONFIG_P2P */
3557
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003558#ifndef CONFIG_NO_RRM
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003559 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003560 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003561 wpa_ie + wpa_ie_len,
3562 max_wpa_ie_len -
3563 wpa_ie_len);
3564 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003565#endif /* CONFIG_NO_RRM */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003566
3567 /*
3568 * Workaround: Add Extended Capabilities element only if the AP
3569 * included this element in Beacon/Probe Response frames. Some older
3570 * APs seem to have interoperability issues if this element is
3571 * included, so while the standard may require us to include the
3572 * element in all cases, it is justifiable to skip it to avoid
3573 * interoperability issues.
3574 */
3575 if (ssid->p2p_group)
3576 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3577 else
3578 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3579
3580 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3581 u8 ext_capab[18];
3582 int ext_capab_len;
3583 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003584 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003585 if (ext_capab_len > 0 &&
3586 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3587 u8 *pos = wpa_ie;
3588 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3589 pos += 2 + pos[1];
3590 os_memmove(pos + ext_capab_len, pos,
3591 wpa_ie_len - (pos - wpa_ie));
3592 wpa_ie_len += ext_capab_len;
3593 os_memcpy(pos, ext_capab, ext_capab_len);
3594 }
3595 }
3596
3597#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003598 if (is_hs20_network(wpa_s, ssid, bss)
3599#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3600 && is_hs20_config(wpa_s)
3601#endif /* ANDROID */
3602 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003603 struct wpabuf *hs20;
3604
Roshan Pius3a1667e2018-07-03 15:17:14 -07003605 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003606 if (hs20) {
3607 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3608 size_t len;
3609
Hai Shalom74f70d42019-02-11 14:42:39 -08003610 wpas_hs20_add_indication(hs20, pps_mo_id,
3611 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003612 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003613 len = max_wpa_ie_len - wpa_ie_len;
3614 if (wpabuf_len(hs20) <= len) {
3615 os_memcpy(wpa_ie + wpa_ie_len,
3616 wpabuf_head(hs20), wpabuf_len(hs20));
3617 wpa_ie_len += wpabuf_len(hs20);
3618 }
3619 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620 }
3621 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003622 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003623#endif /* CONFIG_HS20 */
3624
3625 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3626 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3627 size_t len;
3628
3629 len = max_wpa_ie_len - wpa_ie_len;
3630 if (wpabuf_len(buf) <= len) {
3631 os_memcpy(wpa_ie + wpa_ie_len,
3632 wpabuf_head(buf), wpabuf_len(buf));
3633 wpa_ie_len += wpabuf_len(buf);
3634 }
3635 }
3636
3637#ifdef CONFIG_FST
3638 if (wpa_s->fst_ies) {
3639 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3640
3641 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3642 os_memcpy(wpa_ie + wpa_ie_len,
3643 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3644 wpa_ie_len += fst_ies_len;
3645 }
3646 }
3647#endif /* CONFIG_FST */
3648
3649#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003650 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003651 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003652 int len;
3653
3654 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003655 max_wpa_ie_len - wpa_ie_len,
3656 !!mbo_attr_from_mbo_ie(mbo_ie,
3657 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003658 if (len >= 0)
3659 wpa_ie_len += len;
3660 }
3661#endif /* CONFIG_MBO */
3662
3663#ifdef CONFIG_FILS
3664 if (algs == WPA_AUTH_ALG_FILS) {
3665 size_t len;
3666
3667 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3668 max_wpa_ie_len - wpa_ie_len);
3669 wpa_ie_len += len;
3670 }
3671#endif /* CONFIG_FILS */
3672
3673#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003674#ifdef CONFIG_TESTING_OPTIONS
3675 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3676 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3677 } else
3678#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003679 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003680 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3681 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003682 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003683 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003684
Roshan Pius3a1667e2018-07-03 15:17:14 -07003685 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003686 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003687 } else if (wpa_s->assoc_status_code ==
3688 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003689 if (wpa_s->last_owe_group == 19)
3690 group = 20;
3691 else if (wpa_s->last_owe_group == 20)
3692 group = 21;
3693 else
3694 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003695 } else {
3696 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003697 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003698
Roshan Pius3a1667e2018-07-03 15:17:14 -07003699 wpa_s->last_owe_group = group;
3700 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003701 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3702 if (owe_ie &&
3703 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3704 os_memcpy(wpa_ie + wpa_ie_len,
3705 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3706 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003707 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003708 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003709 }
3710#endif /* CONFIG_OWE */
3711
Hai Shalom021b0b52019-04-10 11:17:58 -07003712#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003713 if (DPP_VERSION > 1 &&
3714 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003715 ssid->dpp_netaccesskey &&
3716 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003717 struct rsn_pmksa_cache_entry *pmksa;
3718
3719 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3720 if (!pmksa || !pmksa->dpp_pfs)
3721 goto pfs_fail;
3722
Hai Shalom021b0b52019-04-10 11:17:58 -07003723 dpp_pfs_free(wpa_s->dpp_pfs);
3724 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3725 ssid->dpp_netaccesskey_len);
3726 if (!wpa_s->dpp_pfs) {
3727 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3728 /* Try to continue without PFS */
3729 goto pfs_fail;
3730 }
3731 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3732 max_wpa_ie_len - wpa_ie_len) {
3733 os_memcpy(wpa_ie + wpa_ie_len,
3734 wpabuf_head(wpa_s->dpp_pfs->ie),
3735 wpabuf_len(wpa_s->dpp_pfs->ie));
3736 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3737 }
3738 }
3739pfs_fail:
3740#endif /* CONFIG_DPP2 */
3741
Roshan Pius3a1667e2018-07-03 15:17:14 -07003742#ifdef CONFIG_IEEE80211R
3743 /*
3744 * Add MDIE under these conditions: the network profile allows FT,
3745 * the AP supports FT, and the mobility domain ID matches.
3746 */
3747 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3748 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3749
3750 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3751 size_t len = 0;
3752 const u8 *md = mdie + 2;
3753 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3754
3755 if (os_memcmp(md, wpa_md,
3756 MOBILITY_DOMAIN_ID_LEN) == 0) {
3757 /* Add mobility domain IE */
3758 len = wpa_ft_add_mdie(
3759 wpa_s->wpa, wpa_ie + wpa_ie_len,
3760 max_wpa_ie_len - wpa_ie_len, mdie);
3761 wpa_ie_len += len;
3762 }
3763#ifdef CONFIG_SME
3764 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003765 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003766 wpa_dbg(wpa_s, MSG_DEBUG,
3767 "SME: Trying to use FT over-the-air");
3768 algs |= WPA_AUTH_ALG_FT;
3769 }
3770#endif /* CONFIG_SME */
3771 }
3772 }
3773#endif /* CONFIG_IEEE80211R */
3774
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003775#ifdef CONFIG_TESTING_OPTIONS
3776 if (wpa_s->rsnxe_override_assoc &&
3777 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3778 max_wpa_ie_len - wpa_ie_len) {
3779 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3780 os_memcpy(wpa_ie + wpa_ie_len,
3781 wpabuf_head(wpa_s->rsnxe_override_assoc),
3782 wpabuf_len(wpa_s->rsnxe_override_assoc));
3783 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3784 } else
3785#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003786 if (wpa_s->rsnxe_len > 0 &&
3787 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3788 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3789 wpa_ie_len += wpa_s->rsnxe_len;
3790 }
3791
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003792#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003793#ifdef CONFIG_TESTING_OPTIONS
3794 if (wpa_s->disable_mscs_support)
3795 goto mscs_end;
3796#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003797 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3798 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003799 struct wpabuf *mscs_ie;
3800 size_t mscs_ie_len, buf_len;
3801
Hai Shalom899fcc72020-10-19 14:38:18 -07003802 buf_len = 3 + /* MSCS descriptor IE header */
3803 1 + /* Request type */
3804 2 + /* User priority control */
3805 4 + /* Stream timeout */
3806 3 + /* TCLAS Mask IE header */
3807 wpa_s->robust_av.frame_classifier_len;
3808 mscs_ie = wpabuf_alloc(buf_len);
3809 if (!mscs_ie) {
3810 wpa_printf(MSG_INFO,
3811 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003812 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003813 }
3814
3815 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3816 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3817 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3818 mscs_ie_len = wpabuf_len(mscs_ie);
3819 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3820 mscs_ie_len);
3821 wpa_ie_len += mscs_ie_len;
3822 }
3823
3824 wpabuf_free(mscs_ie);
3825 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003826mscs_end:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003827#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003828
3829 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3830 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003831
Hai Shalom74f70d42019-02-11 14:42:39 -08003832 if (ssid->multi_ap_backhaul_sta) {
3833 size_t multi_ap_ie_len;
3834
3835 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3836 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi88611412024-06-28 17:34:56 +00003837 MULTI_AP_BACKHAUL_STA);
Hai Shalom74f70d42019-02-11 14:42:39 -08003838 if (multi_ap_ie_len == 0) {
3839 wpa_printf(MSG_ERROR,
3840 "Multi-AP: Failed to build Multi-AP IE");
3841 os_free(wpa_ie);
3842 return NULL;
3843 }
3844 wpa_ie_len += multi_ap_ie_len;
3845 }
3846
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003847 params->wpa_ie = wpa_ie;
3848 params->wpa_ie_len = wpa_ie_len;
3849 params->auth_alg = algs;
3850 if (mask)
3851 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3852
3853 return wpa_ie;
3854}
3855
3856
Hai Shalomc3565922019-10-28 11:58:20 -07003857#ifdef CONFIG_OWE
3858static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3859{
3860 struct wpa_driver_associate_params params;
3861 u8 *wpa_ie;
3862
3863 os_memset(&params, 0, sizeof(params));
3864 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3865 wpa_s->current_ssid, &params, NULL);
3866 if (!wpa_ie)
3867 return;
3868
3869 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3870 os_free(wpa_ie);
3871}
3872#endif /* CONFIG_OWE */
3873
3874
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003875#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3876static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3877{
3878 struct wpa_driver_associate_params params;
3879 enum wpa_drv_update_connect_params_mask mask = 0;
3880 u8 *wpa_ie;
3881
3882 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3883 return; /* nothing to do */
3884
3885 os_memset(&params, 0, sizeof(params));
3886 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3887 wpa_s->current_ssid, &params, &mask);
3888 if (!wpa_ie)
3889 return;
3890
Hai Shalomc1a21442022-02-04 13:43:00 -08003891 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3892 wpa_s->auth_alg = params.auth_alg;
3893 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003894 }
3895
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003896 os_free(wpa_ie);
3897}
3898#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3899
3900
Hai Shalomc3565922019-10-28 11:58:20 -07003901static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3902{
3903 if (!edmg_ie || edmg_ie[1] < 6)
3904 return 0;
3905 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3906}
3907
3908
3909static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3910{
3911 if (!edmg_ie || edmg_ie[1] < 6)
3912 return 0;
3913 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3914}
3915
3916
3917/* Returns the intersection of two EDMG configurations.
3918 * Note: The current implementation is limited to CB2 only (CB1 included),
3919 * i.e., the implementation supports up to 2 contiguous channels.
3920 * For supporting non-contiguous (aggregated) channels and for supporting
3921 * CB3 and above, this function will need to be extended.
3922 */
3923static struct ieee80211_edmg_config
3924get_edmg_intersection(struct ieee80211_edmg_config a,
3925 struct ieee80211_edmg_config b,
3926 u8 primary_channel)
3927{
3928 struct ieee80211_edmg_config result;
3929 int i, contiguous = 0;
3930 int max_contiguous = 0;
3931
3932 result.channels = b.channels & a.channels;
3933 if (!result.channels) {
3934 wpa_printf(MSG_DEBUG,
3935 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3936 a.channels, b.channels);
3937 goto fail;
3938 }
3939
3940 if (!(result.channels & BIT(primary_channel - 1))) {
3941 wpa_printf(MSG_DEBUG,
3942 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3943 primary_channel, result.channels);
3944 goto fail;
3945 }
3946
3947 /* Find max contiguous channels */
3948 for (i = 0; i < 6; i++) {
3949 if (result.channels & BIT(i))
3950 contiguous++;
3951 else
3952 contiguous = 0;
3953
3954 if (contiguous > max_contiguous)
3955 max_contiguous = contiguous;
3956 }
3957
3958 /* Assuming AP and STA supports ONLY contiguous channels,
3959 * bw configuration can have value between 4-7.
3960 */
3961 if ((b.bw_config < a.bw_config))
3962 result.bw_config = b.bw_config;
3963 else
3964 result.bw_config = a.bw_config;
3965
3966 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3967 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3968 wpa_printf(MSG_DEBUG,
3969 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3970 max_contiguous);
3971 goto fail;
3972 }
3973
3974 return result;
3975
3976fail:
3977 result.channels = 0;
3978 result.bw_config = 0;
3979 return result;
3980}
3981
3982
3983static struct ieee80211_edmg_config
3984get_supported_edmg(struct wpa_supplicant *wpa_s,
3985 struct hostapd_freq_params *freq,
3986 struct ieee80211_edmg_config request_edmg)
3987{
3988 enum hostapd_hw_mode hw_mode;
3989 struct hostapd_hw_modes *mode = NULL;
3990 u8 primary_channel;
3991
3992 if (!wpa_s->hw.modes)
3993 goto fail;
3994
3995 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3996 if (hw_mode == NUM_HOSTAPD_MODES)
3997 goto fail;
3998
Hai Shalom60840252021-02-19 19:02:11 -08003999 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004000 if (!mode)
4001 goto fail;
4002
4003 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
4004
4005fail:
4006 request_edmg.channels = 0;
4007 request_edmg.bw_config = 0;
4008 return request_edmg;
4009}
4010
4011
Hai Shalom021b0b52019-04-10 11:17:58 -07004012#ifdef CONFIG_MBO
4013void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
4014{
4015 struct wpa_driver_associate_params params;
4016 u8 *wpa_ie;
4017
4018 /*
4019 * Update MBO connect params only in case of change of MBO attributes
4020 * when connected, if the AP support MBO.
4021 */
4022
4023 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
4024 !wpa_s->current_bss ||
4025 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
4026 return;
4027
4028 os_memset(&params, 0, sizeof(params));
4029 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4030 wpa_s->current_ssid, &params, NULL);
4031 if (!wpa_ie)
4032 return;
4033
4034 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4035 os_free(wpa_ie);
4036}
4037#endif /* CONFIG_MBO */
4038
4039
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004040static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4041{
4042 struct wpa_connect_work *cwork = work->ctx;
4043 struct wpa_bss *bss = cwork->bss;
4044 struct wpa_ssid *ssid = cwork->ssid;
4045 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004046 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004047 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004048 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004049 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004050 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004051 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004052#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004053 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004054#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004055 int assoc_failed = 0;
4056 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004057 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004058#ifdef CONFIG_HT_OVERRIDES
4059 struct ieee80211_ht_capabilities htcaps;
4060 struct ieee80211_ht_capabilities htcaps_mask;
4061#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004062#ifdef CONFIG_VHT_OVERRIDES
4063 struct ieee80211_vht_capabilities vhtcaps;
4064 struct ieee80211_vht_capabilities vhtcaps_mask;
4065#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004066
Hai Shalomc1a21442022-02-04 13:43:00 -08004067 wpa_s->roam_in_progress = false;
4068#ifdef CONFIG_WNM
4069 wpa_s->bss_trans_mgmt_in_progress = false;
4070#endif /* CONFIG_WNM */
4071
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004072 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004073 if (work->started) {
4074 wpa_s->connect_work = NULL;
4075
4076 /* cancel possible auth. timeout */
4077 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4078 NULL);
4079 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004080 wpas_connect_work_free(cwork);
4081 return;
4082 }
4083
4084 wpa_s->connect_work = work;
4085
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004086 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4087 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004088 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4089 wpas_connect_work_done(wpa_s);
4090 return;
4091 }
4092
Sunil Ravi640215c2023-06-28 23:08:09 +00004093 /*
4094 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4095 * (for MLO connection) as the previous BSSID for reassociation requests
4096 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4097 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4098 * will be zero.
4099 */
4100 os_memcpy(prev_bssid,
4101 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4102 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004103 os_memset(&params, 0, sizeof(params));
4104 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004105 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004106
4107 /* Starting new association, so clear the possibly used WPA IE from the
4108 * previous association. */
4109 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4110 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4111 wpa_s->rsnxe_len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004112#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom60840252021-02-19 19:02:11 -08004113 wpa_s->mscs_setup_done = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004114#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08004115
4116 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4117 if (!wpa_ie) {
4118 wpas_connect_work_done(wpa_s);
4119 return;
4120 }
4121
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004122 if (bss &&
4123 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124#ifdef CONFIG_IEEE80211R
4125 const u8 *ie, *md = NULL;
4126#endif /* CONFIG_IEEE80211R */
4127 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4128 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4129 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4130 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4131 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4132 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4133 if (bssid_changed)
4134 wpas_notify_bssid_changed(wpa_s);
4135#ifdef CONFIG_IEEE80211R
4136 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4137 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4138 md = ie + 2;
4139 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4140 if (md) {
4141 /* Prepare for the next transition */
4142 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4143 }
4144#endif /* CONFIG_IEEE80211R */
4145#ifdef CONFIG_WPS
4146 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4147 wpa_s->conf->ap_scan == 2 &&
4148 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4149 /* Use ap_scan==1 style network selection to find the network
4150 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004151 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004152 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153 wpa_s->reassociate = 1;
4154 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004155 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156 return;
4157#endif /* CONFIG_WPS */
4158 } else {
4159 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4160 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004161 if (bss)
4162 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4163 else
4164 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004165 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004166 if (!wpa_s->pno)
4167 wpa_supplicant_cancel_sched_scan(wpa_s);
4168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004169 wpa_supplicant_cancel_scan(wpa_s);
4170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4172 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004173 cipher_pairwise = wpa_s->pairwise_cipher;
4174 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004175 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4177 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4178 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4179 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004180#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 if (wpa_set_wep_keys(wpa_s, ssid)) {
4182 use_crypt = 1;
4183 wep_keys_set = 1;
4184 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004185#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004186 }
4187 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4188 use_crypt = 0;
4189
4190#ifdef IEEE8021X_EAPOL
4191 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4192 if ((ssid->eapol_flags &
4193 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4194 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4195 !wep_keys_set) {
4196 use_crypt = 0;
4197 } else {
4198 /* Assume that dynamic WEP-104 keys will be used and
4199 * set cipher suites in order for drivers to expect
4200 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004201 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202 }
4203 }
4204#endif /* IEEE8021X_EAPOL */
4205
4206 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4207 /* Set the key before (and later after) association */
4208 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4209 }
4210
Sunil8cd6f4d2022-06-28 18:40:46 +00004211 /* Set current_ssid before changing state to ASSOCIATING, so that the
4212 * selected SSID is available to wpas_notify_state_changed(). */
4213 old_ssid = wpa_s->current_ssid;
4214 wpa_s->current_ssid = ssid;
4215
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004216 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4217 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004218 params.ssid = bss->ssid;
4219 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004220 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4221 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004222 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4223 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004224 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004225 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004226 ssid->bssid_set,
4227 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004228 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004229 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004230 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004231 params.bssid_hint = bss->bssid;
4232 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004233 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004235 if (ssid->bssid_hint_set)
4236 params.bssid_hint = ssid->bssid_hint;
4237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004238 params.ssid = ssid->ssid;
4239 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004240 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004242
4243 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4244 wpa_s->conf->ap_scan == 2) {
4245 params.bssid = ssid->bssid;
4246 params.fixed_bssid = 1;
4247 }
4248
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004249 /* Initial frequency for IBSS/mesh */
4250 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004251 ssid->frequency > 0 && params.freq.freq == 0)
4252 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004253
4254 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004255 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004256 if (ssid->beacon_int)
4257 params.beacon_int = ssid->beacon_int;
4258 else
4259 params.beacon_int = wpa_s->conf->beacon_int;
4260 }
4261
Hai Shalomc3565922019-10-28 11:58:20 -07004262 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004263 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4264 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004265 else
4266 edmg_ie_oper = NULL;
4267
4268 if (edmg_ie_oper) {
4269 params.freq.edmg.channels =
4270 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4271 params.freq.edmg.bw_config =
4272 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4273 wpa_printf(MSG_DEBUG,
4274 "AP supports EDMG channels 0x%x, bw_config %d",
4275 params.freq.edmg.channels,
4276 params.freq.edmg.bw_config);
4277
4278 /* User may ask for specific EDMG channel for EDMG connection
4279 * (must be supported by AP)
4280 */
4281 if (ssid->edmg_channel) {
4282 struct ieee80211_edmg_config configured_edmg;
4283 enum hostapd_hw_mode hw_mode;
4284 u8 primary_channel;
4285
4286 hw_mode = ieee80211_freq_to_chan(bss->freq,
4287 &primary_channel);
4288 if (hw_mode == NUM_HOSTAPD_MODES)
4289 goto edmg_fail;
4290
4291 hostapd_encode_edmg_chan(ssid->enable_edmg,
4292 ssid->edmg_channel,
4293 primary_channel,
4294 &configured_edmg);
4295
4296 if (ieee802_edmg_is_allowed(params.freq.edmg,
4297 configured_edmg)) {
4298 params.freq.edmg = configured_edmg;
4299 wpa_printf(MSG_DEBUG,
4300 "Use EDMG channel %d for connection",
4301 ssid->edmg_channel);
4302 } else {
4303 edmg_fail:
4304 params.freq.edmg.channels = 0;
4305 params.freq.edmg.bw_config = 0;
4306 wpa_printf(MSG_WARNING,
4307 "EDMG channel %d not supported by AP, fallback to DMG",
4308 ssid->edmg_channel);
4309 }
4310 }
4311
4312 if (params.freq.edmg.channels) {
4313 wpa_printf(MSG_DEBUG,
4314 "EDMG before: channels 0x%x, bw_config %d",
4315 params.freq.edmg.channels,
4316 params.freq.edmg.bw_config);
4317 params.freq.edmg = get_supported_edmg(wpa_s,
4318 &params.freq,
4319 params.freq.edmg);
4320 wpa_printf(MSG_DEBUG,
4321 "EDMG after: channels 0x%x, bw_config %d",
4322 params.freq.edmg.channels,
4323 params.freq.edmg.bw_config);
4324 }
4325 }
4326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004327 params.pairwise_suite = cipher_pairwise;
4328 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004329 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004330 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004331 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004332 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004333 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004335 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004336#ifdef CONFIG_WEP
4337 {
4338 int i;
4339
4340 for (i = 0; i < NUM_WEP_KEYS; i++) {
4341 if (ssid->wep_key_len[i])
4342 params.wep_key[i] = ssid->wep_key[i];
4343 params.wep_key_len[i] = ssid->wep_key_len[i];
4344 }
4345 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004346 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004347#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348
Hai Shalom74f70d42019-02-11 14:42:39 -08004349 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004350#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4351 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004352 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4353 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004354#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4355 defined(CONFIG_DRIVER_NL80211_SYNA)
4356 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4357 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4358 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4359 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304360#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004361 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4362 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4363 (params.allowed_key_mgmts &
4364 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004365#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4366 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004368 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4369 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004370 }
4371
Hai Shalom74f70d42019-02-11 14:42:39 -08004372 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4373 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4374 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4375 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004376 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4377 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004378 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004379
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004380 if (wpa_s->conf->key_mgmt_offload) {
4381 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4382 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004383 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004384 params.key_mgmt_suite ==
4385 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4386 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004387 params.req_key_mgmt_offload =
4388 ssid->proactive_key_caching < 0 ?
4389 wpa_s->conf->okc : ssid->proactive_key_caching;
4390 else
4391 params.req_key_mgmt_offload = 1;
4392
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004393#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4394 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004395 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004396 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4397 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004398#else
4399 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4400 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004401#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4402 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004403 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4404 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004405 }
4406
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004407 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4408 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4409 params.auth_alg = WPA_AUTH_ALG_SAE;
4410 if (ssid->sae_password) {
4411 params.sae_password = ssid->sae_password;
4412 params.sae_password_id = ssid->sae_password_id;
4413 } else if (ssid->passphrase) {
4414 params.passphrase = ssid->passphrase;
4415 }
4416 }
4417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004418 params.drop_unencrypted = use_crypt;
4419
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004420 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004421 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004422 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4423 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004424 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4425 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004426 ie.capabilities &
4427 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4428 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4429 "MFP: require MFP");
4430 params.mgmt_frame_protection =
4431 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004432#ifdef CONFIG_OWE
4433 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4434 !ssid->owe_only) {
4435 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4436#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004437 }
4438 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004439
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004440 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004441
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004442 if (wpa_s->p2pdev->set_sta_uapsd)
4443 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004444 else
4445 params.uapsd = -1;
4446
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004447#ifdef CONFIG_HT_OVERRIDES
4448 os_memset(&htcaps, 0, sizeof(htcaps));
4449 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4450 params.htcaps = (u8 *) &htcaps;
4451 params.htcaps_mask = (u8 *) &htcaps_mask;
4452 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4453#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004454#ifdef CONFIG_VHT_OVERRIDES
4455 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4456 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4457 params.vhtcaps = &vhtcaps;
4458 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004459 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004460#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004461#ifdef CONFIG_HE_OVERRIDES
4462 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4463#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004464 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004465
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004466#ifdef CONFIG_P2P
4467 /*
4468 * If multi-channel concurrency is not supported, check for any
4469 * frequency conflict. In case of any frequency conflict, remove the
4470 * least prioritized connection.
4471 */
4472 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004473 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004474 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004475 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004476 wpa_printf(MSG_DEBUG,
4477 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004478 freq, params.freq.freq);
4479 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004480 wpa_s, params.freq.freq, ssid) < 0) {
4481 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004482 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004483 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004484 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004485 }
4486 }
4487#endif /* CONFIG_P2P */
4488
Dmitry Shmidte4663042016-04-04 10:07:49 -07004489 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004490 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004491 params.prev_bssid = prev_bssid;
4492
Hai Shalom60840252021-02-19 19:02:11 -08004493#ifdef CONFIG_SAE
4494 params.sae_pwe = wpa_s->conf->sae_pwe;
4495#endif /* CONFIG_SAE */
4496
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004497 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004498 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004499 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 if (ret < 0) {
4501 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4502 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004503 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 /*
4505 * The driver is known to mean what is saying, so we
4506 * can stop right here; the association will not
4507 * succeed.
4508 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004509 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
4510 NULL);
Roger Wang4c09cc92020-11-05 18:57:12 +08004511 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004512 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004513 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004514 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4515 return;
4516 }
4517 /* try to continue anyway; new association will be tried again
4518 * after timeout */
4519 assoc_failed = 1;
4520 }
4521
4522 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4523 /* Set the key after the association just in case association
4524 * cleared the previously configured key. */
4525 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4526 /* No need to timeout authentication since there is no key
4527 * management. */
4528 wpa_supplicant_cancel_auth_timeout(wpa_s);
4529 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4530#ifdef CONFIG_IBSS_RSN
4531 } else if (ssid->mode == WPAS_MODE_IBSS &&
4532 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4533 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4534 /*
4535 * RSN IBSS authentication is per-STA and we can disable the
4536 * per-BSSID authentication.
4537 */
4538 wpa_supplicant_cancel_auth_timeout(wpa_s);
4539#endif /* CONFIG_IBSS_RSN */
4540 } else {
4541 /* Timeout for IEEE 802.11 authentication and association */
4542 int timeout = 60;
4543
4544 if (assoc_failed) {
4545 /* give IBSS a bit more time */
4546 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4547 } else if (wpa_s->conf->ap_scan == 1) {
4548 /* give IBSS a bit more time */
4549 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4550 }
4551 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4552 }
4553
Hai Shalomfdcde762020-04-02 11:19:20 -07004554#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004555 if (wep_keys_set &&
4556 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 /* Set static WEP keys again */
4558 wpa_set_wep_keys(wpa_s, ssid);
4559 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004560#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004561
Sunil8cd6f4d2022-06-28 18:40:46 +00004562 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004563 /*
4564 * Do not allow EAP session resumption between different
4565 * network configurations.
4566 */
4567 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4568 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004569
mtk30479d7f89782024-01-24 11:51:43 +08004570 if (!wpas_driver_bss_selection(wpa_s) ||
4571#ifdef CONFIG_P2P
4572 wpa_s->p2p_in_invitation ||
4573#endif /* CONFIG_P2P */
4574 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004575 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004576#ifdef CONFIG_HS20
4577 hs20_configure_frame_filters(wpa_s);
4578#endif /* CONFIG_HS20 */
4579 }
4580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004581 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4582 wpa_supplicant_initiate_eapol(wpa_s);
4583 if (old_ssid != wpa_s->current_ssid)
4584 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004585 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4586 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004587}
4588
4589
4590static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4591 const u8 *addr)
4592{
4593 struct wpa_ssid *old_ssid;
4594
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004595 wpa_s->ml_connect_probe_ssid = NULL;
4596 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004597 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004598 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004600 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004601 wpa_sm_set_config(wpa_s->wpa, NULL);
4602 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4603 if (old_ssid != wpa_s->current_ssid)
4604 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004605
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004606#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08004607 wpas_scs_deinit(wpa_s);
4608 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004609#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004610 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4611}
4612
4613
4614/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4616 * @wpa_s: Pointer to wpa_supplicant data
4617 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4618 *
4619 * This function is used to request %wpa_supplicant to deauthenticate from the
4620 * current AP.
4621 */
4622void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004623 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004624{
4625 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004626 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004627 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004628
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004629 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004630 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004631 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004632 reason_code, reason2str(reason_code),
4633 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004634
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004635 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4636 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4637 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004638 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004639 else if (!is_zero_ether_addr(wpa_s->bssid))
4640 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004641 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4642 /*
4643 * When using driver-based BSS selection, we may not know the
4644 * BSSID with which we are currently trying to associate. We
4645 * need to notify the driver of this disconnection even in such
4646 * a case, so use the all zeros address here.
4647 */
4648 addr = wpa_s->bssid;
4649 zero_addr = 1;
4650 }
4651
Hai Shalom74f70d42019-02-11 14:42:39 -08004652 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4653 wpa_s->enabled_4addr_mode = 0;
4654
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004655#ifdef CONFIG_TDLS
4656 wpa_tdls_teardown_peers(wpa_s->wpa);
4657#endif /* CONFIG_TDLS */
4658
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004659#ifdef CONFIG_MESH
4660 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004661 struct mesh_conf *mconf;
4662
4663 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004664 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4665 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004666 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4667 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004668 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004669 }
4670#endif /* CONFIG_MESH */
4671
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004672 if (addr) {
4673 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004674 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004675 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004676 event.deauth_info.locally_generated = 1;
4677 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004678 if (zero_addr)
4679 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004680 }
4681
4682 wpa_supplicant_clear_connection(wpa_s, addr);
4683}
4684
Hai Shalomfdcde762020-04-02 11:19:20 -07004685
4686void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4687{
4688 wpa_s->own_reconnect_req = 1;
4689 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4690
4691}
4692
4693
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004694static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4695 struct wpa_ssid *ssid)
4696{
4697 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4698 return;
4699
4700 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004701 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004702 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4703 wpas_notify_network_enabled_changed(wpa_s, ssid);
4704
4705 /*
4706 * Try to reassociate since there is no current configuration and a new
4707 * network was made available.
4708 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004709 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004710 wpa_s->reassociate = 1;
4711}
4712
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004713
Roshan Pius950bec92016-07-19 09:49:24 -07004714/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004715 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004716 * @wpa_s: wpa_supplicant structure for a network interface
4717 * Returns: The new network configuration or %NULL if operation failed
4718 *
4719 * This function performs the following operations:
4720 * 1. Adds a new network.
4721 * 2. Send network addition notification.
4722 * 3. Marks the network disabled.
4723 * 4. Set network default parameters.
4724 */
4725struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4726{
4727 struct wpa_ssid *ssid;
4728
4729 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004730 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004731 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004732 wpas_notify_network_added(wpa_s, ssid);
4733 ssid->disabled = 1;
4734 wpa_config_set_network_defaults(ssid);
4735
4736 return ssid;
4737}
4738
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004739
Roshan Pius950bec92016-07-19 09:49:24 -07004740/**
4741 * wpa_supplicant_remove_network - Remove a configured network based on id
4742 * @wpa_s: wpa_supplicant structure for a network interface
4743 * @id: Unique network id to search for
4744 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4745 * could not be removed
4746 *
4747 * This function performs the following operations:
4748 * 1. Removes the network.
4749 * 2. Send network removal notification.
4750 * 3. Update internal state machines.
4751 * 4. Stop any running sched scans.
4752 */
4753int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4754{
Sunil Ravia04bd252022-05-02 22:54:18 -07004755 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004756 int was_disabled;
4757
4758 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004759 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004760 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004761 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004762
Sunil Ravia04bd252022-05-02 22:54:18 -07004763 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004764#ifdef CONFIG_SME
4765 wpa_s->sme.prev_bssid_set = 0;
4766#endif /* CONFIG_SME */
4767 /*
4768 * Invalidate the EAP session cache if the current or
4769 * previously used network is removed.
4770 */
4771 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4772 }
4773
Sunil Ravia04bd252022-05-02 22:54:18 -07004774 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004775 wpa_sm_set_config(wpa_s->wpa, NULL);
4776 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4777
4778 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4779 wpa_s->own_disconnect_req = 1;
4780 wpa_supplicant_deauthenticate(wpa_s,
4781 WLAN_REASON_DEAUTH_LEAVING);
4782 }
4783
4784 was_disabled = ssid->disabled;
4785
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004786 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004787 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004788
4789 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004790 wpa_printf(MSG_DEBUG,
4791 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004792 wpa_supplicant_cancel_sched_scan(wpa_s);
4793 wpa_supplicant_req_scan(wpa_s, 0, 0);
4794 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004795
Roshan Pius950bec92016-07-19 09:49:24 -07004796 return 0;
4797}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004799
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004800/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004801 * wpa_supplicant_remove_all_networks - Remove all configured networks
4802 * @wpa_s: wpa_supplicant structure for a network interface
4803 * Returns: 0 on success (errors are currently ignored)
4804 *
4805 * This function performs the following operations:
4806 * 1. Remove all networks.
4807 * 2. Send network removal notifications.
4808 * 3. Update internal state machines.
4809 * 4. Stop any running sched scans.
4810 */
4811int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4812{
4813 struct wpa_ssid *ssid;
4814
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304815 if (wpa_s->drv_flags2 &
4816 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4817 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4818 wpa_drv_flush_pmkid(wpa_s);
4819
Hai Shalom899fcc72020-10-19 14:38:18 -07004820 if (wpa_s->sched_scanning)
4821 wpa_supplicant_cancel_sched_scan(wpa_s);
4822
4823 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4824 if (wpa_s->current_ssid) {
4825#ifdef CONFIG_SME
4826 wpa_s->sme.prev_bssid_set = 0;
4827#endif /* CONFIG_SME */
4828 wpa_sm_set_config(wpa_s->wpa, NULL);
4829 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4830 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4831 wpa_s->own_disconnect_req = 1;
4832 wpa_supplicant_deauthenticate(
4833 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4834 }
4835 ssid = wpa_s->conf->ssid;
4836 while (ssid) {
4837 struct wpa_ssid *remove_ssid = ssid;
4838 int id;
4839
4840 id = ssid->id;
4841 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004842 wpas_notify_network_removed(wpa_s, remove_ssid);
4843 wpa_config_remove_network(wpa_s->conf, id);
4844 }
4845 return 0;
4846}
4847
4848
4849/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004850 * wpa_supplicant_enable_network - Mark a configured network as enabled
4851 * @wpa_s: wpa_supplicant structure for a network interface
4852 * @ssid: wpa_ssid structure for a configured network or %NULL
4853 *
4854 * Enables the specified network or all networks if no network specified.
4855 */
4856void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4857 struct wpa_ssid *ssid)
4858{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004860 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4861 wpa_supplicant_enable_one_network(wpa_s, ssid);
4862 } else
4863 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004865 if (wpa_s->reassociate && !wpa_s->disconnected &&
4866 (!wpa_s->current_ssid ||
4867 wpa_s->wpa_state == WPA_DISCONNECTED ||
4868 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004869 if (wpa_s->sched_scanning) {
4870 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4871 "new network to scan filters");
4872 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873 }
4874
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004875 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4876 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004877 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004878 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004879 }
4880}
4881
4882
4883/**
4884 * wpa_supplicant_disable_network - Mark a configured network as disabled
4885 * @wpa_s: wpa_supplicant structure for a network interface
4886 * @ssid: wpa_ssid structure for a configured network or %NULL
4887 *
4888 * Disables the specified network or all networks if no network specified.
4889 */
4890void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4891 struct wpa_ssid *ssid)
4892{
4893 struct wpa_ssid *other_ssid;
4894 int was_disabled;
4895
4896 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004897 if (wpa_s->sched_scanning)
4898 wpa_supplicant_cancel_sched_scan(wpa_s);
4899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4901 other_ssid = other_ssid->next) {
4902 was_disabled = other_ssid->disabled;
4903 if (was_disabled == 2)
4904 continue; /* do not change persistent P2P group
4905 * data */
4906
4907 other_ssid->disabled = 1;
4908
4909 if (was_disabled != other_ssid->disabled)
4910 wpas_notify_network_enabled_changed(
4911 wpa_s, other_ssid);
4912 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004913 if (wpa_s->current_ssid) {
4914 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4915 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004916 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004920 if (ssid == wpa_s->current_ssid) {
4921 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4922 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004923 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004924 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004925 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004926
4927 was_disabled = ssid->disabled;
4928
4929 ssid->disabled = 1;
4930
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004931 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004932 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004933 if (wpa_s->sched_scanning) {
4934 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4935 "to remove network from filters");
4936 wpa_supplicant_cancel_sched_scan(wpa_s);
4937 wpa_supplicant_req_scan(wpa_s, 0, 0);
4938 }
4939 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004940 }
4941}
4942
4943
4944/**
4945 * wpa_supplicant_select_network - Attempt association with a network
4946 * @wpa_s: wpa_supplicant structure for a network interface
4947 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4948 */
4949void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4950 struct wpa_ssid *ssid)
4951{
4952
4953 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004954 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004955
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004956 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004957 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4958 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004959 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004961 disconnected = 1;
4962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004963
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004964 if (ssid)
4965 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967 /*
4968 * Mark all other networks disabled or mark all networks enabled if no
4969 * network specified.
4970 */
4971 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4972 other_ssid = other_ssid->next) {
4973 int was_disabled = other_ssid->disabled;
4974 if (was_disabled == 2)
4975 continue; /* do not change persistent P2P group data */
4976
4977 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004978 if (was_disabled && !other_ssid->disabled)
4979 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004980
4981 if (was_disabled != other_ssid->disabled)
4982 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4983 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004984
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004985 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4986 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004987 /* We are already associated with the selected network */
4988 wpa_printf(MSG_DEBUG, "Already associated with the "
4989 "selected network - do nothing");
4990 return;
4991 }
4992
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004993 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004994 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004995 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004996 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004997 (ssid->mode == WPAS_MODE_MESH ||
4998 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004999
5000 /*
5001 * Don't optimize next scan freqs since a new ESS has been
5002 * selected.
5003 */
5004 os_free(wpa_s->next_scan_freqs);
5005 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005006 } else {
5007 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005008 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005010 wpa_s->disconnected = 0;
5011 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005012 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005013 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005014 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005015 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07005016 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07005017 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005018
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005019 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005020 wpa_supplicant_fast_associate(wpa_s) != 1) {
5021 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005022 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005023 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005024 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005025
5026 if (ssid)
5027 wpas_notify_network_selected(wpa_s, ssid);
5028}
5029
5030
5031/**
Hai Shalomc1a21442022-02-04 13:43:00 -08005032 * wpas_remove_cred - Remove the specified credential and all the network
5033 * entries created based on the removed credential
5034 * @wpa_s: wpa_supplicant structure for a network interface
5035 * @cred: The credential to remove
5036 * Returns: 0 on success, -1 on failure
5037 */
5038int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
5039{
5040 struct wpa_ssid *ssid, *next;
5041 int id;
5042
5043 if (!cred) {
5044 wpa_printf(MSG_DEBUG, "Could not find cred");
5045 return -1;
5046 }
5047
5048 id = cred->id;
5049 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5050 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5051 return -1;
5052 }
5053
5054 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5055
5056 /* Remove any network entry created based on the removed credential */
5057 ssid = wpa_s->conf->ssid;
5058 while (ssid) {
5059 next = ssid->next;
5060
5061 if (ssid->parent_cred == cred) {
5062 wpa_printf(MSG_DEBUG,
5063 "Remove network id %d since it used the removed credential",
5064 ssid->id);
5065 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5066 -1) {
5067 wpa_printf(MSG_DEBUG,
5068 "Could not find network id=%d",
5069 ssid->id);
5070 }
5071 }
5072
5073 ssid = next;
5074 }
5075
5076 return 0;
5077}
5078
5079
5080/**
5081 * wpas_remove_cred - Remove all the Interworking credentials
5082 * @wpa_s: wpa_supplicant structure for a network interface
5083 * Returns: 0 on success, -1 on failure
5084 */
5085int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5086{
5087 int res, ret = 0;
5088 struct wpa_cred *cred, *prev;
5089
5090 cred = wpa_s->conf->cred;
5091 while (cred) {
5092 prev = cred;
5093 cred = cred->next;
5094 res = wpas_remove_cred(wpa_s, prev);
5095 if (res < 0) {
5096 wpa_printf(MSG_DEBUG,
5097 "Removal of all credentials failed - failed to remove credential id=%d",
5098 prev->id);
5099 ret = -1;
5100 }
5101 }
5102
5103 return ret;
5104}
5105
5106
5107/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005108 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5109 * @wpa_s: wpa_supplicant structure for a network interface
5110 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5111 * @pkcs11_module_path: PKCS #11 module path or NULL
5112 * Returns: 0 on success; -1 on failure
5113 *
5114 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5115 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5116 * module path fails the paths will be reset to the default value (NULL).
5117 */
5118int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5119 const char *pkcs11_engine_path,
5120 const char *pkcs11_module_path)
5121{
5122 char *pkcs11_engine_path_copy = NULL;
5123 char *pkcs11_module_path_copy = NULL;
5124
5125 if (pkcs11_engine_path != NULL) {
5126 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5127 if (pkcs11_engine_path_copy == NULL)
5128 return -1;
5129 }
5130 if (pkcs11_module_path != NULL) {
5131 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005132 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005133 os_free(pkcs11_engine_path_copy);
5134 return -1;
5135 }
5136 }
5137
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005138#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005139 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005140 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005141#endif /* CONFIG_PKCS11_ENGINE_PATH */
5142#ifndef CONFIG_PKCS11_MODULE_PATH
5143 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005144 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005145#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005146
5147 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5148 eapol_sm_deinit(wpa_s->eapol);
5149 wpa_s->eapol = NULL;
5150 if (wpa_supplicant_init_eapol(wpa_s)) {
5151 /* Error -> Reset paths to the default value (NULL) once. */
5152 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5153 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5154 NULL);
5155
5156 return -1;
5157 }
5158 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5159
5160 return 0;
5161}
5162
5163
5164/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005165 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5166 * @wpa_s: wpa_supplicant structure for a network interface
5167 * @ap_scan: AP scan mode
5168 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5169 *
5170 */
5171int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5172{
5173
5174 int old_ap_scan;
5175
5176 if (ap_scan < 0 || ap_scan > 2)
5177 return -1;
5178
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005179 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5180 wpa_printf(MSG_INFO,
5181 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5182 }
5183
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005184#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005185 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5186 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5187 wpa_s->wpa_state < WPA_COMPLETED) {
5188 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5189 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005190 return 0;
5191 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005192#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005193
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194 old_ap_scan = wpa_s->conf->ap_scan;
5195 wpa_s->conf->ap_scan = ap_scan;
5196
5197 if (old_ap_scan != wpa_s->conf->ap_scan)
5198 wpas_notify_ap_scan_changed(wpa_s);
5199
5200 return 0;
5201}
5202
5203
5204/**
5205 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5206 * @wpa_s: wpa_supplicant structure for a network interface
5207 * @expire_age: Expiration age in seconds
5208 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5209 *
5210 */
5211int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5212 unsigned int bss_expire_age)
5213{
5214 if (bss_expire_age < 10) {
5215 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5216 bss_expire_age);
5217 return -1;
5218 }
5219 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5220 bss_expire_age);
5221 wpa_s->conf->bss_expiration_age = bss_expire_age;
5222
5223 return 0;
5224}
5225
5226
5227/**
5228 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5229 * @wpa_s: wpa_supplicant structure for a network interface
5230 * @expire_count: number of scans after which an unseen BSS is reclaimed
5231 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5232 *
5233 */
5234int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5235 unsigned int bss_expire_count)
5236{
5237 if (bss_expire_count < 1) {
5238 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5239 bss_expire_count);
5240 return -1;
5241 }
5242 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5243 bss_expire_count);
5244 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5245
5246 return 0;
5247}
5248
5249
5250/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005251 * wpa_supplicant_set_scan_interval - Set scan interval
5252 * @wpa_s: wpa_supplicant structure for a network interface
5253 * @scan_interval: scan interval in seconds
5254 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5255 *
5256 */
5257int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5258 int scan_interval)
5259{
5260 if (scan_interval < 0) {
5261 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5262 scan_interval);
5263 return -1;
5264 }
5265 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5266 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005267 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005268
5269 return 0;
5270}
5271
5272
5273/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005274 * wpa_supplicant_set_debug_params - Set global debug params
5275 * @global: wpa_global structure
5276 * @debug_level: debug level
5277 * @debug_timestamp: determines if show timestamp in debug data
5278 * @debug_show_keys: determines if show keys in debug data
5279 * Returns: 0 if succeed or -1 if debug_level has wrong value
5280 */
5281int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5282 int debug_timestamp, int debug_show_keys)
5283{
5284
5285 int old_level, old_timestamp, old_show_keys;
5286
5287 /* check for allowed debuglevels */
5288 if (debug_level != MSG_EXCESSIVE &&
5289 debug_level != MSG_MSGDUMP &&
5290 debug_level != MSG_DEBUG &&
5291 debug_level != MSG_INFO &&
5292 debug_level != MSG_WARNING &&
5293 debug_level != MSG_ERROR)
5294 return -1;
5295
5296 old_level = wpa_debug_level;
5297 old_timestamp = wpa_debug_timestamp;
5298 old_show_keys = wpa_debug_show_keys;
5299
5300 wpa_debug_level = debug_level;
5301 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5302 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5303
5304 if (wpa_debug_level != old_level)
5305 wpas_notify_debug_level_changed(global);
5306 if (wpa_debug_timestamp != old_timestamp)
5307 wpas_notify_debug_timestamp_changed(global);
5308 if (wpa_debug_show_keys != old_show_keys)
5309 wpas_notify_debug_show_keys_changed(global);
5310
5311 return 0;
5312}
5313
5314
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005315#ifdef CONFIG_OWE
5316static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5317 const u8 *entry_ssid, size_t entry_ssid_len)
5318{
5319 const u8 *owe, *pos, *end;
5320 u8 ssid_len;
5321 struct wpa_bss *bss;
5322
5323 /* Check network profile SSID aganst the SSID in the
5324 * OWE Transition Mode element. */
5325
5326 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5327 if (!bss)
5328 return 0;
5329
5330 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5331 if (!owe)
5332 return 0;
5333
5334 pos = owe + 6;
5335 end = owe + 2 + owe[1];
5336
5337 if (end - pos < ETH_ALEN + 1)
5338 return 0;
5339 pos += ETH_ALEN;
5340 ssid_len = *pos++;
5341 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5342 return 0;
5343
5344 return entry_ssid_len == ssid_len &&
5345 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5346}
5347#endif /* CONFIG_OWE */
5348
5349
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005350/**
5351 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5352 * @wpa_s: Pointer to wpa_supplicant data
5353 * Returns: A pointer to the current network structure or %NULL on failure
5354 */
5355struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5356{
5357 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005358 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005359 int res;
5360 size_t ssid_len;
5361 u8 bssid[ETH_ALEN];
5362 int wired;
5363
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005364 res = wpa_drv_get_ssid(wpa_s, ssid);
5365 if (res < 0) {
5366 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5367 "driver");
5368 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005369 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005370 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005372 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5374 "driver");
5375 return NULL;
5376 }
5377
5378 wired = wpa_s->conf->ap_scan == 0 &&
5379 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5380
5381 entry = wpa_s->conf->ssid;
5382 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005383 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005384 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005385 (!entry->ssid ||
5386 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5387 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005388 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005389 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005390 return entry;
5391#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005392 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005393 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5394 (entry->ssid == NULL || entry->ssid_len == 0) &&
5395 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005396 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005397 return entry;
5398#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005399
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005400#ifdef CONFIG_OWE
5401 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005402 (entry->ssid &&
5403 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5404 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005405 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005406 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005407 return entry;
5408#endif /* CONFIG_OWE */
5409
Dmitry Shmidt04949592012-07-19 12:16:46 -07005410 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005411 entry->ssid_len == 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005412 ether_addr_equal(bssid, entry->bssid))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005413 return entry;
5414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005415 entry = entry->next;
5416 }
5417
5418 return NULL;
5419}
5420
5421
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005422static int select_driver(struct wpa_supplicant *wpa_s, int i)
5423{
5424 struct wpa_global *global = wpa_s->global;
5425
5426 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005427 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005428 if (global->drv_priv[i] == NULL) {
5429 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5430 "'%s'", wpa_drivers[i]->name);
5431 return -1;
5432 }
5433 }
5434
5435 wpa_s->driver = wpa_drivers[i];
5436 wpa_s->global_drv_priv = global->drv_priv[i];
5437
5438 return 0;
5439}
5440
5441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5443 const char *name)
5444{
5445 int i;
5446 size_t len;
5447 const char *pos, *driver = name;
5448
5449 if (wpa_s == NULL)
5450 return -1;
5451
5452 if (wpa_drivers[0] == NULL) {
5453 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5454 "wpa_supplicant");
5455 return -1;
5456 }
5457
5458 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005459 /* Default to first successful driver in the list */
5460 for (i = 0; wpa_drivers[i]; i++) {
5461 if (select_driver(wpa_s, i) == 0)
5462 return 0;
5463 }
5464 /* Drivers have each reported failure, so no wpa_msg() here. */
5465 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005466 }
5467
5468 do {
5469 pos = os_strchr(driver, ',');
5470 if (pos)
5471 len = pos - driver;
5472 else
5473 len = os_strlen(driver);
5474
5475 for (i = 0; wpa_drivers[i]; i++) {
5476 if (os_strlen(wpa_drivers[i]->name) == len &&
5477 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005478 0) {
5479 /* First driver that succeeds wins */
5480 if (select_driver(wpa_s, i) == 0)
5481 return 0;
5482 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005483 }
5484
5485 driver = pos + 1;
5486 } while (pos);
5487
5488 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5489 return -1;
5490}
5491
5492
5493/**
5494 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5495 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5496 * with struct wpa_driver_ops::init()
5497 * @src_addr: Source address of the EAPOL frame
5498 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5499 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005500 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005501 *
5502 * This function is called for each received EAPOL frame. Most driver
5503 * interfaces rely on more generic OS mechanism for receiving frames through
5504 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5505 * take care of received EAPOL frames and deliver them to the core supplicant
5506 * code by calling this function.
5507 */
5508void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005509 const u8 *buf, size_t len,
5510 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005511{
5512 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005513 const u8 *connected_addr = wpa_s->valid_links ?
5514 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005515
Sunil8cd6f4d2022-06-28 18:40:46 +00005516 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5517 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005518 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5519
Hai Shalomc1a21442022-02-04 13:43:00 -08005520 if (wpa_s->own_disconnect_req) {
5521 wpa_printf(MSG_DEBUG,
5522 "Drop received EAPOL frame as we are disconnecting");
5523 return;
5524 }
5525
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005526#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005527 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5528 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005529 if (wpa_s->ignore_auth_resp) {
5530 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5531 return;
5532 }
5533#endif /* CONFIG_TESTING_OPTIONS */
5534
Jouni Malinena05074c2012-12-21 21:35:35 +02005535 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5536 (wpa_s->last_eapol_matches_bssid &&
5537#ifdef CONFIG_AP
5538 !wpa_s->ap_iface &&
5539#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005540 !ether_addr_equal(src_addr, connected_addr))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541 /*
5542 * There is possible race condition between receiving the
5543 * association event and the EAPOL frame since they are coming
5544 * through different paths from the driver. In order to avoid
5545 * issues in trying to process the EAPOL frame before receiving
5546 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005547 * the association event is received. This may also be needed in
5548 * driver-based roaming case, so also use src_addr != BSSID as a
5549 * trigger if we have previously confirmed that the
5550 * Authenticator uses BSSID as the src_addr (which is not the
5551 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005552 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005553 wpa_dbg(wpa_s, MSG_DEBUG,
5554 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5555 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005556 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005557 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005558 wpabuf_free(wpa_s->pending_eapol_rx);
5559 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5560 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005561 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005562 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5563 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005564 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005565 }
5566 return;
5567 }
5568
Jouni Malinena05074c2012-12-21 21:35:35 +02005569 wpa_s->last_eapol_matches_bssid =
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005570 ether_addr_equal(src_addr, connected_addr);
Jouni Malinena05074c2012-12-21 21:35:35 +02005571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005572#ifdef CONFIG_AP
5573 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005574 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5575 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 return;
5577 }
5578#endif /* CONFIG_AP */
5579
5580 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5581 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5582 "no key management is configured");
5583 return;
5584 }
5585
5586 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005587 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005588 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5589 wpa_s->wpa_state != WPA_COMPLETED) &&
5590 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005591 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005592 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005593 int timeout = 10;
5594
5595 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5596 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5597 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5598 /* Use longer timeout for IEEE 802.1X/EAP */
5599 timeout = 70;
5600 }
5601
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005602#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005603 if (wpa_s->current_ssid && wpa_s->current_bss &&
5604 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5605 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5606 /*
5607 * Use shorter timeout if going through WPS AP iteration
5608 * for PIN config method with an AP that does not
5609 * advertise Selected Registrar.
5610 */
5611 struct wpabuf *wps_ie;
5612
5613 wps_ie = wpa_bss_get_vendor_ie_multi(
5614 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5615 if (wps_ie &&
5616 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5617 timeout = 10;
5618 wpabuf_free(wps_ie);
5619 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005620#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005621
5622 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005623 }
5624 wpa_s->eapol_received++;
5625
5626 if (wpa_s->countermeasures) {
5627 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5628 "EAPOL packet");
5629 return;
5630 }
5631
5632#ifdef CONFIG_IBSS_RSN
5633 if (wpa_s->current_ssid &&
5634 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005635 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5636 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637 return;
5638 }
5639#endif /* CONFIG_IBSS_RSN */
5640
5641 /* Source address of the incoming EAPOL frame could be compared to the
5642 * current BSSID. However, it is possible that a centralized
5643 * Authenticator could be using another MAC address than the BSSID of
5644 * an AP, so just allow any address to be used for now. The replies are
5645 * still sent to the current BSSID (if available), though. */
5646
5647 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5648 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005649 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5650 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005651 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5652 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005653 return;
5654 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005655 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005656 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005657 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5658 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005659 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660 * handshake processing which would normally set portValid. We
5661 * need this to allow the EAPOL state machines to be completed
5662 * without going through EAPOL-Key handshake.
5663 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005664 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005665 }
5666}
5667
5668
Sunil8cd6f4d2022-06-28 18:40:46 +00005669static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5670 const u8 *buf, size_t len)
5671{
5672 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5673 FRAME_ENCRYPTION_UNKNOWN);
5674}
5675
5676
Hai Shalomb755a2a2020-04-23 21:49:02 -07005677static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5678{
5679 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5680 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5681}
5682
5683
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005684int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005686 u8 prev_mac_addr[ETH_ALEN];
5687
5688 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5689
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005690 if ((!wpa_s->p2p_mgmt ||
5691 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5692 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005693 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005694 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5695 wpa_drv_get_mac_addr(wpa_s),
5696 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005697 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005698 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005699 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005700 if (wpa_s->l2 == NULL)
5701 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005702
5703 if (l2_packet_set_packet_filter(wpa_s->l2,
5704 L2_PACKET_FILTER_PKTTYPE))
5705 wpa_dbg(wpa_s, MSG_DEBUG,
5706 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005707
5708 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5709 wpa_msg(wpa_s, MSG_ERROR,
5710 "Failed to get own L2 address");
5711 return -1;
5712 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713 } else {
5714 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5715 if (addr)
5716 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5717 }
5718
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005719 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005720 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005721
Hai Shalomc3565922019-10-28 11:58:20 -07005722#ifdef CONFIG_FST
5723 if (wpa_s->fst)
5724 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5725#endif /* CONFIG_FST */
5726
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005727 if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00005728 wpas_notify_mac_address_changed(wpa_s);
5729
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005730 return 0;
5731}
5732
5733
Dmitry Shmidt04949592012-07-19 12:16:46 -07005734static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5735 const u8 *buf, size_t len)
5736{
5737 struct wpa_supplicant *wpa_s = ctx;
5738 const struct l2_ethhdr *eth;
5739
5740 if (len < sizeof(*eth))
5741 return;
5742 eth = (const struct l2_ethhdr *) buf;
5743
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005744 if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005745 !(eth->h_dest[0] & 0x01)) {
5746 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5747 " (bridge - not for this interface - ignore)",
5748 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5749 return;
5750 }
5751
5752 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5753 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5754 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005755 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005756}
5757
5758
Hai Shalom899fcc72020-10-19 14:38:18 -07005759int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5760 const char *bridge_ifname)
5761{
5762 if (wpa_s->wpa_state > WPA_SCANNING)
5763 return -EBUSY;
5764
5765 if (bridge_ifname &&
5766 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5767 return -EINVAL;
5768
5769 if (!bridge_ifname)
5770 bridge_ifname = "";
5771
5772 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5773 return 0;
5774
5775 if (wpa_s->l2_br) {
5776 l2_packet_deinit(wpa_s->l2_br);
5777 wpa_s->l2_br = NULL;
5778 }
5779
5780 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5781 sizeof(wpa_s->bridge_ifname));
5782
5783 if (wpa_s->bridge_ifname[0]) {
5784 wpa_dbg(wpa_s, MSG_DEBUG,
5785 "Receiving packets from bridge interface '%s'",
5786 wpa_s->bridge_ifname);
5787 wpa_s->l2_br = l2_packet_init_bridge(
5788 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5789 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5790 if (!wpa_s->l2_br) {
5791 wpa_msg(wpa_s, MSG_ERROR,
5792 "Failed to open l2_packet connection for the bridge interface '%s'",
5793 wpa_s->bridge_ifname);
5794 goto fail;
5795 }
5796 }
5797
5798#ifdef CONFIG_TDLS
5799 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5800 goto fail;
5801#endif /* CONFIG_TDLS */
5802
5803 return 0;
5804fail:
5805 wpa_s->bridge_ifname[0] = 0;
5806 if (wpa_s->l2_br) {
5807 l2_packet_deinit(wpa_s->l2_br);
5808 wpa_s->l2_br = NULL;
5809 }
5810#ifdef CONFIG_TDLS
5811 if (!wpa_s->p2p_mgmt)
5812 wpa_tdls_init(wpa_s->wpa);
5813#endif /* CONFIG_TDLS */
5814 return -EIO;
5815}
5816
5817
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005818/**
5819 * wpa_supplicant_driver_init - Initialize driver interface parameters
5820 * @wpa_s: Pointer to wpa_supplicant data
5821 * Returns: 0 on success, -1 on failure
5822 *
5823 * This function is called to initialize driver interface parameters.
5824 * wpa_drv_init() must have been called before this function to initialize the
5825 * driver interface.
5826 */
5827int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5828{
5829 static int interface_count = 0;
5830
5831 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5832 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005834 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5835 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005836 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005837 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5838
Hai Shalomb755a2a2020-04-23 21:49:02 -07005839 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005840 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5841 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005842 wpa_s->l2_br = l2_packet_init_bridge(
5843 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5844 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005845 if (wpa_s->l2_br == NULL) {
5846 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5847 "connection for the bridge interface '%s'",
5848 wpa_s->bridge_ifname);
5849 return -1;
5850 }
5851 }
5852
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005853 if (wpa_s->conf->ap_scan == 2 &&
5854 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5855 wpa_printf(MSG_INFO,
5856 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5857 }
5858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859 wpa_clear_keys(wpa_s, NULL);
5860
5861 /* Make sure that TKIP countermeasures are not left enabled (could
5862 * happen if wpa_supplicant is killed during countermeasures. */
5863 wpa_drv_set_countermeasures(wpa_s, 0);
5864
5865 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5866 wpa_drv_flush_pmkid(wpa_s);
5867
5868 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005869 wpa_s->prev_scan_wildcard = 0;
5870
Dmitry Shmidt04949592012-07-19 12:16:46 -07005871 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005872 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5873 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5874 interface_count = 0;
5875 }
Keith Mok4389c282022-11-23 21:36:48 +00005876#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005877 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005878 wpa_supplicant_delayed_sched_scan(wpa_s,
5879 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005880 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005881 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005882 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005883#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005884 interface_count++;
5885 } else
5886 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5887
5888 return 0;
5889}
5890
5891
5892static int wpa_supplicant_daemon(const char *pid_file)
5893{
5894 wpa_printf(MSG_DEBUG, "Daemonize..");
5895 return os_daemonize(pid_file);
5896}
5897
5898
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005899static struct wpa_supplicant *
5900wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005901{
5902 struct wpa_supplicant *wpa_s;
5903
5904 wpa_s = os_zalloc(sizeof(*wpa_s));
5905 if (wpa_s == NULL)
5906 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005907 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908 wpa_s->scan_interval = 5;
5909 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005910 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005911 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005912 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005913 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005914
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005915 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005916 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005917#ifdef CONFIG_TESTING_OPTIONS
5918 dl_list_init(&wpa_s->drv_signal_override);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005919 wpa_s->test_assoc_comeback_type = -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07005920#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005921#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08005922 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005923#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005924 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005925
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005926 return wpa_s;
5927}
5928
5929
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005930#ifdef CONFIG_HT_OVERRIDES
5931
5932static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5933 struct ieee80211_ht_capabilities *htcaps,
5934 struct ieee80211_ht_capabilities *htcaps_mask,
5935 const char *ht_mcs)
5936{
5937 /* parse ht_mcs into hex array */
5938 int i;
5939 const char *tmp = ht_mcs;
5940 char *end = NULL;
5941
5942 /* If ht_mcs is null, do not set anything */
5943 if (!ht_mcs)
5944 return 0;
5945
5946 /* This is what we are setting in the kernel */
5947 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5948
5949 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5950
5951 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005952 long v;
5953
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005954 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005955 v = strtol(tmp, &end, 16);
5956
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005957 if (errno == 0) {
5958 wpa_msg(wpa_s, MSG_DEBUG,
5959 "htcap value[%i]: %ld end: %p tmp: %p",
5960 i, v, end, tmp);
5961 if (end == tmp)
5962 break;
5963
5964 htcaps->supported_mcs_set[i] = v;
5965 tmp = end;
5966 } else {
5967 wpa_msg(wpa_s, MSG_ERROR,
5968 "Failed to parse ht-mcs: %s, error: %s\n",
5969 ht_mcs, strerror(errno));
5970 return -1;
5971 }
5972 }
5973
5974 /*
5975 * If we were able to parse any values, then set mask for the MCS set.
5976 */
5977 if (i) {
5978 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5979 IEEE80211_HT_MCS_MASK_LEN - 1);
5980 /* skip the 3 reserved bits */
5981 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5982 0x1f;
5983 }
5984
5985 return 0;
5986}
5987
5988
5989static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5990 struct ieee80211_ht_capabilities *htcaps,
5991 struct ieee80211_ht_capabilities *htcaps_mask,
5992 int disabled)
5993{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005994 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005995
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005996 if (disabled == -1)
5997 return 0;
5998
Hai Shalom74f70d42019-02-11 14:42:39 -08005999 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
6000
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006001 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
6002 htcaps_mask->ht_capabilities_info |= msk;
6003 if (disabled)
6004 htcaps->ht_capabilities_info &= msk;
6005 else
6006 htcaps->ht_capabilities_info |= msk;
6007
6008 return 0;
6009}
6010
6011
6012static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
6013 struct ieee80211_ht_capabilities *htcaps,
6014 struct ieee80211_ht_capabilities *htcaps_mask,
6015 int factor)
6016{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006017 if (factor == -1)
6018 return 0;
6019
Hai Shalom74f70d42019-02-11 14:42:39 -08006020 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
6021
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006022 if (factor < 0 || factor > 3) {
6023 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
6024 "Must be 0-3 or -1", factor);
6025 return -EINVAL;
6026 }
6027
6028 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
6029 htcaps->a_mpdu_params &= ~0x3;
6030 htcaps->a_mpdu_params |= factor & 0x3;
6031
6032 return 0;
6033}
6034
6035
6036static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
6037 struct ieee80211_ht_capabilities *htcaps,
6038 struct ieee80211_ht_capabilities *htcaps_mask,
6039 int density)
6040{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006041 if (density == -1)
6042 return 0;
6043
Hai Shalom74f70d42019-02-11 14:42:39 -08006044 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
6045
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006046 if (density < 0 || density > 7) {
6047 wpa_msg(wpa_s, MSG_ERROR,
6048 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6049 density);
6050 return -EINVAL;
6051 }
6052
6053 htcaps_mask->a_mpdu_params |= 0x1C;
6054 htcaps->a_mpdu_params &= ~(0x1C);
6055 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6056
6057 return 0;
6058}
6059
6060
6061static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6062 struct ieee80211_ht_capabilities *htcaps,
6063 struct ieee80211_ht_capabilities *htcaps_mask,
6064 int disabled)
6065{
Hai Shalom74f70d42019-02-11 14:42:39 -08006066 if (disabled)
6067 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006068
Paul Stewart092955c2017-02-06 09:13:09 -08006069 set_disable_ht40(htcaps, disabled);
6070 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006071
6072 return 0;
6073}
6074
6075
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006076static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6077 struct ieee80211_ht_capabilities *htcaps,
6078 struct ieee80211_ht_capabilities *htcaps_mask,
6079 int disabled)
6080{
6081 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006082 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6083 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006084
Hai Shalom74f70d42019-02-11 14:42:39 -08006085 if (disabled)
6086 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006087
6088 if (disabled)
6089 htcaps->ht_capabilities_info &= ~msk;
6090 else
6091 htcaps->ht_capabilities_info |= msk;
6092
6093 htcaps_mask->ht_capabilities_info |= msk;
6094
6095 return 0;
6096}
6097
6098
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006099static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6100 struct ieee80211_ht_capabilities *htcaps,
6101 struct ieee80211_ht_capabilities *htcaps_mask,
6102 int disabled)
6103{
6104 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006105 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006106
Hai Shalom74f70d42019-02-11 14:42:39 -08006107 if (disabled)
6108 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006109
6110 if (disabled)
6111 htcaps->ht_capabilities_info &= ~msk;
6112 else
6113 htcaps->ht_capabilities_info |= msk;
6114
6115 htcaps_mask->ht_capabilities_info |= msk;
6116
6117 return 0;
6118}
6119
6120
Hai Shalom74f70d42019-02-11 14:42:39 -08006121static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6122 struct ieee80211_ht_capabilities *htcaps,
6123 struct ieee80211_ht_capabilities *htcaps_mask,
6124 int tx_stbc)
6125{
6126 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6127
6128 if (tx_stbc == -1)
6129 return 0;
6130
6131 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6132
6133 if (tx_stbc < 0 || tx_stbc > 1) {
6134 wpa_msg(wpa_s, MSG_ERROR,
6135 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6136 return -EINVAL;
6137 }
6138
6139 htcaps_mask->ht_capabilities_info |= msk;
6140 htcaps->ht_capabilities_info &= ~msk;
6141 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6142
6143 return 0;
6144}
6145
6146
6147static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6148 struct ieee80211_ht_capabilities *htcaps,
6149 struct ieee80211_ht_capabilities *htcaps_mask,
6150 int rx_stbc)
6151{
6152 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6153
6154 if (rx_stbc == -1)
6155 return 0;
6156
6157 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6158
6159 if (rx_stbc < 0 || rx_stbc > 3) {
6160 wpa_msg(wpa_s, MSG_ERROR,
6161 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6162 return -EINVAL;
6163 }
6164
6165 htcaps_mask->ht_capabilities_info |= msk;
6166 htcaps->ht_capabilities_info &= ~msk;
6167 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6168
6169 return 0;
6170}
6171
6172
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006173void wpa_supplicant_apply_ht_overrides(
6174 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6175 struct wpa_driver_associate_params *params)
6176{
6177 struct ieee80211_ht_capabilities *htcaps;
6178 struct ieee80211_ht_capabilities *htcaps_mask;
6179
6180 if (!ssid)
6181 return;
6182
6183 params->disable_ht = ssid->disable_ht;
6184 if (!params->htcaps || !params->htcaps_mask)
6185 return;
6186
6187 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6188 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6189 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6190 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6191 ssid->disable_max_amsdu);
6192 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6193 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6194 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006195 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006196 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006197 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6198 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006199
6200 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006201 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006202 htcaps->ht_capabilities_info |= bit;
6203 htcaps_mask->ht_capabilities_info |= bit;
6204 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006205}
6206
6207#endif /* CONFIG_HT_OVERRIDES */
6208
6209
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006210#ifdef CONFIG_VHT_OVERRIDES
6211void wpa_supplicant_apply_vht_overrides(
6212 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6213 struct wpa_driver_associate_params *params)
6214{
6215 struct ieee80211_vht_capabilities *vhtcaps;
6216 struct ieee80211_vht_capabilities *vhtcaps_mask;
6217
6218 if (!ssid)
6219 return;
6220
6221 params->disable_vht = ssid->disable_vht;
6222
6223 vhtcaps = (void *) params->vhtcaps;
6224 vhtcaps_mask = (void *) params->vhtcaps_mask;
6225
6226 if (!vhtcaps || !vhtcaps_mask)
6227 return;
6228
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006229 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6230 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006231
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006232#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006233 if (ssid->disable_sgi) {
6234 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6235 VHT_CAP_SHORT_GI_160);
6236 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6237 VHT_CAP_SHORT_GI_160);
6238 wpa_msg(wpa_s, MSG_DEBUG,
6239 "disable-sgi override specified, vht-caps: 0x%x",
6240 vhtcaps->vht_capabilities_info);
6241 }
6242
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006243 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006244 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6245 int max_ampdu;
6246
6247 max_ampdu = (ssid->vht_capa &
6248 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6249 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006250
6251 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6252 wpa_set_ampdu_factor(wpa_s,
6253 (void *) params->htcaps,
6254 (void *) params->htcaps_mask,
6255 max_ampdu);
6256 }
6257#endif /* CONFIG_HT_OVERRIDES */
6258
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006259#define OVERRIDE_MCS(i) \
6260 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6261 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006262 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006263 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006264 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6265 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006266 } \
6267 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6268 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006269 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006270 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006271 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6272 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006273 }
6274
6275 OVERRIDE_MCS(1);
6276 OVERRIDE_MCS(2);
6277 OVERRIDE_MCS(3);
6278 OVERRIDE_MCS(4);
6279 OVERRIDE_MCS(5);
6280 OVERRIDE_MCS(6);
6281 OVERRIDE_MCS(7);
6282 OVERRIDE_MCS(8);
6283}
6284#endif /* CONFIG_VHT_OVERRIDES */
6285
6286
Hai Shalomfdcde762020-04-02 11:19:20 -07006287#ifdef CONFIG_HE_OVERRIDES
6288void wpa_supplicant_apply_he_overrides(
6289 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6290 struct wpa_driver_associate_params *params)
6291{
6292 if (!ssid)
6293 return;
6294
6295 params->disable_he = ssid->disable_he;
6296}
6297#endif /* CONFIG_HE_OVERRIDES */
6298
6299
Sunil Ravi77d572f2023-01-17 23:58:31 +00006300void wpa_supplicant_apply_eht_overrides(
6301 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6302 struct wpa_driver_associate_params *params)
6303{
6304 if (!ssid)
6305 return;
6306
6307 params->disable_eht = ssid->disable_eht;
6308}
6309
6310
Dmitry Shmidt04949592012-07-19 12:16:46 -07006311static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6312{
6313#ifdef PCSC_FUNCS
6314 size_t len;
6315
6316 if (!wpa_s->conf->pcsc_reader)
6317 return 0;
6318
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006319 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006320 if (!wpa_s->scard)
6321 return 1;
6322
6323 if (wpa_s->conf->pcsc_pin &&
6324 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6325 scard_deinit(wpa_s->scard);
6326 wpa_s->scard = NULL;
6327 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6328 return -1;
6329 }
6330
6331 len = sizeof(wpa_s->imsi) - 1;
6332 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6333 scard_deinit(wpa_s->scard);
6334 wpa_s->scard = NULL;
6335 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6336 return -1;
6337 }
6338 wpa_s->imsi[len] = '\0';
6339
6340 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6341
6342 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6343 wpa_s->imsi, wpa_s->mnc_len);
6344
6345 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6346 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6347#endif /* PCSC_FUNCS */
6348
6349 return 0;
6350}
6351
6352
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006353int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6354{
6355 char *val, *pos;
6356
6357 ext_password_deinit(wpa_s->ext_pw);
6358 wpa_s->ext_pw = NULL;
6359 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6360
6361 if (!wpa_s->conf->ext_password_backend)
6362 return 0;
6363
6364 val = os_strdup(wpa_s->conf->ext_password_backend);
6365 if (val == NULL)
6366 return -1;
6367 pos = os_strchr(val, ':');
6368 if (pos)
6369 *pos++ = '\0';
6370
6371 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6372
6373 wpa_s->ext_pw = ext_password_init(val, pos);
6374 os_free(val);
6375 if (wpa_s->ext_pw == NULL) {
6376 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6377 return -1;
6378 }
6379 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6380
6381 return 0;
6382}
6383
6384
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006385#ifdef CONFIG_FST
6386
6387static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6388{
6389 struct wpa_supplicant *wpa_s = ctx;
6390
6391 return (is_zero_ether_addr(wpa_s->bssid) ||
6392 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6393}
6394
6395
6396static void wpas_fst_get_channel_info_cb(void *ctx,
6397 enum hostapd_hw_mode *hw_mode,
6398 u8 *channel)
6399{
6400 struct wpa_supplicant *wpa_s = ctx;
6401
6402 if (wpa_s->current_bss) {
6403 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6404 channel);
6405 } else if (wpa_s->hw.num_modes) {
6406 *hw_mode = wpa_s->hw.modes[0].mode;
6407 } else {
6408 WPA_ASSERT(0);
6409 *hw_mode = 0;
6410 }
6411}
6412
6413
6414static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6415{
6416 struct wpa_supplicant *wpa_s = ctx;
6417
6418 *modes = wpa_s->hw.modes;
6419 return wpa_s->hw.num_modes;
6420}
6421
6422
6423static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6424{
6425 struct wpa_supplicant *wpa_s = ctx;
6426
6427 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6428 wpa_s->fst_ies = fst_ies;
6429}
6430
6431
6432static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6433{
6434 struct wpa_supplicant *wpa_s = ctx;
6435
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006436 if (!ether_addr_equal(wpa_s->bssid, da)) {
Paul Stewart092955c2017-02-06 09:13:09 -08006437 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6438 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6439 return -1;
6440 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006441 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006442 wpa_s->own_addr, wpa_s->bssid,
6443 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006444 0);
6445}
6446
6447
6448static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6449{
6450 struct wpa_supplicant *wpa_s = ctx;
6451
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006452 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006453 return wpa_s->received_mb_ies;
6454}
6455
6456
6457static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6458 const u8 *buf, size_t size)
6459{
6460 struct wpa_supplicant *wpa_s = ctx;
6461 struct mb_ies_info info;
6462
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006463 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006464
6465 if (!mb_ies_info_by_ies(&info, buf, size)) {
6466 wpabuf_free(wpa_s->received_mb_ies);
6467 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6468 }
6469}
6470
6471
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006472static const u8 * wpas_fst_get_peer_first(void *ctx,
6473 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006474 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006475{
6476 struct wpa_supplicant *wpa_s = ctx;
6477
6478 *get_ctx = NULL;
6479 if (!is_zero_ether_addr(wpa_s->bssid))
6480 return (wpa_s->received_mb_ies || !mb_only) ?
6481 wpa_s->bssid : NULL;
6482 return NULL;
6483}
6484
6485
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006486static const u8 * wpas_fst_get_peer_next(void *ctx,
6487 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006488 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006489{
6490 return NULL;
6491}
6492
6493void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6494 struct fst_wpa_obj *iface_obj)
6495{
Sunil8cd6f4d2022-06-28 18:40:46 +00006496 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006497 iface_obj->ctx = wpa_s;
6498 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6499 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6500 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6501 iface_obj->set_ies = wpas_fst_set_ies_cb;
6502 iface_obj->send_action = wpas_fst_send_action_cb;
6503 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6504 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6505 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6506 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6507}
6508#endif /* CONFIG_FST */
6509
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006510static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006511 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006512{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006513 struct wowlan_triggers *triggers;
6514 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006515
6516 if (!wpa_s->conf->wowlan_triggers)
6517 return 0;
6518
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006519 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6520 if (triggers) {
6521 ret = wpa_drv_wowlan(wpa_s, triggers);
6522 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006523 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006524 return ret;
6525}
6526
6527
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006528enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006529{
6530 if (freq < 3000)
6531 return BAND_2_4_GHZ;
6532 if (freq > 50000)
6533 return BAND_60_GHZ;
6534 return BAND_5_GHZ;
6535}
6536
6537
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006538unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006539{
6540 int i;
6541 unsigned int band = 0;
6542
6543 if (freqs) {
6544 /* freqs are specified for the radio work */
6545 for (i = 0; freqs[i]; i++)
6546 band |= wpas_freq_to_band(freqs[i]);
6547 } else {
6548 /*
6549 * freqs are not specified, implies all
6550 * the supported freqs by HW
6551 */
6552 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6553 if (wpa_s->hw.modes[i].num_channels != 0) {
6554 if (wpa_s->hw.modes[i].mode ==
6555 HOSTAPD_MODE_IEEE80211B ||
6556 wpa_s->hw.modes[i].mode ==
6557 HOSTAPD_MODE_IEEE80211G)
6558 band |= BAND_2_4_GHZ;
6559 else if (wpa_s->hw.modes[i].mode ==
6560 HOSTAPD_MODE_IEEE80211A)
6561 band |= BAND_5_GHZ;
6562 else if (wpa_s->hw.modes[i].mode ==
6563 HOSTAPD_MODE_IEEE80211AD)
6564 band |= BAND_60_GHZ;
6565 else if (wpa_s->hw.modes[i].mode ==
6566 HOSTAPD_MODE_IEEE80211ANY)
6567 band = BAND_2_4_GHZ | BAND_5_GHZ |
6568 BAND_60_GHZ;
6569 }
6570 }
6571 }
6572
6573 return band;
6574}
6575
6576
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006577static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6578 const char *rn)
6579{
6580 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6581 struct wpa_radio *radio;
6582
6583 while (rn && iface) {
6584 radio = iface->radio;
6585 if (radio && os_strcmp(rn, radio->name) == 0) {
6586 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6587 wpa_s->ifname, rn);
6588 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6589 return radio;
6590 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006591
6592 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006593 }
6594
6595 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6596 wpa_s->ifname, rn ? rn : "N/A");
6597 radio = os_zalloc(sizeof(*radio));
6598 if (radio == NULL)
6599 return NULL;
6600
6601 if (rn)
6602 os_strlcpy(radio->name, rn, sizeof(radio->name));
6603 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006604 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006605 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6606
6607 return radio;
6608}
6609
6610
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006611static void radio_work_free(struct wpa_radio_work *work)
6612{
6613 if (work->wpa_s->scan_work == work) {
6614 /* This should not really happen. */
6615 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6616 work->type, work, work->started);
6617 work->wpa_s->scan_work = NULL;
6618 }
6619
6620#ifdef CONFIG_P2P
6621 if (work->wpa_s->p2p_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 p2p_scan_work",
6624 work->type, work, work->started);
6625 work->wpa_s->p2p_scan_work = NULL;
6626 }
6627#endif /* CONFIG_P2P */
6628
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006629 if (work->started) {
6630 work->wpa_s->radio->num_active_works--;
6631 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006632 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006633 work->type, work,
6634 work->wpa_s->radio->num_active_works);
6635 }
6636
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006637 dl_list_del(&work->list);
6638 os_free(work);
6639}
6640
6641
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006642static int radio_work_is_connect(struct wpa_radio_work *work)
6643{
6644 return os_strcmp(work->type, "sme-connect") == 0 ||
6645 os_strcmp(work->type, "connect") == 0;
6646}
6647
6648
6649static int radio_work_is_scan(struct wpa_radio_work *work)
6650{
6651 return os_strcmp(work->type, "scan") == 0 ||
6652 os_strcmp(work->type, "p2p-scan") == 0;
6653}
6654
6655
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006656static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6657{
6658 struct wpa_radio_work *active_work = NULL;
6659 struct wpa_radio_work *tmp;
6660
6661 /* Get the active work to know the type and band. */
6662 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6663 if (tmp->started) {
6664 active_work = tmp;
6665 break;
6666 }
6667 }
6668
6669 if (!active_work) {
6670 /* No active work, start one */
6671 radio->num_active_works = 0;
6672 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6673 list) {
6674 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006675 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006676 (((struct wpa_driver_scan_params *)
6677 tmp->ctx)->only_new_results ||
6678 tmp->wpa_s->clear_driver_scan_cache))
6679 continue;
6680 return tmp;
6681 }
6682 return NULL;
6683 }
6684
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006685 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006686 /*
6687 * If the active work is either connect or sme-connect,
6688 * do not parallelize them with other radio works.
6689 */
6690 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6691 "Do not parallelize radio work with %s",
6692 active_work->type);
6693 return NULL;
6694 }
6695
6696 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6697 if (tmp->started)
6698 continue;
6699
6700 /*
6701 * If connect or sme-connect are enqueued, parallelize only
6702 * those operations ahead of them in the queue.
6703 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006704 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006705 break;
6706
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006707 /* Serialize parallel scan and p2p_scan operations on the same
6708 * interface since the driver_nl80211 mechanism for tracking
6709 * scan cookies does not yet have support for this. */
6710 if (active_work->wpa_s == tmp->wpa_s &&
6711 radio_work_is_scan(active_work) &&
6712 radio_work_is_scan(tmp)) {
6713 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6714 "Do not start work '%s' when another work '%s' is already scheduled",
6715 tmp->type, active_work->type);
6716 continue;
6717 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006718 /*
6719 * Check that the radio works are distinct and
6720 * on different bands.
6721 */
6722 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6723 (active_work->bands != tmp->bands)) {
6724 /*
6725 * If a scan has to be scheduled through nl80211 scan
6726 * interface and if an external scan is already running,
6727 * do not schedule the scan since it is likely to get
6728 * rejected by kernel.
6729 */
6730 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006731 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006732 (((struct wpa_driver_scan_params *)
6733 tmp->ctx)->only_new_results ||
6734 tmp->wpa_s->clear_driver_scan_cache))
6735 continue;
6736
6737 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6738 "active_work:%s new_work:%s",
6739 active_work->type, tmp->type);
6740 return tmp;
6741 }
6742 }
6743
6744 /* Did not find a radio work to schedule in parallel. */
6745 return NULL;
6746}
6747
6748
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006749static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6750{
6751 struct wpa_radio *radio = eloop_ctx;
6752 struct wpa_radio_work *work;
6753 struct os_reltime now, diff;
6754 struct wpa_supplicant *wpa_s;
6755
6756 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006757 if (work == NULL) {
6758 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006759 return;
6760 }
6761
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006762 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6763 radio_list);
6764
6765 if (!(wpa_s &&
6766 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6767 if (work->started)
6768 return; /* already started and still in progress */
6769
Hai Shalom60840252021-02-19 19:02:11 -08006770 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006771 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6772 return;
6773 }
6774 } else {
6775 work = NULL;
6776 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6777 /* get the work to schedule next */
6778 work = radio_work_get_next_work(radio);
6779 }
6780 if (!work)
6781 return;
6782 }
6783
6784 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006785 os_get_reltime(&now);
6786 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006787 wpa_dbg(wpa_s, MSG_DEBUG,
6788 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006789 work->type, work, diff.sec, diff.usec);
6790 work->started = 1;
6791 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006792 radio->num_active_works++;
6793
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006794 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006795
6796 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6797 radio->num_active_works < MAX_ACTIVE_WORKS)
6798 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006799}
6800
6801
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006802/*
6803 * This function removes both started and pending radio works running on
6804 * the provided interface's radio.
6805 * Prior to the removal of the radio work, its callback (cb) is called with
6806 * deinit set to be 1. Each work's callback is responsible for clearing its
6807 * internal data and restoring to a correct state.
6808 * @wpa_s: wpa_supplicant data
6809 * @type: type of works to be removed
6810 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6811 * this interface's works.
6812 */
6813void radio_remove_works(struct wpa_supplicant *wpa_s,
6814 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006815{
6816 struct wpa_radio_work *work, *tmp;
6817 struct wpa_radio *radio = wpa_s->radio;
6818
6819 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6820 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006821 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006822 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006823
6824 /* skip other ifaces' works */
6825 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006826 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006827
6828 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6829 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006830 work->cb(work, 1);
6831 radio_work_free(work);
6832 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006833
6834 /* in case we removed the started work */
6835 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006836}
6837
6838
Roshan Pius3a1667e2018-07-03 15:17:14 -07006839void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6840{
6841 struct wpa_radio_work *work;
6842 struct wpa_radio *radio = wpa_s->radio;
6843
6844 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6845 if (work->ctx != ctx)
6846 continue;
6847 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6848 work->type, work, work->started ? " (started)" : "");
6849 radio_work_free(work);
6850 break;
6851 }
6852}
6853
6854
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006855static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6856{
6857 struct wpa_radio *radio = wpa_s->radio;
6858
6859 if (!radio)
6860 return;
6861
6862 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6863 wpa_s->ifname, radio->name);
6864 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006865 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006866 /* If the interface that triggered the external scan was removed, the
6867 * external scan is no longer running. */
6868 if (wpa_s == radio->external_scan_req_interface)
6869 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006870 wpa_s->radio = NULL;
6871 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006872 return; /* Interfaces remain for this radio */
6873
6874 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006875 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006876 os_free(radio);
6877}
6878
6879
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006880void radio_work_check_next(struct wpa_supplicant *wpa_s)
6881{
6882 struct wpa_radio *radio = wpa_s->radio;
6883
6884 if (dl_list_empty(&radio->work))
6885 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006886 if (wpa_s->ext_work_in_progress) {
6887 wpa_printf(MSG_DEBUG,
6888 "External radio work in progress - delay start of pending item");
6889 return;
6890 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006891 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6892 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6893}
6894
6895
6896/**
6897 * radio_add_work - Add a radio work item
6898 * @wpa_s: Pointer to wpa_supplicant data
6899 * @freq: Frequency of the offchannel operation in MHz or 0
6900 * @type: Unique identifier for each type of work
6901 * @next: Force as the next work to be executed
6902 * @cb: Callback function for indicating when radio is available
6903 * @ctx: Context pointer for the work (work->ctx in cb())
6904 * Returns: 0 on success, -1 on failure
6905 *
6906 * This function is used to request time for an operation that requires
6907 * exclusive radio control. Once the radio is available, the registered callback
6908 * function will be called. radio_work_done() must be called once the exclusive
6909 * radio operation has been completed, so that the radio is freed for other
6910 * operations. The special case of deinit=1 is used to free the context data
6911 * during interface removal. That does not allow the callback function to start
6912 * the radio operation, i.e., it must free any resources allocated for the radio
6913 * work and return.
6914 *
6915 * The @freq parameter can be used to indicate a single channel on which the
6916 * offchannel operation will occur. This may allow multiple radio work
6917 * operations to be performed in parallel if they apply for the same channel.
6918 * Setting this to 0 indicates that the work item may use multiple channels or
6919 * requires exclusive control of the radio.
6920 */
6921int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6922 const char *type, int next,
6923 void (*cb)(struct wpa_radio_work *work, int deinit),
6924 void *ctx)
6925{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006926 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006927 struct wpa_radio_work *work;
6928 int was_empty;
6929
6930 work = os_zalloc(sizeof(*work));
6931 if (work == NULL)
6932 return -1;
6933 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6934 os_get_reltime(&work->time);
6935 work->freq = freq;
6936 work->type = type;
6937 work->wpa_s = wpa_s;
6938 work->cb = cb;
6939 work->ctx = ctx;
6940
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006941 if (freq)
6942 work->bands = wpas_freq_to_band(freq);
6943 else if (os_strcmp(type, "scan") == 0 ||
6944 os_strcmp(type, "p2p-scan") == 0)
6945 work->bands = wpas_get_bands(wpa_s,
6946 ((struct wpa_driver_scan_params *)
6947 ctx)->freqs);
6948 else
6949 work->bands = wpas_get_bands(wpa_s, NULL);
6950
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006951 was_empty = dl_list_empty(&wpa_s->radio->work);
6952 if (next)
6953 dl_list_add(&wpa_s->radio->work, &work->list);
6954 else
6955 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6956 if (was_empty) {
6957 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6958 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006959 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6960 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6961 wpa_dbg(wpa_s, MSG_DEBUG,
6962 "Try to schedule a radio work (num_active_works=%u)",
6963 radio->num_active_works);
6964 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006965 }
6966
6967 return 0;
6968}
6969
6970
6971/**
6972 * radio_work_done - Indicate that a radio work item has been completed
6973 * @work: Completed work
6974 *
6975 * This function is called once the callback function registered with
6976 * radio_add_work() has completed its work.
6977 */
6978void radio_work_done(struct wpa_radio_work *work)
6979{
6980 struct wpa_supplicant *wpa_s = work->wpa_s;
6981 struct os_reltime now, diff;
6982 unsigned int started = work->started;
6983
6984 os_get_reltime(&now);
6985 os_reltime_sub(&now, &work->time, &diff);
6986 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6987 work->type, work, started ? "done" : "canceled",
6988 diff.sec, diff.usec);
6989 radio_work_free(work);
6990 if (started)
6991 radio_work_check_next(wpa_s);
6992}
6993
6994
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006995struct wpa_radio_work *
6996radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006997{
6998 struct wpa_radio_work *work;
6999 struct wpa_radio *radio = wpa_s->radio;
7000
7001 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7002 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007003 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007004 }
7005
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007006 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007007}
7008
7009
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007010static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007011 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007012{
7013 const char *ifname, *driver, *rn;
7014
7015 driver = iface->driver;
7016next_driver:
7017 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
7018 return -1;
7019
7020 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
7021 if (wpa_s->drv_priv == NULL) {
7022 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07007023 int level = MSG_ERROR;
7024
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007025 pos = driver ? os_strchr(driver, ',') : NULL;
7026 if (pos) {
7027 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
7028 "driver interface - try next driver wrapper");
7029 driver = pos + 1;
7030 goto next_driver;
7031 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007032
7033#ifdef CONFIG_MATCH_IFACE
7034 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
7035 level = MSG_DEBUG;
7036#endif /* CONFIG_MATCH_IFACE */
7037 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007038 return -1;
7039 }
7040 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
7041 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
7042 "driver_param '%s'", wpa_s->conf->driver_param);
7043 return -1;
7044 }
7045
7046 ifname = wpa_drv_get_ifname(wpa_s);
7047 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7048 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7049 "interface name with '%s'", ifname);
7050 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7051 }
7052
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007053 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007054 if (rn && rn[0] == '\0')
7055 rn = NULL;
7056
7057 wpa_s->radio = radio_add_interface(wpa_s, rn);
7058 if (wpa_s->radio == NULL)
7059 return -1;
7060
7061 return 0;
7062}
7063
7064
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007065#ifdef CONFIG_GAS_SERVER
7066
7067static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7068 unsigned int freq, const u8 *dst,
7069 const u8 *src, const u8 *bssid,
7070 const u8 *data, size_t data_len,
7071 enum offchannel_send_action_result result)
7072{
7073 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7074 " result=%s",
7075 freq, MAC2STR(dst),
7076 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7077 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7078 "FAILED"));
7079 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7080 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7081}
7082
7083
7084static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7085 struct wpabuf *buf, unsigned int wait_time)
7086{
7087 struct wpa_supplicant *wpa_s = ctx;
7088 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7089
7090 if (wait_time > wpa_s->max_remain_on_chan)
7091 wait_time = wpa_s->max_remain_on_chan;
7092
7093 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7094 wpabuf_head(buf), wpabuf_len(buf),
7095 wait_time, wpas_gas_server_tx_status, 0);
7096}
7097
7098#endif /* CONFIG_GAS_SERVER */
7099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007100static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007101 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007102{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007103 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007104 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007105 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007106
7107 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7108 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7109 iface->confname ? iface->confname : "N/A",
7110 iface->driver ? iface->driver : "default",
7111 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7112 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7113
7114 if (iface->confname) {
7115#ifdef CONFIG_BACKEND_FILE
7116 wpa_s->confname = os_rel2abs_path(iface->confname);
7117 if (wpa_s->confname == NULL) {
7118 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7119 "for configuration file '%s'.",
7120 iface->confname);
7121 return -1;
7122 }
7123 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7124 iface->confname, wpa_s->confname);
7125#else /* CONFIG_BACKEND_FILE */
7126 wpa_s->confname = os_strdup(iface->confname);
7127#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007128 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129 if (wpa_s->conf == NULL) {
7130 wpa_printf(MSG_ERROR, "Failed to read or parse "
7131 "configuration '%s'.", wpa_s->confname);
7132 return -1;
7133 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007134 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007135 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007136 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007137 wpa_printf(MSG_ERROR,
7138 "Failed to read or parse configuration '%s'.",
7139 wpa_s->confanother);
7140 return -1;
7141 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007142
7143 /*
7144 * Override ctrl_interface and driver_param if set on command
7145 * line.
7146 */
7147 if (iface->ctrl_interface) {
7148 os_free(wpa_s->conf->ctrl_interface);
7149 wpa_s->conf->ctrl_interface =
7150 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007151 if (!wpa_s->conf->ctrl_interface) {
7152 wpa_printf(MSG_ERROR,
7153 "Failed to duplicate control interface '%s'.",
7154 iface->ctrl_interface);
7155 return -1;
7156 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007157 }
7158
7159 if (iface->driver_param) {
7160 os_free(wpa_s->conf->driver_param);
7161 wpa_s->conf->driver_param =
7162 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007163 if (!wpa_s->conf->driver_param) {
7164 wpa_printf(MSG_ERROR,
7165 "Failed to duplicate driver param '%s'.",
7166 iface->driver_param);
7167 return -1;
7168 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007169 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007170
7171 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7172 os_free(wpa_s->conf->ctrl_interface);
7173 wpa_s->conf->ctrl_interface = NULL;
7174 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007175 } else
7176 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7177 iface->driver_param);
7178
7179 if (wpa_s->conf == NULL) {
7180 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7181 return -1;
7182 }
7183
7184 if (iface->ifname == NULL) {
7185 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7186 return -1;
7187 }
7188 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7189 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7190 iface->ifname);
7191 return -1;
7192 }
7193 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007194#ifdef CONFIG_MATCH_IFACE
7195 wpa_s->matched = iface->matched;
7196#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007197
7198 if (iface->bridge_ifname) {
7199 if (os_strlen(iface->bridge_ifname) >=
7200 sizeof(wpa_s->bridge_ifname)) {
7201 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7202 "name '%s'.", iface->bridge_ifname);
7203 return -1;
7204 }
7205 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7206 sizeof(wpa_s->bridge_ifname));
7207 }
7208
7209 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007210 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7211 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007212
7213 /* Initialize driver interface and register driver event handler before
7214 * L2 receive handler so that association events are processed before
7215 * EAPOL-Key packets if both become available for the same select()
7216 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007217 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007218 return -1;
7219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007220 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7221 return -1;
7222
7223 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7224 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7225 NULL);
7226 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7227
7228 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7229 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7230 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7231 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7232 "dot11RSNAConfigPMKLifetime");
7233 return -1;
7234 }
7235
7236 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7237 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7238 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7239 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7240 "dot11RSNAConfigPMKReauthThreshold");
7241 return -1;
7242 }
7243
7244 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7245 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7246 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7247 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7248 "dot11RSNAConfigSATimeout");
7249 return -1;
7250 }
7251
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007252 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
7253 wpa_s->conf->ft_prepend_pmkid);
7254
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007255 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7256 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007257 &wpa_s->hw.flags,
7258 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007259 if (wpa_s->hw.modes) {
7260 u16 i;
7261
7262 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7263 if (wpa_s->hw.modes[i].vht_capab) {
7264 wpa_s->hw_capab = CAPAB_VHT;
7265 break;
7266 }
7267
7268 if (wpa_s->hw.modes[i].ht_capab &
7269 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7270 wpa_s->hw_capab = CAPAB_HT40;
7271 else if (wpa_s->hw.modes[i].ht_capab &&
7272 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7273 wpa_s->hw_capab = CAPAB_HT;
7274 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007275 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007276 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007277
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007278 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7279 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007280 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007281 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007282 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007283 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007284 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007285 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007286 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007287 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007288 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007289 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7290 wpa_s->max_sched_scan_plan_interval =
7291 capa.max_sched_scan_plan_interval;
7292 wpa_s->max_sched_scan_plan_iterations =
7293 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007294 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7295 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007296 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7297 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007298 wpa_s->extended_capa = capa.extended_capa;
7299 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7300 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007301 wpa_s->num_multichan_concurrent =
7302 capa.num_multichan_concurrent;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007303#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007304 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007305#endif /* CONFIG_NO_WMM_AC */
Sunil Ravi89eba102022-09-13 21:04:37 -07007306 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007307
7308 if (capa.mac_addr_rand_scan_supported)
7309 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7310 if (wpa_s->sched_scan_supported &&
7311 capa.mac_addr_rand_sched_scan_supported)
7312 wpa_s->mac_addr_rand_supported |=
7313 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007314
7315 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7316 if (wpa_s->extended_capa &&
7317 wpa_s->extended_capa_len >= 3 &&
7318 wpa_s->extended_capa[2] & 0x40)
7319 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007320 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007321#ifdef CONFIG_PASN
7322 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7323#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007324 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7325 !!(wpa_s->drv_flags &
7326 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007327 if (wpa_s->max_remain_on_chan == 0)
7328 wpa_s->max_remain_on_chan = 1000;
7329
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007330 /*
7331 * Only take p2p_mgmt parameters when P2P Device is supported.
7332 * Doing it here as it determines whether l2_packet_init() will be done
7333 * during wpa_supplicant_driver_init().
7334 */
7335 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7336 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007337
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007338 if (wpa_s->num_multichan_concurrent == 0)
7339 wpa_s->num_multichan_concurrent = 1;
7340
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007341 if (wpa_supplicant_driver_init(wpa_s) < 0)
7342 return -1;
7343
7344#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007345 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007346 return -1;
7347#endif /* CONFIG_TDLS */
7348
7349 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7350 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7351 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7352 return -1;
7353 }
7354
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007355#ifdef CONFIG_FST
7356 if (wpa_s->conf->fst_group_id) {
7357 struct fst_iface_cfg cfg;
7358 struct fst_wpa_obj iface_obj;
7359
7360 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7361 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7362 sizeof(cfg.group_id));
7363 cfg.priority = wpa_s->conf->fst_priority;
7364 cfg.llt = wpa_s->conf->fst_llt;
7365
7366 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7367 &iface_obj, &cfg);
7368 if (!wpa_s->fst) {
7369 wpa_msg(wpa_s, MSG_ERROR,
7370 "FST: Cannot attach iface %s to group %s",
7371 wpa_s->ifname, cfg.group_id);
7372 return -1;
7373 }
7374 }
7375#endif /* CONFIG_FST */
7376
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007377 if (wpas_wps_init(wpa_s))
7378 return -1;
7379
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007380#ifdef CONFIG_GAS_SERVER
7381 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7382 if (!wpa_s->gas_server) {
7383 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7384 return -1;
7385 }
7386#endif /* CONFIG_GAS_SERVER */
7387
7388#ifdef CONFIG_DPP
7389 if (wpas_dpp_init(wpa_s) < 0)
7390 return -1;
7391#endif /* CONFIG_DPP */
7392
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007393#ifdef CONFIG_NAN_USD
7394 if (wpas_nan_usd_init(wpa_s) < 0)
7395 return -1;
7396#endif /* CONFIG_NAN_USD */
7397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007398 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7399 return -1;
7400 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7401
7402 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7403 if (wpa_s->ctrl_iface == NULL) {
7404 wpa_printf(MSG_ERROR,
7405 "Failed to initialize control interface '%s'.\n"
7406 "You may have another wpa_supplicant process "
7407 "already running or the file was\n"
7408 "left by an unclean termination of wpa_supplicant "
7409 "in which case you will need\n"
7410 "to manually remove this file before starting "
7411 "wpa_supplicant again.\n",
7412 wpa_s->conf->ctrl_interface);
7413 return -1;
7414 }
7415
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007416 wpa_s->gas = gas_query_init(wpa_s);
7417 if (wpa_s->gas == NULL) {
7418 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7419 return -1;
7420 }
7421
Roshan Pius3a1667e2018-07-03 15:17:14 -07007422 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7423 wpa_s->p2p_mgmt) &&
7424 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007425 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7426 return -1;
7427 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428
7429 if (wpa_bss_init(wpa_s) < 0)
7430 return -1;
7431
Paul Stewart092955c2017-02-06 09:13:09 -08007432#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7433#ifdef CONFIG_MESH
7434 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7435#endif /* CONFIG_MESH */
7436#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7437
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007438 /*
7439 * Set Wake-on-WLAN triggers, if configured.
7440 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7441 * have effect anyway when the interface is down).
7442 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007443 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007444 return -1;
7445
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007446#ifdef CONFIG_EAP_PROXY
7447{
7448 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007449 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7450 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007451 if (wpa_s->mnc_len > 0) {
7452 wpa_s->imsi[len] = '\0';
7453 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7454 wpa_s->imsi, wpa_s->mnc_len);
7455 } else {
7456 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7457 }
7458}
7459#endif /* CONFIG_EAP_PROXY */
7460
Dmitry Shmidt04949592012-07-19 12:16:46 -07007461 if (pcsc_reader_init(wpa_s) < 0)
7462 return -1;
7463
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007464 if (wpas_init_ext_pw(wpa_s) < 0)
7465 return -1;
7466
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007467#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007468 wpas_rrm_reset(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007469#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007470
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007471 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7472
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007473#ifdef CONFIG_HS20
7474 hs20_init(wpa_s);
7475#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007476#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007477 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007478 if ((wpa_s->conf->oce & OCE_STA) &&
7479 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7480 wpa_s->enable_oce = OCE_STA;
7481 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7482 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7483 /* TODO: Need to add STA-CFON support */
7484 wpa_printf(MSG_ERROR,
7485 "OCE STA-CFON feature is not yet supported");
7486 }
7487 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007488 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7489#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007490
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007491 wpa_supplicant_set_default_scan_ies(wpa_s);
7492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007493 return 0;
7494}
7495
7496
7497static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007498 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007499{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007500 struct wpa_global *global = wpa_s->global;
7501 struct wpa_supplicant *iface, *prev;
7502
Jimmy Chen0e73c002021-08-18 13:21:30 +08007503 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007504 wpas_p2p_group_remove(wpa_s, "*");
7505
7506 iface = global->ifaces;
7507 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007508 if (iface->p2pdev == wpa_s)
7509 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007510 if (iface == wpa_s || iface->parent != wpa_s) {
7511 iface = iface->next;
7512 continue;
7513 }
7514 wpa_printf(MSG_DEBUG,
7515 "Remove remaining child interface %s from parent %s",
7516 iface->ifname, wpa_s->ifname);
7517 prev = iface;
7518 iface = iface->next;
7519 wpa_supplicant_remove_iface(global, prev, terminate);
7520 }
7521
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007522 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007523 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007524 /*
7525 * Don't deauthenticate if WoWLAN is enable and not explicitly
7526 * been configured to disconnect.
7527 */
7528 if (!wpa_drv_get_wowlan(wpa_s) ||
7529 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007530 wpa_supplicant_deauthenticate(
7531 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007532
Hai Shalomfdcde762020-04-02 11:19:20 -07007533 wpa_drv_set_countermeasures(wpa_s, 0);
7534 wpa_clear_keys(wpa_s, NULL);
7535 } else {
7536 wpa_msg(wpa_s, MSG_INFO,
7537 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7538 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007539 }
7540
7541 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007542 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007543
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007544 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007545 radio_remove_interface(wpa_s);
7546
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007547#ifdef CONFIG_FST
7548 if (wpa_s->fst) {
7549 fst_detach(wpa_s->fst);
7550 wpa_s->fst = NULL;
7551 }
7552 if (wpa_s->received_mb_ies) {
7553 wpabuf_free(wpa_s->received_mb_ies);
7554 wpa_s->received_mb_ies = NULL;
7555 }
7556#endif /* CONFIG_FST */
7557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007558 if (wpa_s->drv_priv)
7559 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007560
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007561 if (notify)
7562 wpas_notify_iface_removed(wpa_s);
7563
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007564 if (terminate)
7565 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007566
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007567 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7568 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007569
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007570#ifdef CONFIG_MESH
7571 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007572 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007573 wpa_s->ifmsh = NULL;
7574 }
7575#endif /* CONFIG_MESH */
7576
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007577 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007578 wpa_config_free(wpa_s->conf);
7579 wpa_s->conf = NULL;
7580 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007581
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007582 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007583 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007584
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007585 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007586}
7587
7588
Dmitry Shmidte4663042016-04-04 10:07:49 -07007589#ifdef CONFIG_MATCH_IFACE
7590
7591/**
7592 * wpa_supplicant_match_iface - Match an interface description to a name
7593 * @global: Pointer to global data from wpa_supplicant_init()
7594 * @ifname: Name of the interface to match
7595 * Returns: Pointer to the created interface description or %NULL on failure
7596 */
7597struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7598 const char *ifname)
7599{
7600 int i;
7601 struct wpa_interface *iface, *miface;
7602
7603 for (i = 0; i < global->params.match_iface_count; i++) {
7604 miface = &global->params.match_ifaces[i];
7605 if (!miface->ifname ||
7606 fnmatch(miface->ifname, ifname, 0) == 0) {
7607 iface = os_zalloc(sizeof(*iface));
7608 if (!iface)
7609 return NULL;
7610 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007611 if (!miface->ifname)
7612 iface->matched = WPA_IFACE_MATCHED_NULL;
7613 else
7614 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007615 iface->ifname = ifname;
7616 return iface;
7617 }
7618 }
7619
7620 return NULL;
7621}
7622
7623
7624/**
7625 * wpa_supplicant_match_existing - Match existing interfaces
7626 * @global: Pointer to global data from wpa_supplicant_init()
7627 * Returns: 0 on success, -1 on failure
7628 */
7629static int wpa_supplicant_match_existing(struct wpa_global *global)
7630{
7631 struct if_nameindex *ifi, *ifp;
7632 struct wpa_supplicant *wpa_s;
7633 struct wpa_interface *iface;
7634
7635 ifp = if_nameindex();
7636 if (!ifp) {
7637 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7638 return -1;
7639 }
7640
7641 for (ifi = ifp; ifi->if_name; ifi++) {
7642 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7643 if (wpa_s)
7644 continue;
7645 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7646 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007647 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007648 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007649 }
7650 }
7651
7652 if_freenameindex(ifp);
7653 return 0;
7654}
7655
7656#endif /* CONFIG_MATCH_IFACE */
7657
7658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007659/**
7660 * wpa_supplicant_add_iface - Add a new network interface
7661 * @global: Pointer to global data from wpa_supplicant_init()
7662 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007663 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007664 * Returns: Pointer to the created interface or %NULL on failure
7665 *
7666 * This function is used to add new network interfaces for %wpa_supplicant.
7667 * This can be called before wpa_supplicant_run() to add interfaces before the
7668 * main event loop has been started. In addition, new interfaces can be added
7669 * dynamically while %wpa_supplicant is already running. This could happen,
7670 * e.g., when a hotplug network adapter is inserted.
7671 */
7672struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007673 struct wpa_interface *iface,
7674 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007675{
7676 struct wpa_supplicant *wpa_s;
7677 struct wpa_interface t_iface;
7678 struct wpa_ssid *ssid;
7679
7680 if (global == NULL || iface == NULL)
7681 return NULL;
7682
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007683 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007684 if (wpa_s == NULL)
7685 return NULL;
7686
7687 wpa_s->global = global;
7688
7689 t_iface = *iface;
7690 if (global->params.override_driver) {
7691 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7692 "('%s' -> '%s')",
7693 iface->driver, global->params.override_driver);
7694 t_iface.driver = global->params.override_driver;
7695 }
7696 if (global->params.override_ctrl_interface) {
7697 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7698 "ctrl_interface ('%s' -> '%s')",
7699 iface->ctrl_interface,
7700 global->params.override_ctrl_interface);
7701 t_iface.ctrl_interface =
7702 global->params.override_ctrl_interface;
7703 }
7704 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7705 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7706 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007707 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007708 return NULL;
7709 }
7710
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007711 /* Notify the control interfaces about new iface */
7712 if (wpas_notify_iface_added(wpa_s)) {
7713 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7714 return NULL;
7715 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007716
Jimmy Chene2206be2022-07-10 10:25:21 +08007717 /* Notify the control interfaces about new networks */
7718 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7719 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007720 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007721 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7722 && os_strncmp((const char *) ssid->ssid,
7723 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7724 wpas_notify_persistent_group_added(wpa_s, ssid);
7725 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007726 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007727
7728 wpa_s->next = global->ifaces;
7729 global->ifaces = wpa_s;
7730
7731 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007732 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007733
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007734#ifdef CONFIG_P2P
7735 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007736 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007737 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007738 wpas_p2p_add_p2pdev_interface(
7739 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007740 wpa_printf(MSG_INFO,
7741 "P2P: Failed to enable P2P Device interface");
7742 /* Try to continue without. P2P will be disabled. */
7743 }
7744#endif /* CONFIG_P2P */
7745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007746 return wpa_s;
7747}
7748
7749
7750/**
7751 * wpa_supplicant_remove_iface - Remove a network interface
7752 * @global: Pointer to global data from wpa_supplicant_init()
7753 * @wpa_s: Pointer to the network interface to be removed
7754 * Returns: 0 if interface was removed, -1 if interface was not found
7755 *
7756 * This function can be used to dynamically remove network interfaces from
7757 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7758 * addition, this function is used to remove all remaining interfaces when
7759 * %wpa_supplicant is terminated.
7760 */
7761int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007762 struct wpa_supplicant *wpa_s,
7763 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007764{
7765 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007766#ifdef CONFIG_MESH
7767 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7768 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007769 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007770#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771
7772 /* Remove interface from the global list of interfaces */
7773 prev = global->ifaces;
7774 if (prev == wpa_s) {
7775 global->ifaces = wpa_s->next;
7776 } else {
7777 while (prev && prev->next != wpa_s)
7778 prev = prev->next;
7779 if (prev == NULL)
7780 return -1;
7781 prev->next = wpa_s->next;
7782 }
7783
7784 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7785
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007786#ifdef CONFIG_MESH
7787 if (mesh_if_created) {
7788 ifname = os_strdup(wpa_s->ifname);
7789 if (ifname == NULL) {
7790 wpa_dbg(wpa_s, MSG_ERROR,
7791 "mesh: Failed to malloc ifname");
7792 return -1;
7793 }
7794 }
7795#endif /* CONFIG_MESH */
7796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007797 if (global->p2p_group_formation == wpa_s)
7798 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007799 if (global->p2p_invite_group == wpa_s)
7800 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007801 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007802
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007803#ifdef CONFIG_MESH
7804 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007805 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007806 os_free(ifname);
7807 }
7808#endif /* CONFIG_MESH */
7809
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007810 return 0;
7811}
7812
7813
7814/**
7815 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7816 * @wpa_s: Pointer to the network interface
7817 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7818 */
7819const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7820{
7821 const char *eapol_method;
7822
7823 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7824 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7825 return "NO-EAP";
7826 }
7827
7828 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7829 if (eapol_method == NULL)
7830 return "UNKNOWN-EAP";
7831
7832 return eapol_method;
7833}
7834
7835
7836/**
7837 * wpa_supplicant_get_iface - Get a new network interface
7838 * @global: Pointer to global data from wpa_supplicant_init()
7839 * @ifname: Interface name
7840 * Returns: Pointer to the interface or %NULL if not found
7841 */
7842struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7843 const char *ifname)
7844{
7845 struct wpa_supplicant *wpa_s;
7846
7847 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7848 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7849 return wpa_s;
7850 }
7851 return NULL;
7852}
7853
7854
7855#ifndef CONFIG_NO_WPA_MSG
7856static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7857{
7858 struct wpa_supplicant *wpa_s = ctx;
7859 if (wpa_s == NULL)
7860 return NULL;
7861 return wpa_s->ifname;
7862}
7863#endif /* CONFIG_NO_WPA_MSG */
7864
7865
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007866#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7867#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7868#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7869
7870/* Periodic cleanup tasks */
7871static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7872{
7873 struct wpa_global *global = eloop_ctx;
7874 struct wpa_supplicant *wpa_s;
7875
7876 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7877 wpas_periodic, global, NULL);
7878
7879#ifdef CONFIG_P2P
7880 if (global->p2p)
7881 p2p_expire_peers(global->p2p);
7882#endif /* CONFIG_P2P */
7883
7884 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7885 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7886#ifdef CONFIG_AP
7887 ap_periodic(wpa_s);
7888#endif /* CONFIG_AP */
7889 }
7890}
7891
7892
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007893/**
7894 * wpa_supplicant_init - Initialize %wpa_supplicant
7895 * @params: Parameters for %wpa_supplicant
7896 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7897 *
7898 * This function is used to initialize %wpa_supplicant. After successful
7899 * initialization, the returned data pointer can be used to add and remove
7900 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7901 */
7902struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7903{
7904 struct wpa_global *global;
7905 int ret, i;
7906
7907 if (params == NULL)
7908 return NULL;
7909
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007910#ifdef CONFIG_DRIVER_NDIS
7911 {
7912 void driver_ndis_init_ops(void);
7913 driver_ndis_init_ops();
7914 }
7915#endif /* CONFIG_DRIVER_NDIS */
7916
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007917#ifndef CONFIG_NO_WPA_MSG
7918 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7919#endif /* CONFIG_NO_WPA_MSG */
7920
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007921 if (params->wpa_debug_file_path)
7922 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007923 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007924 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007925 if (params->wpa_debug_syslog)
7926 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007927 if (params->wpa_debug_tracing) {
7928 ret = wpa_debug_open_linux_tracing();
7929 if (ret) {
7930 wpa_printf(MSG_ERROR,
7931 "Failed to enable trace logging");
7932 return NULL;
7933 }
7934 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007935
7936 ret = eap_register_methods();
7937 if (ret) {
7938 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7939 if (ret == -2)
7940 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7941 "the same EAP type.");
7942 return NULL;
7943 }
7944
7945 global = os_zalloc(sizeof(*global));
7946 if (global == NULL)
7947 return NULL;
7948 dl_list_init(&global->p2p_srv_bonjour);
7949 dl_list_init(&global->p2p_srv_upnp);
7950 global->params.daemonize = params->daemonize;
7951 global->params.wait_for_monitor = params->wait_for_monitor;
7952 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007953
7954 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007955 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007956 if (!global->params.pid_file) {
7957 wpa_supplicant_deinit(global);
7958 return NULL;
7959 }
7960 }
7961
7962 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007963 global->params.ctrl_interface =
7964 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007965 if (!global->params.ctrl_interface) {
7966 wpa_supplicant_deinit(global);
7967 return NULL;
7968 }
7969 }
7970
7971 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007972 global->params.ctrl_interface_group =
7973 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007974 if (!global->params.ctrl_interface_group) {
7975 wpa_supplicant_deinit(global);
7976 return NULL;
7977 }
7978 }
7979
7980 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007981 global->params.override_driver =
7982 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007983 if (!global->params.override_driver) {
7984 wpa_supplicant_deinit(global);
7985 return NULL;
7986 }
7987 }
7988
7989 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007990 global->params.override_ctrl_interface =
7991 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007992 if (!global->params.override_ctrl_interface) {
7993 wpa_supplicant_deinit(global);
7994 return NULL;
7995 }
7996 }
7997
Dmitry Shmidte4663042016-04-04 10:07:49 -07007998#ifdef CONFIG_MATCH_IFACE
7999 global->params.match_iface_count = params->match_iface_count;
8000 if (params->match_iface_count) {
8001 global->params.match_ifaces =
8002 os_calloc(params->match_iface_count,
8003 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00008004 if (!global->params.match_ifaces) {
8005 wpa_printf(MSG_ERROR,
8006 "Failed to allocate match interfaces");
8007 wpa_supplicant_deinit(global);
8008 return NULL;
8009 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07008010 os_memcpy(global->params.match_ifaces,
8011 params->match_ifaces,
8012 params->match_iface_count *
8013 sizeof(struct wpa_interface));
8014 }
8015#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008016#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00008017 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008018 global->params.conf_p2p_dev =
8019 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008020 if (!global->params.conf_p2p_dev) {
8021 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
8022 wpa_supplicant_deinit(global);
8023 return NULL;
8024 }
8025 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008026#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008027 wpa_debug_level = global->params.wpa_debug_level =
8028 params->wpa_debug_level;
8029 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
8030 params->wpa_debug_show_keys;
8031 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
8032 params->wpa_debug_timestamp;
8033
Hai Shalomfdcde762020-04-02 11:19:20 -07008034 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008035
8036 if (eloop_init()) {
8037 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
8038 wpa_supplicant_deinit(global);
8039 return NULL;
8040 }
8041
Jouni Malinen75ecf522011-06-27 15:19:46 -07008042 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008043
8044 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
8045 if (global->ctrl_iface == NULL) {
8046 wpa_supplicant_deinit(global);
8047 return NULL;
8048 }
8049
8050 if (wpas_notify_supplicant_initialized(global)) {
8051 wpa_supplicant_deinit(global);
8052 return NULL;
8053 }
8054
8055 for (i = 0; wpa_drivers[i]; i++)
8056 global->drv_count++;
8057 if (global->drv_count == 0) {
8058 wpa_printf(MSG_ERROR, "No drivers enabled");
8059 wpa_supplicant_deinit(global);
8060 return NULL;
8061 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008062 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008063 if (global->drv_priv == NULL) {
8064 wpa_supplicant_deinit(global);
8065 return NULL;
8066 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008068#ifdef CONFIG_WIFI_DISPLAY
8069 if (wifi_display_init(global) < 0) {
8070 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8071 wpa_supplicant_deinit(global);
8072 return NULL;
8073 }
8074#endif /* CONFIG_WIFI_DISPLAY */
8075
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008076 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8077 wpas_periodic, global, NULL);
8078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008079 return global;
8080}
8081
8082
8083/**
8084 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8085 * @global: Pointer to global data from wpa_supplicant_init()
8086 * Returns: 0 after successful event loop run, -1 on failure
8087 *
8088 * This function starts the main event loop and continues running as long as
8089 * there are any remaining events. In most cases, this function is running as
8090 * long as the %wpa_supplicant process in still in use.
8091 */
8092int wpa_supplicant_run(struct wpa_global *global)
8093{
8094 struct wpa_supplicant *wpa_s;
8095
8096 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008097 (wpa_supplicant_daemon(global->params.pid_file) ||
8098 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008099 return -1;
8100
Dmitry Shmidte4663042016-04-04 10:07:49 -07008101#ifdef CONFIG_MATCH_IFACE
8102 if (wpa_supplicant_match_existing(global))
8103 return -1;
8104#endif
8105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008106 if (global->params.wait_for_monitor) {
8107 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008108 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008109 wpa_supplicant_ctrl_iface_wait(
8110 wpa_s->ctrl_iface);
8111 }
8112
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008113#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008114 // If daemonize is enabled, initialize AIDL here.
8115 if (global->params.daemonize) {
8116 global->aidl = wpas_aidl_init(global);
8117 if (!global->aidl)
8118 return -1;
8119 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008120#endif /* CONFIG_AIDL */
8121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008122 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8123 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8124
8125 eloop_run();
8126
8127 return 0;
8128}
8129
8130
8131/**
8132 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8133 * @global: Pointer to global data from wpa_supplicant_init()
8134 *
8135 * This function is called to deinitialize %wpa_supplicant and to free all
8136 * allocated resources. Remaining network interfaces will also be removed.
8137 */
8138void wpa_supplicant_deinit(struct wpa_global *global)
8139{
8140 int i;
8141
8142 if (global == NULL)
8143 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008144
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008145 eloop_cancel_timeout(wpas_periodic, global, NULL);
8146
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008147#ifdef CONFIG_WIFI_DISPLAY
8148 wifi_display_deinit(global);
8149#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008150
8151 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008152 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008153
8154 if (global->ctrl_iface)
8155 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8156
8157 wpas_notify_supplicant_deinitialized(global);
8158
8159 eap_peer_unregister_methods();
8160#ifdef CONFIG_AP
8161 eap_server_unregister_methods();
8162#endif /* CONFIG_AP */
8163
8164 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8165 if (!global->drv_priv[i])
8166 continue;
8167 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8168 }
8169 os_free(global->drv_priv);
8170
8171 random_deinit();
8172
8173 eloop_destroy();
8174
8175 if (global->params.pid_file) {
8176 os_daemonize_terminate(global->params.pid_file);
8177 os_free(global->params.pid_file);
8178 }
8179 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008180 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008181 os_free(global->params.override_driver);
8182 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008183#ifdef CONFIG_MATCH_IFACE
8184 os_free(global->params.match_ifaces);
8185#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008186#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008187 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008188#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008189
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008190 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008191 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008192 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008193
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008194 os_free(global);
8195 wpa_debug_close_syslog();
8196 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008197 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008198}
8199
8200
8201void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8202{
8203 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8204 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8205 char country[3];
8206 country[0] = wpa_s->conf->country[0];
8207 country[1] = wpa_s->conf->country[1];
8208 country[2] = '\0';
8209 if (wpa_drv_set_country(wpa_s, country) < 0) {
8210 wpa_printf(MSG_ERROR, "Failed to set country code "
8211 "'%s'", country);
8212 }
8213 }
8214
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008215 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8216 wpas_init_ext_pw(wpa_s);
8217
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008218 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8219 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8220
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008221 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8222 struct wpa_driver_capa capa;
8223 int res = wpa_drv_get_capa(wpa_s, &capa);
8224
8225 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8226 wpa_printf(MSG_ERROR,
8227 "Failed to update wowlan_triggers to '%s'",
8228 wpa_s->conf->wowlan_triggers);
8229 }
8230
Hai Shalom81f62d82019-07-22 12:10:00 -07008231 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8232 wpa_supplicant_set_default_scan_ies(wpa_s);
8233
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008234 if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
8235 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
8236 wpa_s->conf->ft_prepend_pmkid);
8237
Hai Shalom899fcc72020-10-19 14:38:18 -07008238#ifdef CONFIG_BGSCAN
8239 /*
8240 * We default to global bgscan parameters only when per-network bgscan
8241 * parameters aren't set. Only bother resetting bgscan parameters if
8242 * this is the case.
8243 */
8244 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8245 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8246 wpa_s->wpa_state == WPA_COMPLETED)
8247 wpa_supplicant_reset_bgscan(wpa_s);
8248#endif /* CONFIG_BGSCAN */
8249
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008250#ifdef CONFIG_WPS
8251 wpas_wps_update_config(wpa_s);
8252#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008253 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008254 wpa_s->conf->changed_parameters = 0;
8255}
8256
8257
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008258void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008259{
8260 int i;
8261
8262 for (i = 0; i < *num_freqs; i++) {
8263 if (freqs[i] == freq)
8264 return;
8265 }
8266
8267 freqs[*num_freqs] = freq;
8268 (*num_freqs)++;
8269}
8270
8271
8272static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8273{
8274 struct wpa_bss *bss, *cbss;
8275 const int max_freqs = 10;
8276 int *freqs;
8277 int num_freqs = 0;
8278
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008279 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008280 if (freqs == NULL)
8281 return NULL;
8282
8283 cbss = wpa_s->current_bss;
8284
8285 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8286 if (bss == cbss)
8287 continue;
8288 if (bss->ssid_len == cbss->ssid_len &&
8289 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008290 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008291 add_freq(freqs, &num_freqs, bss->freq);
8292 if (num_freqs == max_freqs)
8293 break;
8294 }
8295 }
8296
8297 if (num_freqs == 0) {
8298 os_free(freqs);
8299 freqs = NULL;
8300 }
8301
8302 return freqs;
8303}
8304
8305
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008306void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
8307 const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008308{
8309 int timeout;
8310 int count;
8311 int *freqs = NULL;
8312
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008313 wpas_connect_work_done(wpa_s);
8314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008315 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008316 * Remove possible authentication timeout since the connection failed.
8317 */
8318 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8319
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008320 /*
Hai Shalom60840252021-02-19 19:02:11 -08008321 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008322 * generated based on local request to disconnect.
8323 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008324 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008325 wpa_s->own_disconnect_req = 0;
8326 wpa_dbg(wpa_s, MSG_DEBUG,
8327 "Ignore connection failure due to local request to disconnect");
8328 return;
8329 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008330 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008331 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8332 "indication since interface has been put into "
8333 "disconnected state");
8334 return;
8335 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008336 if (wpa_s->auto_reconnect_disabled) {
8337 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8338 "indication since auto connect is disabled");
8339 return;
8340 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008341
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008342 /* Also mark links as failed */
8343 while (link_bssids && *link_bssids) {
8344 wpa_bssid_ignore_add(wpa_s, *link_bssids);
8345 link_bssids++;
8346 }
8347
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008348 /*
Hai Shalom60840252021-02-19 19:02:11 -08008349 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008350 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008351 */
Hai Shalom60840252021-02-19 19:02:11 -08008352 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008353 if (count == 1 && wpa_s->current_bss) {
8354 /*
Hai Shalom60840252021-02-19 19:02:11 -08008355 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008356 * another BSS available for the same ESS, we should try that
8357 * next. Otherwise, we may as well try this one once more
8358 * before allowing other, likely worse, ESSes to be considered.
8359 */
8360 freqs = get_bss_freqs_in_ess(wpa_s);
8361 if (freqs) {
8362 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8363 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008364 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008365 /*
8366 * On the next scan, go through only the known channels
8367 * used in this ESS based on previous scans to speed up
8368 * common load balancing use case.
8369 */
8370 os_free(wpa_s->next_scan_freqs);
8371 wpa_s->next_scan_freqs = freqs;
8372 }
8373 }
8374
Hai Shalom899fcc72020-10-19 14:38:18 -07008375 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008376
Hai Shalom899fcc72020-10-19 14:38:18 -07008377 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008378 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8379 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008380 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008381 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008382 /*
8383 * Multiple consecutive connection failures mean that other APs are
8384 * either not available or have already been tried, so we can start
8385 * increasing the delay here to avoid constant scanning.
8386 */
8387 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008388 case 1:
8389 timeout = 100;
8390 break;
8391 case 2:
8392 timeout = 500;
8393 break;
8394 case 3:
8395 timeout = 1000;
8396 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008397 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008398 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008399 break;
8400 default:
8401 timeout = 10000;
8402 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008403 }
8404
Hai Shalom899fcc72020-10-19 14:38:18 -07008405 wpa_dbg(wpa_s, MSG_DEBUG,
8406 "Consecutive connection failures: %d --> request scan in %d ms",
8407 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008409 /*
8410 * TODO: if more than one possible AP is available in scan results,
8411 * could try the other ones before requesting a new scan.
8412 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008413
8414 /* speed up the connection attempt with normal scan */
8415 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008416 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8417 1000 * (timeout % 1000));
8418}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008419
8420
Hai Shalomce48b4a2018-09-05 11:41:35 -07008421#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008422
8423void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8424{
8425 struct wpa_ssid *ssid = wpa_s->current_ssid;
8426 const u8 *realm, *username, *rrk;
8427 size_t realm_len, username_len, rrk_len;
8428 u16 next_seq_num;
8429
8430 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8431 * Check for ERP keys existing to limit when this can be done since
8432 * the rejection response is not protected and such triggers should
8433 * really not allow internal state to be modified unless required to
8434 * avoid significant issues in functionality. In addition, drop
8435 * externally configure PMKSA entries even without ERP keys since it
8436 * is possible for an external component to add PMKSA entries for FILS
8437 * authentication without restoring previously generated ERP keys.
8438 *
8439 * In this case, this is needed to allow recovery from cases where the
8440 * AP or authentication server has dropped PMKSAs and ERP keys. */
8441 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8442 return;
8443
8444 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8445 &username, &username_len,
8446 &realm, &realm_len, &next_seq_num,
8447 &rrk, &rrk_len) != 0 ||
8448 !realm) {
8449 wpa_dbg(wpa_s, MSG_DEBUG,
8450 "FILS: Drop external PMKSA cache entry");
8451 wpa_sm_aborted_external_cached(wpa_s->wpa);
8452 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8453 return;
8454 }
8455
8456 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8457 wpa_sm_aborted_cached(wpa_s->wpa);
8458 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8459}
8460
8461
Hai Shalomce48b4a2018-09-05 11:41:35 -07008462void fils_connection_failure(struct wpa_supplicant *wpa_s)
8463{
8464 struct wpa_ssid *ssid = wpa_s->current_ssid;
8465 const u8 *realm, *username, *rrk;
8466 size_t realm_len, username_len, rrk_len;
8467 u16 next_seq_num;
8468
8469 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8470 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8471 &username, &username_len,
8472 &realm, &realm_len, &next_seq_num,
8473 &rrk, &rrk_len) != 0 ||
8474 !realm)
8475 return;
8476
8477 wpa_hexdump_ascii(MSG_DEBUG,
8478 "FILS: Store last connection failure realm",
8479 realm, realm_len);
8480 os_free(wpa_s->last_con_fail_realm);
8481 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8482 if (wpa_s->last_con_fail_realm) {
8483 wpa_s->last_con_fail_realm_len = realm_len;
8484 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8485 }
8486}
8487#endif /* CONFIG_FILS */
8488
8489
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008490int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8491{
8492 return wpa_s->conf->ap_scan == 2 ||
8493 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8494}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008495
Dmitry Shmidt04949592012-07-19 12:16:46 -07008496
Gabriel Biren57ededa2021-09-03 16:08:50 +00008497#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008498int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8499 struct wpa_ssid *ssid,
8500 const char *field,
8501 const char *value)
8502{
8503#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008504 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008505
8506 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8507 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8508 (const u8 *) value, os_strlen(value));
8509
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008510 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008511 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008512#else /* IEEE8021X_EAPOL */
8513 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8514 return -1;
8515#endif /* IEEE8021X_EAPOL */
8516}
8517
8518int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8519 struct wpa_ssid *ssid,
8520 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008521 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008522{
8523#ifdef IEEE8021X_EAPOL
8524 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008525 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008526
8527 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008528 case WPA_CTRL_REQ_EAP_IDENTITY:
8529 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008530 os_free(eap->imsi_identity);
8531 if (value == NULL)
8532 return -1;
8533 identity = os_strchr(value, ':');
8534 if (identity == NULL) {
8535 /* plain identity */
8536 eap->identity = (u8 *)os_strdup(value);
8537 eap->identity_len = os_strlen(value);
8538 } else {
8539 /* have both plain identity and encrypted identity */
8540 imsi_identity = value;
8541 *identity++ = '\0';
8542 /* plain identity */
8543 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8544 eap->imsi_identity_len = strlen(imsi_identity);
8545 /* encrypted identity */
8546 eap->identity = (u8 *)dup_binstr(identity,
8547 value_len - strlen(imsi_identity) - 1);
8548 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8549 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008550 eap->pending_req_identity = 0;
8551 if (ssid == wpa_s->current_ssid)
8552 wpa_s->reassociate = 1;
8553 break;
8554 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008555 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008556 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008557 if (!eap->password)
8558 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008559 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008560 eap->pending_req_password = 0;
8561 if (ssid == wpa_s->current_ssid)
8562 wpa_s->reassociate = 1;
8563 break;
8564 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008565 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008566 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008567 if (!eap->new_password)
8568 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008569 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008570 eap->pending_req_new_password = 0;
8571 if (ssid == wpa_s->current_ssid)
8572 wpa_s->reassociate = 1;
8573 break;
8574 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008575 str_clear_free(eap->cert.pin);
8576 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008577 if (!eap->cert.pin)
8578 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008579 eap->pending_req_pin = 0;
8580 if (ssid == wpa_s->current_ssid)
8581 wpa_s->reassociate = 1;
8582 break;
8583 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008584 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008585 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008586 if (!eap->otp)
8587 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008588 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008589 os_free(eap->pending_req_otp);
8590 eap->pending_req_otp = NULL;
8591 eap->pending_req_otp_len = 0;
8592 break;
8593 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008594 str_clear_free(eap->cert.private_key_passwd);
8595 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008596 if (!eap->cert.private_key_passwd)
8597 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008598 eap->pending_req_passphrase = 0;
8599 if (ssid == wpa_s->current_ssid)
8600 wpa_s->reassociate = 1;
8601 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008602 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008603 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008604 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008605 if (!eap->external_sim_resp)
8606 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008607 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008608 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008609 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8610 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8611 return -1;
8612 ssid->mem_only_psk = 1;
8613 if (ssid->passphrase)
8614 wpa_config_update_psk(ssid);
8615 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8616 wpa_supplicant_req_scan(wpa_s, 0, 0);
8617 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008618 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8619 if (eap->pending_ext_cert_check != PENDING_CHECK)
8620 return -1;
8621 if (os_strcmp(value, "good") == 0)
8622 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8623 else if (os_strcmp(value, "bad") == 0)
8624 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8625 else
8626 return -1;
8627 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008628 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008629 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008630 return -1;
8631 }
8632
8633 return 0;
8634#else /* IEEE8021X_EAPOL */
8635 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8636 return -1;
8637#endif /* IEEE8021X_EAPOL */
8638}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008639#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008640
8641
8642int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8643{
Hai Shalomfdcde762020-04-02 11:19:20 -07008644#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008645 int i;
8646 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008647#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008648
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008649 if (wpa_s->p2p_mgmt)
8650 return 1; /* no normal network profiles on p2p_mgmt interface */
8651
Dmitry Shmidt04949592012-07-19 12:16:46 -07008652 if (ssid == NULL)
8653 return 1;
8654
8655 if (ssid->disabled)
8656 return 1;
8657
Hai Shalomfdcde762020-04-02 11:19:20 -07008658#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008659 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008660 drv_enc = wpa_s->drv_enc;
8661 else
8662 drv_enc = (unsigned int) -1;
8663
8664 for (i = 0; i < NUM_WEP_KEYS; i++) {
8665 size_t len = ssid->wep_key_len[i];
8666 if (len == 0)
8667 continue;
8668 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8669 continue;
8670 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8671 continue;
8672 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8673 continue;
8674 return 1; /* invalid WEP key */
8675 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008676#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008677
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008678 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008679 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008680 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008681 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008682 return 1;
8683
Sunil Ravi89eba102022-09-13 21:04:37 -07008684#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008685#ifdef CRYPTO_RSA_OAEP_SHA256
8686 if (ssid->eap.imsi_privacy_cert) {
8687 struct crypto_rsa_key *key;
8688 bool failed = false;
8689
8690 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8691 if (!key)
8692 failed = true;
8693 crypto_rsa_key_free(key);
8694 if (failed) {
8695 wpa_printf(MSG_DEBUG,
8696 "Invalid imsi_privacy_cert (%s) - disable network",
8697 ssid->eap.imsi_privacy_cert);
8698 return 1;
8699 }
8700 }
8701#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008702#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008703
Dmitry Shmidt04949592012-07-19 12:16:46 -07008704 return 0;
8705}
8706
8707
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008708int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8709{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008710 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8711 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8712 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8713 /*
8714 * Driver does not support BIP -- ignore pmf=1 default
8715 * since the connection with PMF would fail and the
8716 * configuration does not require PMF to be enabled.
8717 */
8718 return NO_MGMT_FRAME_PROTECTION;
8719 }
8720
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008721 if (ssid &&
8722 (ssid->key_mgmt &
8723 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8724 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8725 /*
8726 * Do not use the default PMF value for non-RSN networks
8727 * since PMF is available only with RSN and pmf=2
8728 * configuration would otherwise prevent connections to
8729 * all open networks.
8730 */
8731 return NO_MGMT_FRAME_PROTECTION;
8732 }
8733
Sunil Ravi77d572f2023-01-17 23:58:31 +00008734#ifdef CONFIG_OCV
8735 /* Enable PMF if OCV is being enabled */
8736 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8737 ssid && ssid->ocv)
8738 return MGMT_FRAME_PROTECTION_OPTIONAL;
8739#endif /* CONFIG_OCV */
8740
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008741 return wpa_s->conf->pmf;
8742 }
8743
8744 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008745}
8746
8747
Sunil Ravi77d572f2023-01-17 23:58:31 +00008748#ifdef CONFIG_SAE
8749bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8750 struct wpa_ssid *ssid,
8751 const struct wpa_ie_data *ie)
8752{
8753 return wpa_s->conf->sae_check_mfp &&
8754 (!(ie->capabilities &
8755 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8756 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8757}
8758#endif /* CONFIG_SAE */
8759
8760
Hai Shalomc1a21442022-02-04 13:43:00 -08008761int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8762{
8763 if (wpa_s->current_ssid == NULL ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008764 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
Hai Shalomc1a21442022-02-04 13:43:00 -08008765 return 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008766 if (wpa_s->valid_links) {
8767 if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
8768 !wpas_ap_link_address(wpa_s, addr))
8769 return 0;
8770 } else {
8771 if (!ether_addr_equal(addr, wpa_s->bssid))
8772 return 0;
8773 }
Hai Shalomc1a21442022-02-04 13:43:00 -08008774 return wpa_sm_pmf_enabled(wpa_s->wpa);
8775}
8776
8777
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008778int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008779{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008780 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008781 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008782 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008783 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008784 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008785}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008786
8787
Sunil Ravi77d572f2023-01-17 23:58:31 +00008788void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8789 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008790{
8791 struct wpa_ssid *ssid = wpa_s->current_ssid;
8792 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008793 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008794
8795 if (ssid == NULL) {
8796 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8797 "SSID block");
8798 return;
8799 }
8800
8801 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8802 return;
8803
8804 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008805
8806#ifdef CONFIG_P2P
8807 if (ssid->p2p_group &&
8808 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8809 /*
8810 * Skip the wait time since there is a short timeout on the
8811 * connection to a P2P group.
8812 */
8813 return;
8814 }
8815#endif /* CONFIG_P2P */
8816
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008817 if (ssid->auth_failures > 50)
8818 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008819 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008820 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008821 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008822 dur = 90;
8823 else if (ssid->auth_failures > 3)
8824 dur = 60;
8825 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008826 dur = 30;
8827 else if (ssid->auth_failures > 1)
8828 dur = 20;
8829 else
8830 dur = 10;
8831
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008832 if (ssid->auth_failures > 1 &&
8833 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8834 dur += os_random() % (ssid->auth_failures * 10);
8835
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008836 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008837 if (now.sec + dur <= ssid->disabled_until.sec)
8838 return;
8839
8840 ssid->disabled_until.sec = now.sec + dur;
8841
8842 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008843 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008844 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008845 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008846
8847 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8848 int msg_len = snprintf(NULL, 0, format_str,
8849 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8850 ssid->auth_failures, dur, reason) + 1;
8851 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308852 if (!msg)
8853 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008854 snprintf(msg, msg_len, format_str,
8855 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8856 ssid->auth_failures, dur, reason);
8857 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8858 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008859
8860 if (bssid)
8861 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008862}
8863
8864
8865void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8866 struct wpa_ssid *ssid, int clear_failures)
8867{
8868 if (ssid == NULL)
8869 return;
8870
8871 if (ssid->disabled_until.sec) {
8872 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8873 "id=%d ssid=\"%s\"",
8874 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8875 }
8876 ssid->disabled_until.sec = 0;
8877 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008878 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008879 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008880 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8881 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8882 " ignored to allow a lower priority BSS, if any, to be tried next",
8883 MAC2STR(ssid->disabled_due_to));
8884 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8885 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8886 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008887}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008888
8889
8890int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8891{
8892 size_t i;
8893
8894 if (wpa_s->disallow_aps_bssid == NULL)
8895 return 0;
8896
8897 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008898 if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8899 bssid))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008900 return 1;
8901 }
8902
8903 return 0;
8904}
8905
8906
8907int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8908 size_t ssid_len)
8909{
8910 size_t i;
8911
8912 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8913 return 0;
8914
8915 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8916 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8917 if (ssid_len == s->ssid_len &&
8918 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8919 return 1;
8920 }
8921
8922 return 0;
8923}
8924
8925
8926/**
8927 * wpas_request_connection - Request a new connection
8928 * @wpa_s: Pointer to the network interface
8929 *
8930 * This function is used to request a new connection to be found. It will mark
8931 * the interface to allow reassociation and request a new scan to find a
8932 * suitable network to connect to.
8933 */
8934void wpas_request_connection(struct wpa_supplicant *wpa_s)
8935{
8936 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008937 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008938 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008939 wpa_s->disconnected = 0;
8940 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008941 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008942
8943 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8944 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008945 else
8946 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008947}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008948
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008949
Roshan Pius02242d72016-08-09 15:31:48 -07008950/**
8951 * wpas_request_disconnection - Request disconnection
8952 * @wpa_s: Pointer to the network interface
8953 *
8954 * This function is used to request disconnection from the currently connected
8955 * network. This will stop any ongoing scans and initiate deauthentication.
8956 */
8957void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8958{
8959#ifdef CONFIG_SME
8960 wpa_s->sme.prev_bssid_set = 0;
8961#endif /* CONFIG_SME */
8962 wpa_s->reassociate = 0;
8963 wpa_s->disconnected = 1;
8964 wpa_supplicant_cancel_sched_scan(wpa_s);
8965 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008966 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008967 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8968 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008969 radio_remove_works(wpa_s, "connect", 0);
8970 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008971 wpa_s->roam_in_progress = false;
8972#ifdef CONFIG_WNM
8973 wpa_s->bss_trans_mgmt_in_progress = false;
8974#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008975}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008976
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008977
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008978void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8979 struct wpa_used_freq_data *freqs_data,
8980 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008981{
8982 unsigned int i;
8983
8984 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8985 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008986 for (i = 0; i < len; i++) {
8987 struct wpa_used_freq_data *cur = &freqs_data[i];
8988 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8989 i, cur->freq, cur->flags);
8990 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008991}
8992
8993
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008994/*
8995 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008996 * are using the same radio as the current interface, and in addition, get
8997 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008998 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008999int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
9000 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009001 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009002{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009003 struct wpa_supplicant *ifs;
9004 u8 bssid[ETH_ALEN];
9005 int freq;
9006 unsigned int idx = 0, i;
9007
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009008 wpa_dbg(wpa_s, MSG_DEBUG,
9009 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009010 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009011
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009012 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
9013 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009014 if (idx == len)
9015 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009016
Sunil Ravi77d572f2023-01-17 23:58:31 +00009017 if (exclude_current && ifs == wpa_s)
9018 continue;
9019
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009020 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
9021 continue;
9022
9023 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009024 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
9025 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009026 freq = ifs->current_ssid->frequency;
9027 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
9028 freq = ifs->assoc_freq;
9029 else
9030 continue;
9031
9032 /* Hold only distinct freqs */
9033 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009034 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009035 break;
9036
9037 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009038 freqs_data[idx++].freq = freq;
9039
9040 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009041 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009042 WPA_FREQ_USED_BY_P2P_CLIENT :
9043 WPA_FREQ_USED_BY_INFRA_STATION;
9044 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009045 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009046
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009047 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009048 return idx;
9049}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009050
9051
9052/*
9053 * Find the operating frequencies of any of the virtual interfaces that
9054 * are using the same radio as the current interface.
9055 */
9056int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009057 int *freq_array, unsigned int len,
9058 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009059{
9060 struct wpa_used_freq_data *freqs_data;
9061 int num, i;
9062
9063 os_memset(freq_array, 0, sizeof(int) * len);
9064
9065 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
9066 if (!freqs_data)
9067 return -1;
9068
Sunil Ravi77d572f2023-01-17 23:58:31 +00009069 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
9070 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009071 for (i = 0; i < num; i++)
9072 freq_array[i] = freqs_data[i].freq;
9073
9074 os_free(freqs_data);
9075
9076 return num;
9077}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009078
9079
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009080struct wpa_supplicant *
9081wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9082{
9083 switch (frame) {
9084#ifdef CONFIG_P2P
9085 case VENDOR_ELEM_PROBE_REQ_P2P:
9086 case VENDOR_ELEM_PROBE_RESP_P2P:
9087 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9088 case VENDOR_ELEM_BEACON_P2P_GO:
9089 case VENDOR_ELEM_P2P_PD_REQ:
9090 case VENDOR_ELEM_P2P_PD_RESP:
9091 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9092 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9093 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9094 case VENDOR_ELEM_P2P_INV_REQ:
9095 case VENDOR_ELEM_P2P_INV_RESP:
9096 case VENDOR_ELEM_P2P_ASSOC_REQ:
9097 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009098 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009099#endif /* CONFIG_P2P */
9100 default:
9101 return wpa_s;
9102 }
9103}
9104
9105
9106void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9107{
9108 unsigned int i;
9109 char buf[30];
9110
9111 wpa_printf(MSG_DEBUG, "Update vendor elements");
9112
9113 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9114 if (wpa_s->vendor_elem[i]) {
9115 int res;
9116
9117 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9118 if (!os_snprintf_error(sizeof(buf), res)) {
9119 wpa_hexdump_buf(MSG_DEBUG, buf,
9120 wpa_s->vendor_elem[i]);
9121 }
9122 }
9123 }
9124
9125#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009126 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009127 wpa_s->global->p2p &&
9128 !wpa_s->global->p2p_disabled)
9129 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9130#endif /* CONFIG_P2P */
9131}
9132
9133
9134int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9135 const u8 *elem, size_t len)
9136{
9137 u8 *ie, *end;
9138
9139 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9140 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9141
9142 for (; ie + 1 < end; ie += 2 + ie[1]) {
9143 if (ie + len > end)
9144 break;
9145 if (os_memcmp(ie, elem, len) != 0)
9146 continue;
9147
9148 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9149 wpabuf_free(wpa_s->vendor_elem[frame]);
9150 wpa_s->vendor_elem[frame] = NULL;
9151 } else {
9152 os_memmove(ie, ie + len, end - (ie + len));
9153 wpa_s->vendor_elem[frame]->used -= len;
9154 }
9155 wpas_vendor_elem_update(wpa_s);
9156 return 0;
9157 }
9158
9159 return -1;
9160}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009161
9162
9163struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009164 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009165 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009166{
9167 u16 i;
9168
Hai Shalomc1a21442022-02-04 13:43:00 -08009169 if (!modes)
9170 return NULL;
9171
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009172 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009173 if (modes[i].mode != mode ||
9174 !modes[i].num_channels || !modes[i].channels)
9175 continue;
Sunil Ravi88611412024-06-28 17:34:56 +00009176 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
9177 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009178 return &modes[i];
9179 }
9180
9181 return NULL;
9182}
9183
9184
Hai Shalomc1a21442022-02-04 13:43:00 -08009185struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9186 u16 num_modes, int freq)
9187{
9188 int i, j;
9189
9190 for (i = 0; i < num_modes; i++) {
9191 for (j = 0; j < modes[i].num_channels; j++) {
9192 if (freq == modes[i].channels[j].freq)
9193 return &modes[i];
9194 }
9195 }
9196
9197 return NULL;
9198}
9199
9200
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009201static struct
9202wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9203 const u8 *bssid)
9204{
9205 struct wpa_bss_tmp_disallowed *bss;
9206
9207 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9208 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009209 if (ether_addr_equal(bssid, bss->bssid))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009210 return bss;
9211 }
9212
9213 return NULL;
9214}
9215
9216
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009217static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9218{
9219 struct wpa_bss_tmp_disallowed *tmp;
9220 unsigned int num_bssid = 0;
9221 u8 *bssids;
9222 int ret;
9223
9224 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9225 if (!bssids)
9226 return -1;
9227 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9228 struct wpa_bss_tmp_disallowed, list) {
9229 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9230 ETH_ALEN);
9231 num_bssid++;
9232 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009233 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009234 os_free(bssids);
9235 return ret;
9236}
9237
9238
9239static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9240{
9241 struct wpa_supplicant *wpa_s = eloop_ctx;
9242 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9243
9244 /* Make sure the bss is not already freed */
9245 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9246 struct wpa_bss_tmp_disallowed, list) {
9247 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009248 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009249 wpa_set_driver_tmp_disallow_list(wpa_s);
9250 break;
9251 }
9252 }
9253}
9254
9255
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009256void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009257 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009258{
9259 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009260
9261 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9262 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009263 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009264 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009265 }
9266
9267 bss = os_malloc(sizeof(*bss));
9268 if (!bss) {
9269 wpa_printf(MSG_DEBUG,
9270 "Failed to allocate memory for temp disallow BSS");
9271 return;
9272 }
9273
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009274 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9275 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009276 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009277
9278finish:
9279 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009280 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9281 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009282}
9283
9284
Hai Shalom74f70d42019-02-11 14:42:39 -08009285int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9286 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009287{
Hai Shalom74f70d42019-02-11 14:42:39 -08009288 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009289
9290 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9291 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009292 if (ether_addr_equal(bss->bssid, tmp->bssid)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009293 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009294 break;
9295 }
9296 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009297 if (!disallowed)
9298 return 0;
9299
9300 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009301 bss->level > disallowed->rssi_threshold) {
9302 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9303 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009304 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009305 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009306
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009307 return 1;
9308}
Hai Shalom81f62d82019-07-22 12:10:00 -07009309
9310
9311int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9312 unsigned int type, const u8 *addr,
9313 const u8 *mask)
9314{
9315 if ((addr && !mask) || (!addr && mask)) {
9316 wpa_printf(MSG_INFO,
9317 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9318 return -1;
9319 }
9320
9321 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9322 wpa_printf(MSG_INFO,
9323 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9324 return -1;
9325 }
9326
9327 if (type & MAC_ADDR_RAND_SCAN) {
9328 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9329 addr, mask))
9330 return -1;
9331 }
9332
9333 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9334 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9335 addr, mask))
9336 return -1;
9337
9338 if (wpa_s->sched_scanning && !wpa_s->pno)
9339 wpas_scan_restart_sched_scan(wpa_s);
9340 }
9341
9342 if (type & MAC_ADDR_RAND_PNO) {
9343 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9344 addr, mask))
9345 return -1;
9346
9347 if (wpa_s->pno) {
9348 wpas_stop_pno(wpa_s);
9349 wpas_start_pno(wpa_s);
9350 }
9351 }
9352
9353 return 0;
9354}
9355
9356
9357int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9358 unsigned int type)
9359{
9360 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9361 if (wpa_s->pno) {
9362 if (type & MAC_ADDR_RAND_PNO) {
9363 wpas_stop_pno(wpa_s);
9364 wpas_start_pno(wpa_s);
9365 }
9366 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9367 wpas_scan_restart_sched_scan(wpa_s);
9368 }
9369
9370 return 0;
9371}
Hai Shalomfdcde762020-04-02 11:19:20 -07009372
9373
9374int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9375 struct wpa_signal_info *si)
9376{
9377 int res;
9378
9379 if (!wpa_s->driver->signal_poll)
9380 return -1;
9381
9382 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9383
9384#ifdef CONFIG_TESTING_OPTIONS
9385 if (res == 0) {
9386 struct driver_signal_override *dso;
9387
9388 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9389 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009390 if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009391 continue;
9392 wpa_printf(MSG_DEBUG,
9393 "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 +00009394 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009395 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009396 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009397 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009398 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009399 dso->si_avg_beacon_signal,
9400 si->current_noise,
9401 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009402 si->data.signal = dso->si_current_signal;
9403 si->data.avg_signal = dso->si_avg_signal;
9404 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009405 si->current_noise = dso->si_current_noise;
9406 break;
9407 }
9408 }
9409#endif /* CONFIG_TESTING_OPTIONS */
9410
9411 return res;
9412}
9413
9414
9415struct wpa_scan_results *
Sunil Ravi88611412024-06-28 17:34:56 +00009416wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
Hai Shalomfdcde762020-04-02 11:19:20 -07009417{
9418 struct wpa_scan_results *scan_res;
9419#ifdef CONFIG_TESTING_OPTIONS
9420 size_t idx;
9421#endif /* CONFIG_TESTING_OPTIONS */
9422
Sunil Ravi88611412024-06-28 17:34:56 +00009423 if (!wpa_s->driver->get_scan_results2)
Hai Shalomfdcde762020-04-02 11:19:20 -07009424 return NULL;
9425
Sunil Ravi88611412024-06-28 17:34:56 +00009426 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
Hai Shalomfdcde762020-04-02 11:19:20 -07009427
9428#ifdef CONFIG_TESTING_OPTIONS
9429 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9430 struct driver_signal_override *dso;
9431 struct wpa_scan_res *res = scan_res->res[idx];
9432
9433 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9434 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009435 if (!ether_addr_equal(res->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009436 continue;
9437 wpa_printf(MSG_DEBUG,
9438 "Override driver scan signal level %d->%d for "
9439 MACSTR,
9440 res->level, dso->scan_level,
9441 MAC2STR(res->bssid));
9442 res->flags |= WPA_SCAN_QUAL_INVALID;
9443 if (dso->scan_level < 0)
9444 res->flags |= WPA_SCAN_LEVEL_DBM;
9445 else
9446 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9447 res->level = dso->scan_level;
9448 break;
9449 }
9450 }
9451#endif /* CONFIG_TESTING_OPTIONS */
9452
9453 return scan_res;
9454}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009455
9456
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009457bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009458{
9459 int i;
9460
9461 if (!wpa_s->valid_links)
9462 return false;
9463
Sunil Ravi88611412024-06-28 17:34:56 +00009464 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9465 if (!(wpa_s->valid_links & BIT(i)))
9466 continue;
9467
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009468 if (ether_addr_equal(wpa_s->links[i].bssid, addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00009469 return true;
9470 }
9471
9472 return false;
9473}
9474
9475
9476int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9477 unsigned int wait, const u8 *dst, const u8 *src,
9478 const u8 *bssid, const u8 *data, size_t data_len,
9479 int no_cck)
9480{
9481 if (!wpa_s->driver->send_action)
9482 return -1;
9483
9484 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9485 if (wpas_ap_link_address(wpa_s, dst))
9486 dst = wpa_s->ap_mld_addr;
9487
9488 if (wpas_ap_link_address(wpa_s, bssid))
9489 bssid = wpa_s->ap_mld_addr;
9490 }
9491
9492 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9493 bssid, data, data_len, no_cck);
9494}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009495
9496
9497bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9498{
9499 struct hostapd_channel_data *chnl;
9500 int i, j;
9501
9502 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9503 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9504 chnl = wpa_s->hw.modes[i].channels;
9505 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9506 if (only_enabled &&
9507 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9508 continue;
9509 if (is_6ghz_freq(chnl[j].freq))
9510 return true;
9511 }
9512 }
9513 }
9514
9515 return false;
9516}