blob: e3ed8582430de10c4f9cc50604e8a97607d7e808 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003 * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
Sunil8cd6f4d2022-06-28 18:40:46 +000020#include "crypto/crypto.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070023#include "eapol_supp/eapol_supp_sm.h"
24#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070025#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "eap_server/eap_methods.h"
27#include "rsn_supp/wpa.h"
28#include "eloop.h"
29#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070030#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031#include "l2_packet/l2_packet.h"
32#include "wpa_supplicant_i.h"
33#include "driver_i.h"
34#include "ctrl_iface.h"
35#include "pcsc_funcs.h"
36#include "common/version.h"
37#include "rsn_supp/preauth.h"
38#include "rsn_supp/pmksa_cache.h"
39#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070040#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080042#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070044#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080045#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080048#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "wpas_glue.h"
50#include "wps_supplicant.h"
51#include "ibss_rsn.h"
52#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054#include "ap.h"
55#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070056#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057#include "notify.h"
58#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060#include "bss.h"
61#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080062#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070063#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070064#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070065#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080066#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070067#include "dpp_supplicant.h"
Sunil Ravib0ac25f2024-07-12 01:42:03 +000068#include "nan_usd.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070069#ifdef CONFIG_MESH
70#include "ap/ap_config.h"
71#include "ap/hostapd.h"
72#endif /* CONFIG_MESH */
Gabriel Biren3c401c52024-10-10 20:11:18 +000073#include "aidl/vendor/aidl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070075const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076"wpa_supplicant v" VERSION_STR "\n"
Sunil Ravi7f769292024-07-23 22:21:32 +000077"Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070079const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080080"This software may be distributed under the terms of the BSD license.\n"
81"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082#ifdef EAP_TLS_OPENSSL
83"\nThis product includes software developed by the OpenSSL Project\n"
84"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
85#endif /* EAP_TLS_OPENSSL */
86;
87
88#ifndef CONFIG_NO_STDOUT_DEBUG
89/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080091"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070092const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080093"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070094"\n"
95"Redistribution and use in source and binary forms, with or without\n"
96"modification, are permitted provided that the following conditions are\n"
97"met:\n"
98"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070099const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700100"1. Redistributions of source code must retain the above copyright\n"
101" notice, this list of conditions and the following disclaimer.\n"
102"\n"
103"2. Redistributions in binary form must reproduce the above copyright\n"
104" notice, this list of conditions and the following disclaimer in the\n"
105" documentation and/or other materials provided with the distribution.\n"
106"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700107const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700108"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
109" names of its contributors may be used to endorse or promote products\n"
110" derived from this software without specific prior written permission.\n"
111"\n"
112"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
113"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
114"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
115"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700116const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
118"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
119"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
120"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
121"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
122"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
123"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
124"\n";
125#endif /* CONFIG_NO_STDOUT_DEBUG */
126
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700127
128static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
Sunil Ravi7f769292024-07-23 22:21:32 +0000129static void wpas_verify_ssid_beacon(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700130#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
131static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
132#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700133#ifdef CONFIG_OWE
134static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
135#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700136
137
Hai Shalomfdcde762020-04-02 11:19:20 -0700138#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700139/* Configure default/group WEP keys for static WEP */
140int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
141{
142 int i, set = 0;
143
144 for (i = 0; i < NUM_WEP_KEYS; i++) {
145 if (ssid->wep_key_len[i] == 0)
146 continue;
147
148 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000149 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700151 ssid->wep_key[i], ssid->wep_key_len[i],
152 i == ssid->wep_tx_keyidx ?
153 KEY_FLAG_GROUP_RX_TX_DEFAULT :
154 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155 }
156
157 return set;
158}
Hai Shalomfdcde762020-04-02 11:19:20 -0700159#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160
161
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700162int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
163 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164{
165 u8 key[32];
166 size_t keylen;
167 enum wpa_alg alg;
168 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800169 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700170
171 /* IBSS/WPA-None uses only one key (Group) for both receiving and
172 * sending unicast and multicast packets. */
173
174 if (ssid->mode != WPAS_MODE_IBSS) {
175 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
176 "IBSS/ad-hoc) for WPA-None", ssid->mode);
177 return -1;
178 }
179
180 if (!ssid->psk_set) {
181 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
182 "WPA-None");
183 return -1;
184 }
185
186 switch (wpa_s->group_cipher) {
187 case WPA_CIPHER_CCMP:
188 os_memcpy(key, ssid->psk, 16);
189 keylen = 16;
190 alg = WPA_ALG_CCMP;
191 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700192 case WPA_CIPHER_GCMP:
193 os_memcpy(key, ssid->psk, 16);
194 keylen = 16;
195 alg = WPA_ALG_GCMP;
196 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197 case WPA_CIPHER_TKIP:
198 /* WPA-None uses the same Michael MIC key for both TX and RX */
199 os_memcpy(key, ssid->psk, 16 + 8);
200 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
201 keylen = 32;
202 alg = WPA_ALG_TKIP;
203 break;
204 default:
205 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
206 "WPA-None", wpa_s->group_cipher);
207 return -1;
208 }
209
210 /* TODO: should actually remember the previously used seq#, both for TX
211 * and RX from each STA.. */
212
Sunil Ravi77d572f2023-01-17 23:58:31 +0000213 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700214 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800215 os_memset(key, 0, sizeof(key));
216 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217}
218
219
220static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
221{
222 struct wpa_supplicant *wpa_s = eloop_ctx;
223 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700224 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
225 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
226 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 bssid = wpa_s->pending_bssid;
228 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
229 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800230 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700231 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800233 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700234 wpa_s->reassociate = 1;
235
236 /*
237 * If we timed out, the AP or the local radio may be busy.
238 * So, wait a second until scanning again.
239 */
240 wpa_supplicant_req_scan(wpa_s, 1, 0);
241}
242
243
244/**
245 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
246 * @wpa_s: Pointer to wpa_supplicant data
247 * @sec: Number of seconds after which to time out authentication
248 * @usec: Number of microseconds after which to time out authentication
249 *
250 * This function is used to schedule a timeout for the current authentication
251 * attempt.
252 */
253void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
254 int sec, int usec)
255{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700256 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
258 return;
259
260 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
261 "%d usec", sec, usec);
262 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700263 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700264 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
265}
266
267
Roshan Pius3a1667e2018-07-03 15:17:14 -0700268/*
269 * wpas_auth_timeout_restart - Restart and change timeout for authentication
270 * @wpa_s: Pointer to wpa_supplicant data
271 * @sec_diff: difference in seconds applied to original timeout value
272 */
273void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
274{
275 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
276
277 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
278 wpa_dbg(wpa_s, MSG_DEBUG,
279 "Authentication timeout restart: %d sec", new_sec);
280 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
281 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
282 wpa_s, NULL);
283 }
284}
285
286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287/**
288 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
289 * @wpa_s: Pointer to wpa_supplicant data
290 *
291 * This function is used to cancel authentication timeout scheduled with
292 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
293 * been completed.
294 */
295void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
296{
297 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
298 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800299 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700300 os_free(wpa_s->last_con_fail_realm);
301 wpa_s->last_con_fail_realm = NULL;
302 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303}
304
305
306/**
307 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
308 * @wpa_s: Pointer to wpa_supplicant data
309 *
310 * This function is used to configure EAPOL state machine based on the selected
311 * authentication mode.
312 */
313void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
314{
315#ifdef IEEE8021X_EAPOL
316 struct eapol_config eapol_conf;
317 struct wpa_ssid *ssid = wpa_s->current_ssid;
318
319#ifdef CONFIG_IBSS_RSN
320 if (ssid->mode == WPAS_MODE_IBSS &&
321 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
322 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
323 /*
324 * RSN IBSS authentication is per-STA and we can disable the
325 * per-BSSID EAPOL authentication.
326 */
327 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700328 eapol_sm_notify_eap_success(wpa_s->eapol, true);
329 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330 return;
331 }
332#endif /* CONFIG_IBSS_RSN */
333
Hai Shalome21d4e82020-04-29 16:34:06 -0700334 eapol_sm_notify_eap_success(wpa_s->eapol, false);
335 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336
337 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
338 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
339 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
340 else
341 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
342
343 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
344 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
345 eapol_conf.accept_802_1x_keys = 1;
346 eapol_conf.required_keys = 0;
347 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
348 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
349 }
350 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
351 eapol_conf.required_keys |=
352 EAPOL_REQUIRE_KEY_BROADCAST;
353 }
354
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700355 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356 eapol_conf.required_keys = 0;
357 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700358 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359 eapol_conf.workaround = ssid->eap_workaround;
360 eapol_conf.eap_disabled =
361 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
362 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
363 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700364 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800365
366#ifdef CONFIG_WPS
367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
368 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
369 if (wpa_s->current_bss) {
370 struct wpabuf *ie;
371 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
372 WPS_IE_VENDOR_TYPE);
373 if (ie) {
374 if (wps_is_20(ie))
375 eapol_conf.wps |=
376 EAPOL_PEER_IS_WPS20_AP;
377 wpabuf_free(ie);
378 }
379 }
380 }
381#endif /* CONFIG_WPS */
382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700384
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800385#ifdef CONFIG_MACSEC
386 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
387 ieee802_1x_create_preshared_mka(wpa_s, ssid);
388 else
389 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
390#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800391#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392}
393
394
395/**
396 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
397 * @wpa_s: Pointer to wpa_supplicant data
398 * @ssid: Configuration data for the network
399 *
400 * This function is used to configure WPA state machine and related parameters
401 * to a mode where WPA is not enabled. This is called as part of the
402 * authentication configuration when the selected network does not use WPA.
403 */
404void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
405 struct wpa_ssid *ssid)
406{
Hai Shalomfdcde762020-04-02 11:19:20 -0700407#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700409#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000410 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700411
412 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
413 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
414 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
415 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
416 else
417 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
418 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
419 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700420 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Sunil Ravic0f5d412024-09-11 22:12:49 +0000421 wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
422 wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
423 wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Matthew Wang9ed1c792024-12-02 14:05:18 +0000425#ifndef CONFIG_NO_WPA
Hai Shalomc3565922019-10-28 11:58:20 -0700426 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Matthew Wang9ed1c792024-12-02 14:05:18 +0000427#endif /* CONFIG_NO_WPA */
Hai Shalomc3565922019-10-28 11:58:20 -0700428 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
430 wpa_s->group_cipher = WPA_CIPHER_NONE;
431 wpa_s->mgmt_group_cipher = 0;
432
Hai Shalomfdcde762020-04-02 11:19:20 -0700433#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700434 for (i = 0; i < NUM_WEP_KEYS; i++) {
435 if (ssid->wep_key_len[i] > 5) {
436 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
437 wpa_s->group_cipher = WPA_CIPHER_WEP104;
438 break;
439 } else if (ssid->wep_key_len[i] > 0) {
440 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
441 wpa_s->group_cipher = WPA_CIPHER_WEP40;
442 break;
443 }
444 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700445#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700446
447 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
448 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
450 wpa_s->pairwise_cipher);
451 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
453 wpa_s->mgmt_group_cipher);
Sunil Ravi7f769292024-07-23 22:21:32 +0000454 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455
456 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000457 os_memset(&mlo, 0, sizeof(mlo));
458 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700459}
460
461
Dmitry Shmidt04949592012-07-19 12:16:46 -0700462void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800463{
464 int i;
465 if (wpa_s->hw.modes == NULL)
466 return;
467
468 for (i = 0; i < wpa_s->hw.num_modes; i++) {
469 os_free(wpa_s->hw.modes[i].channels);
470 os_free(wpa_s->hw.modes[i].rates);
471 }
472
473 os_free(wpa_s->hw.modes);
474 wpa_s->hw.modes = NULL;
475}
476
477
Hai Shalomc1a21442022-02-04 13:43:00 -0800478static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
479 struct wpa_bss_tmp_disallowed *bss)
480{
481 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
482 dl_list_del(&bss->list);
483 os_free(bss);
484}
485
486
Hai Shalom74f70d42019-02-11 14:42:39 -0800487void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800488{
489 struct wpa_bss_tmp_disallowed *bss, *prev;
490
491 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800492 struct wpa_bss_tmp_disallowed, list)
493 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800494}
495
496
Paul Stewart092955c2017-02-06 09:13:09 -0800497void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
498{
499 struct fils_hlp_req *req;
500
501 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
502 list)) != NULL) {
503 dl_list_del(&req->list);
504 wpabuf_free(req->pkt);
505 os_free(req);
506 }
507}
508
509
Hai Shalomfdcde762020-04-02 11:19:20 -0700510void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
511{
512 struct wpa_supplicant *wpa_s = eloop_ctx;
513
514 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
515 return;
516 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
517 wpa_bss_flush(wpa_s);
518}
519
520
521#ifdef CONFIG_TESTING_OPTIONS
522void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
523{
524 struct driver_signal_override *dso;
525
526 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
527 struct driver_signal_override, list))) {
528 dl_list_del(&dso->list);
529 os_free(dso);
530 }
531}
532#endif /* CONFIG_TESTING_OPTIONS */
533
534
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700535static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
536{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700537 int i;
538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700540 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541 scard_deinit(wpa_s->scard);
542 wpa_s->scard = NULL;
543 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
544 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
545 l2_packet_deinit(wpa_s->l2);
546 wpa_s->l2 = NULL;
547 if (wpa_s->l2_br) {
548 l2_packet_deinit(wpa_s->l2_br);
549 wpa_s->l2_br = NULL;
550 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800551#ifdef CONFIG_TESTING_OPTIONS
552 l2_packet_deinit(wpa_s->l2_test);
553 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800554 os_free(wpa_s->get_pref_freq_list_override);
555 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700556 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
557 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800558 os_free(wpa_s->extra_sae_rejected_groups);
559 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700560 wpabuf_free(wpa_s->rsne_override_eapol);
561 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800562 wpabuf_free(wpa_s->rsnxe_override_assoc);
563 wpa_s->rsnxe_override_assoc = NULL;
564 wpabuf_free(wpa_s->rsnxe_override_eapol);
565 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700566 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800567#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569 if (wpa_s->conf != NULL) {
570 struct wpa_ssid *ssid;
571 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
572 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 }
574
575 os_free(wpa_s->confname);
576 wpa_s->confname = NULL;
577
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700578 os_free(wpa_s->confanother);
579 wpa_s->confanother = NULL;
580
Hai Shalomce48b4a2018-09-05 11:41:35 -0700581 os_free(wpa_s->last_con_fail_realm);
582 wpa_s->last_con_fail_realm = NULL;
583 wpa_s->last_con_fail_realm_len = 0;
584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 wpa_sm_set_eapol(wpa_s->wpa, NULL);
586 eapol_sm_deinit(wpa_s->eapol);
587 wpa_s->eapol = NULL;
588
589 rsn_preauth_deinit(wpa_s->wpa);
590
591#ifdef CONFIG_TDLS
592 wpa_tdls_deinit(wpa_s->wpa);
593#endif /* CONFIG_TDLS */
594
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000595#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800596 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000597#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800599 ptksa_cache_deinit(wpa_s->ptksa);
600 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 wpa_sm_deinit(wpa_s->wpa);
602 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800603 wpa_bssid_ignore_clear(wpa_s);
604
605#ifdef CONFIG_PASN
606 wpas_pasn_auth_stop(wpa_s);
607#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608
609 wpa_bss_deinit(wpa_s);
610
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700611 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612 wpa_supplicant_cancel_scan(wpa_s);
613 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800614 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
615#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
616 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
617 wpa_s, NULL);
618#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700620 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700621 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Sunil Ravi7f769292024-07-23 22:21:32 +0000622 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700623
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 wpas_wps_deinit(wpa_s);
625
626 wpabuf_free(wpa_s->pending_eapol_rx);
627 wpa_s->pending_eapol_rx = NULL;
628
629#ifdef CONFIG_IBSS_RSN
630 ibss_rsn_deinit(wpa_s->ibss_rsn);
631 wpa_s->ibss_rsn = NULL;
632#endif /* CONFIG_IBSS_RSN */
633
634 sme_deinit(wpa_s);
635
636#ifdef CONFIG_AP
637 wpa_supplicant_ap_deinit(wpa_s);
638#endif /* CONFIG_AP */
639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700640 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800642#ifdef CONFIG_OFFCHANNEL
643 offchannel_deinit(wpa_s);
644#endif /* CONFIG_OFFCHANNEL */
645
646 wpa_supplicant_cancel_sched_scan(wpa_s);
647
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648 os_free(wpa_s->next_scan_freqs);
649 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800650
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800651 os_free(wpa_s->manual_scan_freqs);
652 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700653 os_free(wpa_s->select_network_scan_freqs);
654 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800655
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700656 os_free(wpa_s->manual_sched_scan_freqs);
657 wpa_s->manual_sched_scan_freqs = NULL;
658
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800659 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
660
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700661 /*
662 * Need to remove any pending gas-query radio work before the
663 * gas_query_deinit() call because gas_query::work has not yet been set
664 * for works that have not been started. gas_query_free() will be unable
665 * to cancel such pending radio works and once the pending gas-query
666 * radio work eventually gets removed, the deinit notification call to
667 * gas_query_start_cb() would result in dereferencing freed memory.
668 */
669 if (wpa_s->radio)
670 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800671 gas_query_deinit(wpa_s->gas);
672 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673 gas_server_deinit(wpa_s->gas_server);
674 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800675
676 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700677
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700678 ieee802_1x_dealloc_kay_sm(wpa_s);
679
Dmitry Shmidt04949592012-07-19 12:16:46 -0700680 os_free(wpa_s->bssid_filter);
681 wpa_s->bssid_filter = NULL;
682
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800683 os_free(wpa_s->disallow_aps_bssid);
684 wpa_s->disallow_aps_bssid = NULL;
685 os_free(wpa_s->disallow_aps_ssid);
686 wpa_s->disallow_aps_ssid = NULL;
687
Dmitry Shmidt04949592012-07-19 12:16:46 -0700688 wnm_bss_keep_alive_deinit(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000689 wnm_btm_reset(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690
691 ext_password_deinit(wpa_s->ext_pw);
692 wpa_s->ext_pw = NULL;
693
694 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800695 wpa_s->last_gas_resp = NULL;
696 wpabuf_free(wpa_s->prev_gas_resp);
697 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700698
699 os_free(wpa_s->last_scan_res);
700 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800701
702#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700703 if (wpa_s->drv_priv)
704 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700705 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800706#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700707
708 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
709 wpabuf_free(wpa_s->vendor_elem[i]);
710 wpa_s->vendor_elem[i] = NULL;
711 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800712
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000713#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800714 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000715#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800716
717 wpa_s->sched_scan_plans_num = 0;
718 os_free(wpa_s->sched_scan_plans);
719 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800720
721#ifdef CONFIG_MBO
722 wpa_s->non_pref_chan_num = 0;
723 os_free(wpa_s->non_pref_chan);
724 wpa_s->non_pref_chan = NULL;
725#endif /* CONFIG_MBO */
726
727 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700728
729 wpabuf_free(wpa_s->lci);
730 wpa_s->lci = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000731#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800732 wpas_clear_beacon_rep_data(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000733#endif /* CONFIG_NO_RRM */
Paul Stewart092955c2017-02-06 09:13:09 -0800734
735#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
736#ifdef CONFIG_MESH
737 {
738 struct external_pmksa_cache *entry;
739
740 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
741 struct external_pmksa_cache,
742 list)) != NULL) {
743 dl_list_del(&entry->list);
744 os_free(entry->pmksa_cache);
745 os_free(entry);
746 }
747 }
748#endif /* CONFIG_MESH */
749#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
750
751 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800752
753 wpabuf_free(wpa_s->ric_ies);
754 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700755
756#ifdef CONFIG_DPP
757 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700758 dpp_global_deinit(wpa_s->dpp);
759 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700760#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800761
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000762#ifdef CONFIG_NAN_USD
763 wpas_nan_usd_deinit(wpa_s);
764#endif /* CONFIG_NAN_USD */
765
Hai Shalom60840252021-02-19 19:02:11 -0800766#ifdef CONFIG_PASN
767 wpas_pasn_auth_stop(wpa_s);
768#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000769#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -0800770 wpas_scs_deinit(wpa_s);
771 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000772#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000773
774#ifdef CONFIG_OWE
775 os_free(wpa_s->owe_trans_scan_freq);
776 wpa_s->owe_trans_scan_freq = NULL;
777#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778}
779
780
781/**
782 * wpa_clear_keys - Clear keys configured for the driver
783 * @wpa_s: Pointer to wpa_supplicant data
784 * @addr: Previously used BSSID or %NULL if not available
785 *
786 * This function clears the encryption keys that has been previously configured
787 * for the driver.
788 */
789void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
790{
Hai Shalomc3565922019-10-28 11:58:20 -0700791 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792
793 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794 for (i = 0; i < max; i++) {
795 if (wpa_s->keys_cleared & BIT(i))
796 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000797 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700798 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800799 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700800 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
801 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800802 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700803 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000804 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
805 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700806 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000807 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
808 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700809 /* MLME-SETPROTECTION.request(None) */
810 wpa_drv_mlme_setprotection(
811 wpa_s, addr,
812 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
813 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
814 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800815 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816}
817
818
819/**
820 * wpa_supplicant_state_txt - Get the connection state name as a text string
821 * @state: State (wpa_state; WPA_*)
822 * Returns: The state name as a printable text string
823 */
824const char * wpa_supplicant_state_txt(enum wpa_states state)
825{
826 switch (state) {
827 case WPA_DISCONNECTED:
828 return "DISCONNECTED";
829 case WPA_INACTIVE:
830 return "INACTIVE";
831 case WPA_INTERFACE_DISABLED:
832 return "INTERFACE_DISABLED";
833 case WPA_SCANNING:
834 return "SCANNING";
835 case WPA_AUTHENTICATING:
836 return "AUTHENTICATING";
837 case WPA_ASSOCIATING:
838 return "ASSOCIATING";
839 case WPA_ASSOCIATED:
840 return "ASSOCIATED";
841 case WPA_4WAY_HANDSHAKE:
842 return "4WAY_HANDSHAKE";
843 case WPA_GROUP_HANDSHAKE:
844 return "GROUP_HANDSHAKE";
845 case WPA_COMPLETED:
846 return "COMPLETED";
847 default:
848 return "UNKNOWN";
849 }
850}
851
852
853#ifdef CONFIG_BGSCAN
854
Hai Shalom899fcc72020-10-19 14:38:18 -0700855static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
856{
857 if (wpa_s->bgscan_ssid) {
858 bgscan_deinit(wpa_s);
859 wpa_s->bgscan_ssid = NULL;
860 }
861}
862
863
864/**
865 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
866 * @wpa_s: Pointer to the wpa_supplicant data
867 *
868 * Stop, start, or reconfigure the scan parameters depending on the method.
869 */
870void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700871{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800872 const char *name;
873
874 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
875 name = wpa_s->current_ssid->bgscan;
876 else
877 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700878 if (!name || name[0] == '\0') {
879 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800880 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700881 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800882 if (wpas_driver_bss_selection(wpa_s))
883 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800884#ifdef CONFIG_P2P
885 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
886 return;
887#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888
889 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800890 if (wpa_s->current_ssid) {
891 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
893 "bgscan");
894 /*
895 * Live without bgscan; it is only used as a roaming
896 * optimization, so the initial connection is not
897 * affected.
898 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700899 } else {
900 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700901 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700902 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
Sunil Ravi99c035e2024-07-12 01:42:03 +0000903 0, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700904 if (scan_res) {
905 bgscan_notify_scan(wpa_s, scan_res);
906 wpa_scan_results_free(scan_res);
907 }
908 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700909 } else
910 wpa_s->bgscan_ssid = NULL;
911}
912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700913#endif /* CONFIG_BGSCAN */
914
915
Dmitry Shmidt04949592012-07-19 12:16:46 -0700916static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
917{
918 if (autoscan_init(wpa_s, 0))
919 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
920}
921
922
923static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
924{
925 autoscan_deinit(wpa_s);
926}
927
928
929void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
930{
931 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
932 wpa_s->wpa_state == WPA_SCANNING) {
933 autoscan_deinit(wpa_s);
934 wpa_supplicant_start_autoscan(wpa_s);
935 }
936}
937
938
Sunil Ravi7f769292024-07-23 22:21:32 +0000939static void wpas_verify_ssid_beacon(void *eloop_ctx, void *timeout_ctx)
940{
941 struct wpa_supplicant *wpa_s = eloop_ctx;
942 struct wpa_bss *bss;
943 const u8 *ssid;
944 size_t ssid_len;
945
946 if (!wpa_s->current_ssid || !wpa_s->current_bss)
947 return;
948
949 ssid = wpa_s->current_bss->ssid;
950 ssid_len = wpa_s->current_bss->ssid_len;
951
952 if (wpa_s->current_ssid->ssid_len &&
953 (wpa_s->current_ssid->ssid_len != ssid_len ||
954 os_memcmp(wpa_s->current_ssid->ssid, ssid, ssid_len) != 0))
955 return;
956
957 if (wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
958 !wpa_s->bigtk_set || wpa_s->ssid_verified)
959 return;
960
961 wpa_printf(MSG_DEBUG,
962 "SSID not yet verified; check if the driver has received a verified Beacon frame");
963 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
964 return;
965
966 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
967 if (!bss)
968 return;
969 wpa_printf(MSG_DEBUG, "The current beacon time stamp: 0x%llx",
970 (long long unsigned int) bss->tsf);
971 if (bss->tsf > wpa_s->first_beacon_tsf) {
972 const u8 *ie;
973
974 wpa_printf(MSG_DEBUG,
975 "Verified Beacon frame has been received");
976 wpa_s->beacons_checked++;
977
978 ie = wpa_bss_get_ie_beacon(bss, WLAN_EID_SSID);
979 if (ie && ie[1] == ssid_len &&
980 os_memcmp(&ie[2], ssid, ssid_len) == 0) {
981 wpa_printf(MSG_DEBUG,
982 "SSID verified based on a Beacon frame and beacon protection");
983 wpa_s->ssid_verified = true;
984 return;
985 }
986
987 /* TODO: Multiple BSSID element */
988 }
989
990 if (wpa_s->beacons_checked < 16) {
991 eloop_register_timeout(wpa_s->next_beacon_check, 0,
992 wpas_verify_ssid_beacon, wpa_s, NULL);
993 wpa_s->next_beacon_check++;
994 }
995}
996
997
998static void wpas_verify_ssid_beacon_prot(struct wpa_supplicant *wpa_s)
999{
1000 struct wpa_bss *bss;
1001
1002 wpa_printf(MSG_DEBUG,
1003 "SSID not yet verified; try to verify using beacon protection");
1004 /* Fetch the current scan result which is likely based on not yet
1005 * verified payload since the current BIGTK was just received. Any
1006 * newer update in the future with a larger timestamp value is an
1007 * indication that a verified Beacon frame has been received. */
1008 if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
1009 return;
1010
1011 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->bssid);
1012 if (!bss)
1013 return;
1014 wpa_printf(MSG_DEBUG, "The initial beacon time stamp: 0x%llx",
1015 (long long unsigned int) bss->tsf);
1016 wpa_s->first_beacon_tsf = bss->tsf;
1017 wpa_s->beacons_checked = 0;
1018 wpa_s->next_beacon_check = 1;
1019 eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
1020 eloop_register_timeout(1, 0, wpas_verify_ssid_beacon, wpa_s, NULL);
1021}
1022
1023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001024/**
1025 * wpa_supplicant_set_state - Set current connection state
1026 * @wpa_s: Pointer to wpa_supplicant data
1027 * @state: The new connection state
1028 *
1029 * This function is called whenever the connection state changes, e.g.,
1030 * association is completed for WPA/WPA2 4-Way Handshake is started.
1031 */
1032void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
1033 enum wpa_states state)
1034{
1035 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -07001036#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -07001037 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001038#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039
1040 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
1041 wpa_supplicant_state_txt(wpa_s->wpa_state),
1042 wpa_supplicant_state_txt(state));
1043
Hai Shalom74f70d42019-02-11 14:42:39 -08001044 if (state == WPA_COMPLETED &&
1045 os_reltime_initialized(&wpa_s->roam_start)) {
1046 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
1047 wpa_s->roam_start.sec = 0;
1048 wpa_s->roam_start.usec = 0;
1049 wpas_notify_auth_changed(wpa_s);
1050 wpas_notify_roam_time(wpa_s);
1051 wpas_notify_roam_complete(wpa_s);
1052 } else if (state == WPA_DISCONNECTED &&
1053 os_reltime_initialized(&wpa_s->roam_start)) {
1054 wpa_s->roam_start.sec = 0;
1055 wpa_s->roam_start.usec = 0;
1056 wpa_s->roam_time.sec = 0;
1057 wpa_s->roam_time.usec = 0;
1058 wpas_notify_roam_complete(wpa_s);
1059 }
1060
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08001061 if (state == WPA_INTERFACE_DISABLED) {
1062 /* Assure normal scan when interface is restored */
1063 wpa_s->normal_scans = 0;
1064 }
1065
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001066 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001067 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001068 /* Reinitialize normal_scan counter */
1069 wpa_s->normal_scans = 0;
1070 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001071
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001072#ifdef CONFIG_P2P
1073 /*
1074 * P2PS client has to reply to Probe Request frames received on the
1075 * group operating channel. Enable Probe Request frame reporting for
1076 * P2P connected client in case p2p_cli_probe configuration property is
1077 * set to 1.
1078 */
1079 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
1080 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
1081 wpa_s->current_ssid->p2p_group) {
1082 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
1083 wpa_dbg(wpa_s, MSG_DEBUG,
1084 "P2P: Enable CLI Probe Request RX reporting");
1085 wpa_s->p2p_cli_probe =
1086 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
1087 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
1088 wpa_dbg(wpa_s, MSG_DEBUG,
1089 "P2P: Disable CLI Probe Request RX reporting");
1090 wpa_s->p2p_cli_probe = 0;
1091 wpa_drv_probe_req_report(wpa_s, 0);
1092 }
1093 }
1094#endif /* CONFIG_P2P */
1095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 if (state != WPA_SCANNING)
1097 wpa_supplicant_notify_scanning(wpa_s, 0);
1098
1099 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001100 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001101 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001102 char mld_addr[50];
1103
1104 mld_addr[0] = '\0';
1105 if (wpa_s->valid_links)
1106 os_snprintf(mld_addr, sizeof(mld_addr),
1107 " ap_mld_addr=" MACSTR,
1108 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001109
1110#ifdef CONFIG_SME
1111 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1112 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1113 fils_hlp_sent = 1;
1114#endif /* CONFIG_SME */
1115 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1116 wpa_auth_alg_fils(wpa_s->auth_alg))
1117 fils_hlp_sent = 1;
1118
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001119#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001121 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001122 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001124 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001125 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001126#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001127 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001128 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 wpa_drv_set_operstate(wpa_s, 1);
1131#ifndef IEEE8021X_EAPOL
1132 wpa_drv_set_supp_port(wpa_s, 1);
1133#endif /* IEEE8021X_EAPOL */
1134 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001135 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001137
1138 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001139
1140#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1141 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001142 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001143#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001144#ifdef CONFIG_OWE
1145 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1146 wpas_update_owe_connect_params(wpa_s);
1147#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001148#ifdef CONFIG_HS20
1149 hs20_configure_frame_filters(wpa_s);
1150#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1152 state == WPA_ASSOCIATED) {
1153 wpa_s->new_connection = 1;
1154 wpa_drv_set_operstate(wpa_s, 0);
1155#ifndef IEEE8021X_EAPOL
1156 wpa_drv_set_supp_port(wpa_s, 0);
1157#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001158 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 }
1160 wpa_s->wpa_state = state;
1161
1162#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001163 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1164 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001165 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 wpa_supplicant_stop_bgscan(wpa_s);
1167#endif /* CONFIG_BGSCAN */
1168
Hai Shalom5f92bc92019-04-18 11:54:11 -07001169 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001170 wpa_supplicant_stop_autoscan(wpa_s);
1171
1172 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1173 wpa_supplicant_start_autoscan(wpa_s);
1174
Sunil Ravi99c035e2024-07-12 01:42:03 +00001175 if (state == WPA_COMPLETED || state == WPA_INTERFACE_DISABLED ||
1176 state == WPA_INACTIVE)
1177 wnm_btm_reset(wpa_s);
1178
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001179#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1181 wmm_ac_notify_disassoc(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001182#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 if (wpa_s->wpa_state != old_state) {
1185 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1186
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001187 /*
1188 * Notify the P2P Device interface about a state change in one
1189 * of the interfaces.
1190 */
1191 wpas_p2p_indicate_state_change(wpa_s);
1192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 if (wpa_s->wpa_state == WPA_COMPLETED ||
1194 old_state == WPA_COMPLETED)
1195 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001196#ifdef CONFIG_DPP2
1197 if (wpa_s->wpa_state == WPA_COMPLETED)
1198 wpas_dpp_connected(wpa_s);
1199#endif /* CONFIG_DPP2 */
Sunil Ravi7f769292024-07-23 22:21:32 +00001200
1201 if (wpa_s->wpa_state == WPA_COMPLETED &&
1202 wpa_s->bigtk_set && !wpa_s->ssid_verified)
1203 wpas_verify_ssid_beacon_prot(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204 }
Hai Shalomc3565922019-10-28 11:58:20 -07001205#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1206 if (update_fils_connect_params)
1207 wpas_update_fils_connect_params(wpa_s);
1208#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209}
1210
1211
1212void wpa_supplicant_terminate_proc(struct wpa_global *global)
1213{
1214 int pending = 0;
1215#ifdef CONFIG_WPS
1216 struct wpa_supplicant *wpa_s = global->ifaces;
1217 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001218 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001219 if (wpas_wps_terminate_pending(wpa_s) == 1)
1220 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001221#ifdef CONFIG_P2P
1222 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1223 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1224 wpas_p2p_disconnect(wpa_s);
1225#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001226 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 }
1228#endif /* CONFIG_WPS */
1229 if (pending)
1230 return;
1231 eloop_terminate();
1232}
1233
1234
1235static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1236{
1237 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238 wpa_supplicant_terminate_proc(global);
1239}
1240
1241
1242void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1243{
1244 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001245 enum wpa_states new_state;
1246
1247 if (old_state == WPA_SCANNING)
1248 new_state = WPA_SCANNING;
1249 else
1250 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001251
1252 wpa_s->pairwise_cipher = 0;
1253 wpa_s->group_cipher = 0;
1254 wpa_s->mgmt_group_cipher = 0;
1255 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001256 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001257 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001258 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001259
1260 if (wpa_s->wpa_state != old_state)
1261 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1262}
1263
1264
1265/**
1266 * wpa_supplicant_reload_configuration - Reload configuration data
1267 * @wpa_s: Pointer to wpa_supplicant data
1268 * Returns: 0 on success or -1 if configuration parsing failed
1269 *
1270 * This function can be used to request that the configuration data is reloaded
1271 * (e.g., after configuration file change). This function is reloading
1272 * configuration only for one interface, so this may need to be called multiple
1273 * times if %wpa_supplicant is controlling multiple interfaces and all
1274 * interfaces need reconfiguration.
1275 */
1276int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1277{
1278 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279 int reconf_ctrl;
1280 int old_ap_scan;
1281
1282 if (wpa_s->confname == NULL)
1283 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001284 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285 if (conf == NULL) {
1286 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1287 "file '%s' - exiting", wpa_s->confname);
1288 return -1;
1289 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001290 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001291 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001292 wpa_msg(wpa_s, MSG_ERROR,
1293 "Failed to parse the configuration file '%s' - exiting",
1294 wpa_s->confanother);
1295 return -1;
1296 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 conf->changed_parameters = (unsigned int) -1;
1299
1300 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1301 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1302 os_strcmp(conf->ctrl_interface,
1303 wpa_s->conf->ctrl_interface) != 0);
1304
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001305 if (reconf_ctrl) {
1306 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 wpa_s->ctrl_iface = NULL;
1308 }
1309
1310 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001311 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001312 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1313 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001314 wpa_supplicant_deauthenticate(wpa_s,
1315 WLAN_REASON_DEAUTH_LEAVING);
1316 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317
1318 /*
1319 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001320 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001321 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001322 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1323 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1324 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325 /*
1326 * Clear forced success to clear EAP state for next
1327 * authentication.
1328 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001329 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 }
1331 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1332 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001333 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1335 rsn_preauth_deinit(wpa_s->wpa);
1336
1337 old_ap_scan = wpa_s->conf->ap_scan;
1338 wpa_config_free(wpa_s->conf);
1339 wpa_s->conf = conf;
1340 if (old_ap_scan != wpa_s->conf->ap_scan)
1341 wpas_notify_ap_scan_changed(wpa_s);
1342
1343 if (reconf_ctrl)
1344 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1345
1346 wpa_supplicant_update_config(wpa_s);
1347
1348 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001349 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350 wpa_s->reassociate = 1;
1351 wpa_supplicant_req_scan(wpa_s, 0, 0);
1352 }
Hai Shalom60840252021-02-19 19:02:11 -08001353 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001354 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1355 return 0;
1356}
1357
1358
1359static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1360{
1361 struct wpa_global *global = signal_ctx;
1362 struct wpa_supplicant *wpa_s;
1363 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1364 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1365 sig);
1366 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1367 wpa_supplicant_terminate_proc(global);
1368 }
1369 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001370
1371 if (wpa_debug_reopen_file() < 0) {
1372 /* Ignore errors since we cannot really do much to fix this */
1373 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1374 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375}
1376
1377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001378static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1379 struct wpa_ssid *ssid,
1380 struct wpa_ie_data *ie)
1381{
1382 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1383 if (ret) {
1384 if (ret == -2) {
1385 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1386 "from association info");
1387 }
1388 return -1;
1389 }
1390
1391 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1392 "cipher suites");
1393 if (!(ie->group_cipher & ssid->group_cipher)) {
1394 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1395 "cipher 0x%x (mask 0x%x) - reject",
1396 ie->group_cipher, ssid->group_cipher);
1397 return -1;
1398 }
1399 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1400 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1401 "cipher 0x%x (mask 0x%x) - reject",
1402 ie->pairwise_cipher, ssid->pairwise_cipher);
1403 return -1;
1404 }
1405 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1406 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1407 "management 0x%x (mask 0x%x) - reject",
1408 ie->key_mgmt, ssid->key_mgmt);
1409 return -1;
1410 }
1411
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001413 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1415 "that does not support management frame protection - "
1416 "reject");
1417 return -1;
1418 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419
1420 return 0;
1421}
1422
1423
Hai Shalom021b0b52019-04-10 11:17:58 -07001424static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1425 int freq)
1426{
1427 if (!ie->has_group)
1428 ie->group_cipher = wpa_default_rsn_cipher(freq);
1429 if (!ie->has_pairwise)
1430 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1431 return (ie->group_cipher & ssid->group_cipher) &&
1432 (ie->pairwise_cipher & ssid->pairwise_cipher);
1433}
1434
1435
Hai Shalomc1a21442022-02-04 13:43:00 -08001436void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1437 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1438{
1439 int sel;
1440
1441 sel = ie->mgmt_group_cipher;
1442 if (ssid->group_mgmt_cipher)
1443 sel &= ssid->group_mgmt_cipher;
1444 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1445 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1446 sel = 0;
1447 wpa_dbg(wpa_s, MSG_DEBUG,
1448 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1449 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1450 if (sel & WPA_CIPHER_AES_128_CMAC) {
1451 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1452 wpa_dbg(wpa_s, MSG_DEBUG,
1453 "WPA: using MGMT group cipher AES-128-CMAC");
1454 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1455 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1456 wpa_dbg(wpa_s, MSG_DEBUG,
1457 "WPA: using MGMT group cipher BIP-GMAC-128");
1458 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1459 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1460 wpa_dbg(wpa_s, MSG_DEBUG,
1461 "WPA: using MGMT group cipher BIP-GMAC-256");
1462 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1463 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1464 wpa_dbg(wpa_s, MSG_DEBUG,
1465 "WPA: using MGMT group cipher BIP-CMAC-256");
1466 } else {
1467 wpa_s->mgmt_group_cipher = 0;
1468 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1469 }
1470 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1471 wpa_s->mgmt_group_cipher);
1472 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1473 wpas_get_ssid_pmf(wpa_s, ssid));
1474}
1475
Sunil Ravi77d572f2023-01-17 23:58:31 +00001476/**
1477 * wpa_supplicant_get_psk - Get PSK from config or external database
1478 * @wpa_s: Pointer to wpa_supplicant data
1479 * @bss: Scan results for the selected BSS, or %NULL if not available
1480 * @ssid: Configuration data for the selected network
1481 * @psk: Buffer for the PSK
1482 * Returns: 0 on success or -1 if configuration parsing failed
1483 *
1484 * This function obtains the PSK for a network, either included inline in the
1485 * config or retrieved from an external database.
1486 */
1487static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1488 struct wpa_bss *bss, struct wpa_ssid *ssid,
1489 u8 *psk)
1490{
1491 if (ssid->psk_set) {
1492 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1493 ssid->psk, PMK_LEN);
1494 os_memcpy(psk, ssid->psk, PMK_LEN);
1495 return 0;
1496 }
1497
1498#ifndef CONFIG_NO_PBKDF2
1499 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1500 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1501 4096, psk, PMK_LEN) != 0) {
1502 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1503 return -1;
1504 }
1505 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1506 psk, PMK_LEN);
1507 return 0;
1508 }
1509#endif /* CONFIG_NO_PBKDF2 */
1510
1511#ifdef CONFIG_EXT_PASSWORD
1512 if (ssid->ext_psk) {
1513 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1514 ssid->ext_psk);
1515 char pw_str[64 + 1];
1516
1517 if (!pw) {
1518 wpa_msg(wpa_s, MSG_INFO,
1519 "EXT PW: No PSK found from external storage");
1520 return -1;
1521 }
1522
1523 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1524 wpa_msg(wpa_s, MSG_INFO,
1525 "EXT PW: Unexpected PSK length %d in external storage",
1526 (int) wpabuf_len(pw));
1527 ext_password_free(pw);
1528 return -1;
1529 }
1530
1531 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1532 pw_str[wpabuf_len(pw)] = '\0';
1533
1534#ifndef CONFIG_NO_PBKDF2
1535 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1536 {
1537 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1538 4096, psk, PMK_LEN) != 0) {
1539 wpa_msg(wpa_s, MSG_WARNING,
1540 "Error in pbkdf2_sha1()");
1541 forced_memzero(pw_str, sizeof(pw_str));
1542 ext_password_free(pw);
1543 return -1;
1544 }
1545 wpa_hexdump_key(MSG_MSGDUMP,
1546 "PSK (from external passphrase)",
1547 psk, PMK_LEN);
1548 } else
1549#endif /* CONFIG_NO_PBKDF2 */
1550 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1551 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1552 wpa_msg(wpa_s, MSG_INFO,
1553 "EXT PW: Invalid PSK hex string");
1554 forced_memzero(pw_str, sizeof(pw_str));
1555 ext_password_free(pw);
1556 return -1;
1557 }
1558 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1559 psk, PMK_LEN);
1560 } else {
1561 wpa_msg(wpa_s, MSG_INFO,
1562 "EXT PW: No suitable PSK available");
1563 forced_memzero(pw_str, sizeof(pw_str));
1564 ext_password_free(pw);
1565 return -1;
1566 }
1567
1568 forced_memzero(pw_str, sizeof(pw_str));
1569 ext_password_free(pw);
1570
1571 return 0;
1572 }
1573#endif /* CONFIG_EXT_PASSWORD */
1574
1575 return -1;
1576}
1577
Hai Shalomc1a21442022-02-04 13:43:00 -08001578
Sunil Ravi89eba102022-09-13 21:04:37 -07001579static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1580 struct wpa_ssid *ssid)
1581{
1582 int akm_count = wpa_s->max_num_akms;
1583 u8 capab = 0;
1584
1585 if (akm_count < 2)
1586 return;
1587
1588 akm_count--;
1589 wpa_s->allowed_key_mgmts = 0;
1590 switch (wpa_s->key_mgmt) {
1591 case WPA_KEY_MGMT_PSK:
1592 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1593 akm_count--;
1594 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1595 }
1596 if (!akm_count)
1597 break;
1598 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1599 akm_count--;
1600 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1601 }
1602 if (!akm_count)
1603 break;
1604 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1605 wpa_s->allowed_key_mgmts |=
1606 WPA_KEY_MGMT_PSK_SHA256;
1607 break;
1608 case WPA_KEY_MGMT_PSK_SHA256:
1609 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1610 akm_count--;
1611 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1612 }
1613 if (!akm_count)
1614 break;
1615 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1616 akm_count--;
1617 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1618 }
1619 if (!akm_count)
1620 break;
1621 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1622 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1623 break;
1624 case WPA_KEY_MGMT_SAE:
1625 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1626 akm_count--;
1627 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1628 }
1629 if (!akm_count)
1630 break;
1631 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1632 akm_count--;
1633 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1634 }
1635 if (!akm_count)
1636 break;
1637 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1638 wpa_s->allowed_key_mgmts |=
1639 WPA_KEY_MGMT_PSK_SHA256;
1640 break;
1641 case WPA_KEY_MGMT_SAE_EXT_KEY:
1642 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1643 akm_count--;
1644 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1645 }
1646 if (!akm_count)
1647 break;
1648 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1649 akm_count--;
1650 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1651 }
1652 if (!akm_count)
1653 break;
1654 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1655 wpa_s->allowed_key_mgmts |=
1656 WPA_KEY_MGMT_PSK_SHA256;
1657 break;
1658 default:
1659 return;
1660 }
1661
Sunil Ravi77d572f2023-01-17 23:58:31 +00001662 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1663 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001664 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1665#ifdef CONFIG_SAE_PK
1666 if (ssid->sae_pk)
1667 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1668#endif /* CONFIG_SAE_PK */
1669
1670 if (!((wpa_s->allowed_key_mgmts &
1671 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1672 return;
1673
1674 if (!wpa_s->rsnxe_len) {
1675 wpa_s->rsnxe_len = 3;
1676 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1677 wpa_s->rsnxe[1] = 1;
1678 wpa_s->rsnxe[2] = 0;
1679 }
1680
1681 wpa_s->rsnxe[2] |= capab;
1682}
1683
1684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001685/**
1686 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1687 * @wpa_s: Pointer to wpa_supplicant data
1688 * @bss: Scan results for the selected BSS, or %NULL if not available
1689 * @ssid: Configuration data for the selected network
1690 * @wpa_ie: Buffer for the WPA/RSN IE
1691 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1692 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001693 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001694 * Returns: 0 on success or -1 on failure
1695 *
1696 * This function is used to configure authentication and encryption parameters
1697 * based on the network configuration and scan result for the selected BSS (if
1698 * available).
1699 */
1700int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1701 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001702 u8 *wpa_ie, size_t *wpa_ie_len,
1703 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704{
1705 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001706 int sel, proto;
1707 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001708 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001709 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001710
1711 if (bss) {
1712 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
Sunil Ravi7f769292024-07-23 22:21:32 +00001713 bss_rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
1714 bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001715 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001716 } else {
1717 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719
1720 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1721 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001722 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 (ie.key_mgmt & ssid->key_mgmt)) {
1724 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1725 proto = WPA_PROTO_RSN;
1726 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001727 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 (ie.group_cipher & ssid->group_cipher) &&
1729 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1730 (ie.key_mgmt & ssid->key_mgmt)) {
1731 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1732 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001733#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001734 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1735 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1736 (ie.group_cipher & ssid->group_cipher) &&
1737 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1738 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001739 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001740 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001741 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1742 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1743 (ie.group_cipher & ssid->group_cipher) &&
1744 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1745 (ie.key_mgmt & ssid->key_mgmt)) {
1746 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1747 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001748#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749 } else if (bss) {
1750 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001751 wpa_dbg(wpa_s, MSG_DEBUG,
1752 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1753 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1754 ssid->key_mgmt);
1755 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1756 MAC2STR(bss->bssid),
1757 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1758 bss_wpa ? " WPA" : "",
1759 bss_rsn ? " RSN" : "",
1760 bss_osen ? " OSEN" : "");
1761 if (bss_rsn) {
1762 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1763 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1764 wpa_dbg(wpa_s, MSG_DEBUG,
1765 "Could not parse RSN element");
1766 } else {
1767 wpa_dbg(wpa_s, MSG_DEBUG,
1768 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1769 ie.pairwise_cipher, ie.group_cipher,
1770 ie.key_mgmt);
1771 }
1772 }
1773 if (bss_wpa) {
1774 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1775 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1776 wpa_dbg(wpa_s, MSG_DEBUG,
1777 "Could not parse WPA element");
1778 } else {
1779 wpa_dbg(wpa_s, MSG_DEBUG,
1780 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1781 ie.pairwise_cipher, ie.group_cipher,
1782 ie.key_mgmt);
1783 }
1784 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 return -1;
1786 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001787 if (ssid->proto & WPA_PROTO_OSEN)
1788 proto = WPA_PROTO_OSEN;
1789 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001790 proto = WPA_PROTO_RSN;
1791 else
1792 proto = WPA_PROTO_WPA;
1793 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1794 os_memset(&ie, 0, sizeof(ie));
1795 ie.group_cipher = ssid->group_cipher;
1796 ie.pairwise_cipher = ssid->pairwise_cipher;
1797 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001798 ie.mgmt_group_cipher = 0;
1799 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1800 if (ssid->group_mgmt_cipher &
1801 WPA_CIPHER_BIP_GMAC_256)
1802 ie.mgmt_group_cipher =
1803 WPA_CIPHER_BIP_GMAC_256;
1804 else if (ssid->group_mgmt_cipher &
1805 WPA_CIPHER_BIP_CMAC_256)
1806 ie.mgmt_group_cipher =
1807 WPA_CIPHER_BIP_CMAC_256;
1808 else if (ssid->group_mgmt_cipher &
1809 WPA_CIPHER_BIP_GMAC_128)
1810 ie.mgmt_group_cipher =
1811 WPA_CIPHER_BIP_GMAC_128;
1812 else
1813 ie.mgmt_group_cipher =
1814 WPA_CIPHER_AES_128_CMAC;
1815 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001816#ifdef CONFIG_OWE
1817 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1818 !ssid->owe_only &&
1819 !bss_wpa && !bss_rsn && !bss_osen) {
1820 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1821 wpa_s->wpa_proto = 0;
1822 *wpa_ie_len = 0;
1823 return 0;
1824 }
1825#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1827 "based on configuration");
1828 } else
1829 proto = ie.proto;
1830 }
1831
1832 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1833 "pairwise %d key_mgmt %d proto %d",
1834 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 if (ssid->ieee80211w) {
1836 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1837 ie.mgmt_group_cipher);
1838 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001840 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1842 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001843 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844
1845 if (bss || !wpa_s->ap_ies_from_associnfo) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00001846 const u8 *rsnoe = NULL, *rsno2e = NULL, *rsnxoe = NULL;
1847
1848 if (bss) {
1849 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1850 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
1851 rsnoe = wpa_bss_get_vendor_ie(
1852 bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
1853 rsno2e = wpa_bss_get_vendor_ie(
1854 bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
1855 rsnxoe = wpa_bss_get_vendor_ie(
1856 bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
1857 }
1858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001859 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1860 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1861 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001862 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1863 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
Sunil Ravic0f5d412024-09-11 22:12:49 +00001864 bss_rsnx ? 2 + bss_rsnx[1] : 0) ||
1865 wpa_sm_set_ap_rsne_override(wpa_s->wpa, rsnoe,
1866 rsnoe ? 2 + rsnoe[1] : 0) ||
1867 wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
1868 rsno2e ? 2 + rsno2e[1] : 0) ||
1869 wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
1870 rsnxoe ? 2 + rsnxoe[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871 return -1;
1872 }
1873
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001874#ifdef CONFIG_NO_WPA
1875 wpa_s->group_cipher = WPA_CIPHER_NONE;
1876 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1877#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001879 wpa_dbg(wpa_s, MSG_DEBUG,
1880 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1881 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001882 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1883 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1885 "cipher");
1886 return -1;
1887 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001888 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1889 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890
1891 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001892 wpa_dbg(wpa_s, MSG_DEBUG,
1893 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1894 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001895 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1896 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1898 "cipher");
1899 return -1;
1900 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001901 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1902 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001903#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904
1905 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001906#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001907 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1908 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001909 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001910 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1911 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001912#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001913#ifdef CONFIG_IEEE80211R
1914 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1915 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1916 sel &= ~WPA_KEY_MGMT_FT;
1917#endif /* CONFIG_IEEE80211R */
1918 wpa_dbg(wpa_s, MSG_DEBUG,
1919 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1920 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001922#ifdef CONFIG_IEEE80211R
1923#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001924 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1925 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001926 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1927 wpa_dbg(wpa_s, MSG_DEBUG,
1928 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001929 if (!ssid->ft_eap_pmksa_caching &&
1930 pmksa_cache_get_current(wpa_s->wpa)) {
1931 /* PMKSA caching with FT may have interoperability
1932 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001933 wpa_dbg(wpa_s, MSG_DEBUG,
1934 "WPA: Disable PMKSA caching for FT/802.1X connection");
1935 pmksa_cache_clear_current(wpa_s->wpa);
1936 }
1937#endif /* CONFIG_SHA384 */
1938#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001939#ifdef CONFIG_SUITEB192
1940 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1941 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1942 wpa_dbg(wpa_s, MSG_DEBUG,
1943 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1944#endif /* CONFIG_SUITEB192 */
1945#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001946 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1947 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1948 wpa_dbg(wpa_s, MSG_DEBUG,
1949 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001950#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001951#ifdef CONFIG_SHA384
1952 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1953 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1954 wpa_dbg(wpa_s, MSG_DEBUG,
1955 "WPA: using KEY_MGMT 802.1X with SHA384");
1956#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001957#ifdef CONFIG_FILS
1958#ifdef CONFIG_IEEE80211R
1959 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1960 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1961 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001962#endif /* CONFIG_IEEE80211R */
1963 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1964 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1965 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001966#ifdef CONFIG_IEEE80211R
1967 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1968 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1969 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1970#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001971 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1972 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1973 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1974#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001976 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1977 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1979 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001980 if (!ssid->ft_eap_pmksa_caching &&
1981 pmksa_cache_get_current(wpa_s->wpa)) {
1982 /* PMKSA caching with FT may have interoperability
1983 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001984 wpa_dbg(wpa_s, MSG_DEBUG,
1985 "WPA: Disable PMKSA caching for FT/802.1X connection");
1986 pmksa_cache_clear_current(wpa_s->wpa);
1987 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001988#endif /* CONFIG_IEEE80211R */
1989#ifdef CONFIG_DPP
1990 } else if (sel & WPA_KEY_MGMT_DPP) {
1991 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1992 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1993#endif /* CONFIG_DPP */
1994#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001995 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1996 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1997 wpa_dbg(wpa_s, MSG_DEBUG,
1998 "RSN: using KEY_MGMT FT/SAE (ext key)");
1999 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
2000 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
2001 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07002002 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
2003 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
2004 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
2005 } else if (sel & WPA_KEY_MGMT_SAE) {
2006 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
2007 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
2008#endif /* CONFIG_SAE */
2009#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
2011 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
2012 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
2013#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2015 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
2016 wpa_dbg(wpa_s, MSG_DEBUG,
2017 "WPA: using KEY_MGMT 802.1X with SHA256");
2018 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
2019 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
2020 wpa_dbg(wpa_s, MSG_DEBUG,
2021 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
2023 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
2024 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
2025 } else if (sel & WPA_KEY_MGMT_PSK) {
2026 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
2027 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
2028 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
2029 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
2030 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002031#ifdef CONFIG_HS20
2032 } else if (sel & WPA_KEY_MGMT_OSEN) {
2033 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
2034 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
2035#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002036#ifdef CONFIG_OWE
2037 } else if (sel & WPA_KEY_MGMT_OWE) {
2038 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
2039 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
2040#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002041 } else {
2042 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
2043 "authenticated key management type");
2044 return -1;
2045 }
2046
2047 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
2048 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
2049 wpa_s->pairwise_cipher);
2050 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
2051
Hai Shalomc3565922019-10-28 11:58:20 -07002052 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002053 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
2054 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07002055 wpa_msg(wpa_s, MSG_INFO,
2056 "RSN: Management frame protection required but the selected AP does not enable it");
2057 return -1;
2058 }
2059
Hai Shalomc1a21442022-02-04 13:43:00 -08002060 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08002061#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08002062 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
2063 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
2064 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08002065#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07002066 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07002067 if ((ssid->sae_password_id ||
2068 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002069 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
2070 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
2071 if (bss && is_6ghz_freq(bss->freq) &&
2072 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
2073 wpa_dbg(wpa_s, MSG_DEBUG,
2074 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
2075 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08002076 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002077 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07002078#ifdef CONFIG_SAE_PK
2079 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
2080 wpa_key_mgmt_sae(ssid->key_mgmt) &&
2081 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
2082 ((ssid->sae_password &&
2083 sae_pk_valid_password(ssid->sae_password)) ||
2084 (!ssid->sae_password && ssid->passphrase &&
2085 sae_pk_valid_password(ssid->passphrase))));
2086#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002087 if (bss && is_6ghz_freq(bss->freq) &&
2088 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
2089 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
2090 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
2091 MGMT_FRAME_PROTECTION_REQUIRED);
2092 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07002093#ifdef CONFIG_TESTING_OPTIONS
2094 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
2095 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07002096 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
2097 wpa_s->oci_freq_override_eapol);
2098 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
2099 wpa_s->oci_freq_override_eapol_g2);
2100 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
2101 wpa_s->oci_freq_override_ft_assoc);
2102 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
2103 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07002104 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
2105 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07002106#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07002107
2108 /* Extended Key ID is only supported in infrastructure BSS so far */
2109 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
2110 (ssid->proto & WPA_PROTO_RSN) &&
2111 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
2112 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
2113 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
2114 int use_ext_key_id = 0;
2115
2116 wpa_msg(wpa_s, MSG_DEBUG,
2117 "WPA: Enable Extended Key ID support");
2118 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
2119 wpa_s->conf->extended_key_id);
2120 if (bss_rsn &&
2121 wpa_s->conf->extended_key_id &&
2122 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
2123 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
2124 use_ext_key_id = 1;
2125 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
2126 use_ext_key_id);
2127 } else {
2128 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
2129 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
2130 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131
Sunil Ravi640215c2023-06-28 23:08:09 +00002132 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2133 * appropriate advertisement of the supported number of PTKSA receive
2134 * counters. In theory, this could be based on a driver capability, but
2135 * in practice all cases using WMM support at least eight replay
2136 * counters, so use a hardcoded value for now since there is no explicit
2137 * driver capability indication for this.
2138 *
2139 * In addition, claim WMM to be enabled if the AP supports it since it
2140 * is far more likely for any current device to support WMM. */
2141 wmm = wpa_s->connection_set &&
2142 (wpa_s->connection_ht || wpa_s->connection_vht ||
2143 wpa_s->connection_he || wpa_s->connection_eht);
2144 if (!wmm && bss)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002145 wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
Sunil Ravi640215c2023-06-28 23:08:09 +00002146 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2147
Sunil Ravi7f769292024-07-23 22:21:32 +00002148 if (ssid->ssid_protection && proto == WPA_PROTO_RSN) {
2149 bool ssid_prot;
2150
2151 /* Enable SSID protection based on the AP advertising support
2152 * for it to avoid potential interoperability issues with
2153 * incorrect AP behavior if we were to send an "unexpected"
2154 * RSNXE with multiple octets of payload. */
2155 ssid_prot = ieee802_11_rsnx_capab(
2156 bss_rsnx, WLAN_RSNX_CAPAB_SSID_PROTECTION);
2157 if (!skip_default_rsne)
2158 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION,
2159 proto == WPA_PROTO_RSN && ssid_prot);
2160 } else {
2161 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, false);
2162 }
2163
Sunil Ravi77d572f2023-01-17 23:58:31 +00002164 if (!skip_default_rsne) {
2165 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2166 wpa_ie_len)) {
2167 wpa_msg(wpa_s, MSG_WARNING,
2168 "RSN: Failed to generate RSNE/WPA IE");
2169 return -1;
2170 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171
Matthew Wang9ed1c792024-12-02 14:05:18 +00002172#ifndef CONFIG_NO_WPA
Sunil Ravi77d572f2023-01-17 23:58:31 +00002173 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2174 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2175 &wpa_s->rsnxe_len)) {
2176 wpa_msg(wpa_s, MSG_WARNING,
2177 "RSN: Failed to generate RSNXE");
2178 return -1;
2179 }
Matthew Wang9ed1c792024-12-02 14:05:18 +00002180#endif /* CONFIG_NO_WPA */
Hai Shalomc3565922019-10-28 11:58:20 -07002181 }
2182
Hai Shalom021b0b52019-04-10 11:17:58 -07002183 if (0) {
2184#ifdef CONFIG_DPP
2185 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2186 /* Use PMK from DPP network introduction (PMKSA entry) */
2187 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002188#ifdef CONFIG_DPP2
2189 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2190#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002191#endif /* CONFIG_DPP */
2192 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002193 int psk_set = 0;
2194
Sunil Ravi77d572f2023-01-17 23:58:31 +00002195 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2196 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002197
Sunil Ravi77d572f2023-01-17 23:58:31 +00002198 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2199 psk) == 0) {
2200 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2201 NULL);
2202 psk_set = 1;
2203 }
2204 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002205 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002206
Roshan Pius3a1667e2018-07-03 15:17:14 -07002207 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002208 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002209 psk_set = 1;
2210
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002211 if (!psk_set) {
2212 wpa_msg(wpa_s, MSG_INFO,
2213 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002214 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002215 return -1;
2216 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002217#ifdef CONFIG_OWE
2218 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2219 /* OWE Diffie-Hellman exchange in (Re)Association
2220 * Request/Response frames set the PMK, so do not override it
2221 * here. */
2222#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002223 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2225
Hai Shalomfdcde762020-04-02 11:19:20 -07002226 if (ssid->mode != WPAS_MODE_IBSS &&
2227 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2228 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2229 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2230 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2231 wpa_msg(wpa_s, MSG_INFO,
2232 "Disable PTK0 rekey support - replaced with reconnect");
2233 wpa_s->deny_ptk0_rekey = 1;
2234 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2235 } else {
2236 wpa_s->deny_ptk0_rekey = 0;
2237 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2238 }
2239
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002240#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
2241 defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302242 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002243 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2244 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002245 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2246 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302247 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2248 wpa_dbg(wpa_s, MSG_INFO,
2249 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2250 }
Sunil Ravif42be322022-11-04 03:31:21 +00002251#else
2252 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2253 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2254 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Isaac Chiou6ce580d2024-04-24 17:07:24 +08002255#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
2256 * CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 return 0;
2259}
2260
2261
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002262static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2263 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002264{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002265#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002266 bool scs = true, mscs = true;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002267#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08002268
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002269 *pos = 0x00;
2270
2271 switch (idx) {
2272 case 0: /* Bits 0-7 */
2273 break;
2274 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002275 if (wpa_s->conf->coloc_intf_reporting) {
2276 /* Bit 13 - Collocated Interference Reporting */
2277 *pos |= 0x20;
2278 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002279 break;
2280 case 2: /* Bits 16-23 */
2281#ifdef CONFIG_WNM
2282 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002283 if ((wpas_driver_bss_selection(wpa_s) ||
2284 !wpa_s->disable_mbo_oce) &&
2285 !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002286 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002287#endif /* CONFIG_WNM */
2288 break;
2289 case 3: /* Bits 24-31 */
2290#ifdef CONFIG_WNM
2291 *pos |= 0x02; /* Bit 25 - SSID List */
2292#endif /* CONFIG_WNM */
2293#ifdef CONFIG_INTERWORKING
2294 if (wpa_s->conf->interworking)
2295 *pos |= 0x80; /* Bit 31 - Interworking */
2296#endif /* CONFIG_INTERWORKING */
2297 break;
2298 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002299#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002300 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002301 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002302#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002303 break;
2304 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002305#ifdef CONFIG_HS20
2306 if (wpa_s->conf->hs20)
2307 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2308#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002309#ifdef CONFIG_MBO
2310 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2311#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002312 break;
2313 case 6: /* Bits 48-55 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002314#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002315#ifdef CONFIG_TESTING_OPTIONS
2316 if (wpa_s->disable_scs_support)
2317 scs = false;
2318#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002319 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2320 /* Drop own SCS capability indication since the AP does
2321 * not support it. This is needed to avoid
2322 * interoperability issues with APs that get confused
2323 * with Extended Capabilities element. */
2324 scs = false;
2325 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002326 if (scs)
2327 *pos |= 0x40; /* Bit 54 - SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002328#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002329 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002330 case 7: /* Bits 56-63 */
2331 break;
2332 case 8: /* Bits 64-71 */
2333 if (wpa_s->conf->ftm_responder)
2334 *pos |= 0x40; /* Bit 70 - FTM responder */
2335 if (wpa_s->conf->ftm_initiator)
2336 *pos |= 0x80; /* Bit 71 - FTM initiator */
2337 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002338 case 9: /* Bits 72-79 */
2339#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002340 if (!wpa_s->disable_fils)
2341 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002342#endif /* CONFIG_FILS */
2343 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002344 case 10: /* Bits 80-87 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002345#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08002346#ifdef CONFIG_TESTING_OPTIONS
2347 if (wpa_s->disable_mscs_support)
2348 mscs = false;
2349#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002350 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2351 /* Drop own MSCS capability indication since the AP does
2352 * not support it. This is needed to avoid
2353 * interoperability issues with APs that get confused
2354 * with Extended Capabilities element. */
2355 mscs = false;
2356 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002357 if (mscs)
2358 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002359#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002360 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002361 }
2362}
2363
2364
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002365int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2366 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002367{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002368 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002369 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002370
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002371 if (len < wpa_s->extended_capa_len)
2372 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002373 if (buflen < (size_t) len + 2) {
2374 wpa_printf(MSG_INFO,
2375 "Not enough room for building extended capabilities element");
2376 return -1;
2377 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002378
2379 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002380 *pos++ = len;
2381 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002382 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002383
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002384 if (i < wpa_s->extended_capa_len) {
2385 *pos &= ~wpa_s->extended_capa_mask[i];
2386 *pos |= wpa_s->extended_capa[i];
2387 }
2388 }
2389
2390 while (len > 0 && buf[1 + len] == 0) {
2391 len--;
2392 buf[1] = len;
2393 }
2394 if (len == 0)
2395 return 0;
2396
2397 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002398}
2399
2400
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002401static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2402 struct wpa_bss *test_bss)
2403{
2404 struct wpa_bss *bss;
2405
2406 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2407 if (bss == test_bss)
2408 return 1;
2409 }
2410
2411 return 0;
2412}
2413
2414
2415static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2416 struct wpa_ssid *test_ssid)
2417{
2418 struct wpa_ssid *ssid;
2419
2420 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2421 if (ssid == test_ssid)
2422 return 1;
2423 }
2424
2425 return 0;
2426}
2427
2428
2429int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2430 struct wpa_ssid *test_ssid)
2431{
2432 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2433 return 0;
2434
2435 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2436}
2437
2438
2439void wpas_connect_work_free(struct wpa_connect_work *cwork)
2440{
2441 if (cwork == NULL)
2442 return;
2443 os_free(cwork);
2444}
2445
2446
2447void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2448{
2449 struct wpa_connect_work *cwork;
2450 struct wpa_radio_work *work = wpa_s->connect_work;
2451
2452 if (!work)
2453 return;
2454
2455 wpa_s->connect_work = NULL;
2456 cwork = work->ctx;
2457 work->ctx = NULL;
2458 wpas_connect_work_free(cwork);
2459 radio_work_done(work);
2460}
2461
2462
Sunil Ravi77d572f2023-01-17 23:58:31 +00002463int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2464 enum wpas_mac_addr_style style,
2465 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002466{
2467 struct os_reltime now;
2468 u8 addr[ETH_ALEN];
2469
2470 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002471 /* Random addresses are valid within a given ESS so check
2472 * expiration/value only when continuing to use the same ESS. */
2473 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2474 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2475 /* Pregenerated addresses do not expire but their value
2476 * might have changed, so let's check that. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002477 if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
Sunil Ravi77d572f2023-01-17 23:58:31 +00002478 return 0;
2479 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2480 wpa_s->last_mac_addr_change.usec != 0) &&
2481 !os_reltime_expired(
2482 &now,
2483 &wpa_s->last_mac_addr_change,
2484 wpa_s->conf->rand_addr_lifetime)) {
2485 wpa_msg(wpa_s, MSG_DEBUG,
2486 "Previously selected random MAC address has not yet expired");
2487 return 0;
2488 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002489 }
2490
2491 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002492 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002493 if (random_mac_addr(addr) < 0)
2494 return -1;
2495 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002496 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002497 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2498 if (random_mac_addr_keep_oui(addr) < 0)
2499 return -1;
2500 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002501 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2502 if (!ssid) {
2503 wpa_msg(wpa_s, MSG_INFO,
2504 "Invalid 'ssid' for address policy 3");
2505 return -1;
2506 }
2507 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2508 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002509 default:
2510 return -1;
2511 }
2512
2513 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2514 wpa_msg(wpa_s, MSG_INFO,
2515 "Failed to set random MAC address");
2516 return -1;
2517 }
2518
2519 os_get_reltime(&wpa_s->last_mac_addr_change);
2520 wpa_s->mac_addr_changed = 1;
2521 wpa_s->last_mac_addr_style = style;
2522
2523 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2524 wpa_msg(wpa_s, MSG_INFO,
2525 "Could not update MAC address information");
2526 return -1;
2527 }
2528
2529 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2530 MAC2STR(addr));
2531
Sunil Ravi77d572f2023-01-17 23:58:31 +00002532 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002533}
2534
2535
2536int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2537{
2538 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2539 !wpa_s->conf->preassoc_mac_addr)
2540 return 0;
2541
Sunil Ravi77d572f2023-01-17 23:58:31 +00002542 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2543 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002544}
2545
2546
Sunil Ravi036cec52023-03-29 11:35:17 -07002547void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2548 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002549{
2550#ifdef CONFIG_SAE
2551 int *groups = conf->sae_groups;
2552 int default_groups[] = { 19, 20, 21, 0 };
2553 const char *password;
2554
2555 if (!groups || groups[0] <= 0)
2556 groups = default_groups;
2557
2558 password = ssid->sae_password;
2559 if (!password)
2560 password = ssid->passphrase;
2561
Hai Shalom899fcc72020-10-19 14:38:18 -07002562 if (!password ||
Sunil Ravi7f769292024-07-23 22:21:32 +00002563 !wpa_key_mgmt_sae(ssid->key_mgmt) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002564 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002565 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002566 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002567 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002568 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002569 /* PT derivation not needed */
2570 sae_deinit_pt(ssid->pt);
2571 ssid->pt = NULL;
2572 return;
2573 }
2574
2575 if (ssid->pt)
2576 return; /* PT already derived */
2577 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2578 (const u8 *) password, os_strlen(password),
2579 ssid->sae_password_id);
2580#endif /* CONFIG_SAE */
2581}
2582
2583
Sunil Ravi7f769292024-07-23 22:21:32 +00002584void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002585{
2586#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2587 os_free(wpa_s->sme.sae_rejected_groups);
2588 wpa_s->sme.sae_rejected_groups = NULL;
2589#ifdef CONFIG_TESTING_OPTIONS
2590 if (wpa_s->extra_sae_rejected_groups) {
2591 int i, *groups = wpa_s->extra_sae_rejected_groups;
2592
2593 for (i = 0; groups[i]; i++) {
2594 wpa_printf(MSG_DEBUG,
2595 "TESTING: Indicate rejection of an extra SAE group %d",
2596 groups[i]);
2597 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2598 groups[i]);
2599 }
2600 }
2601#endif /* CONFIG_TESTING_OPTIONS */
2602#endif /* CONFIG_SAE && CONFIG_SME */
2603}
2604
2605
Hai Shalom60840252021-02-19 19:02:11 -08002606int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2607{
2608 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2609 wpa_msg(wpa_s, MSG_INFO,
2610 "Could not restore permanent MAC address");
2611 return -1;
2612 }
2613 wpa_s->mac_addr_changed = 0;
2614 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2615 wpa_msg(wpa_s, MSG_INFO,
2616 "Could not update MAC address information");
2617 return -1;
2618 }
2619 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2620 return 0;
2621}
2622
2623
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002624static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2625
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626/**
2627 * wpa_supplicant_associate - Request association
2628 * @wpa_s: Pointer to wpa_supplicant data
2629 * @bss: Scan results for the selected BSS, or %NULL if not available
2630 * @ssid: Configuration data for the selected network
2631 *
2632 * This function is used to request %wpa_supplicant to associate with a BSS.
2633 */
2634void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2635 struct wpa_bss *bss, struct wpa_ssid *ssid)
2636{
Sunil Ravi7f769292024-07-23 22:21:32 +00002637 bool clear_rejected = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002638 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002639 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002640
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002641 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002642 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002643
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002644 /*
2645 * If we are starting a new connection, any previously pending EAPOL
2646 * RX cannot be valid anymore.
2647 */
2648 wpabuf_free(wpa_s->pending_eapol_rx);
2649 wpa_s->pending_eapol_rx = NULL;
2650
Sunil Ravi77d572f2023-01-17 23:58:31 +00002651 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002652 rand_style = wpa_s->conf->mac_addr;
2653 else
2654 rand_style = ssid->mac_addr;
2655
Sunil Ravia04bd252022-05-02 22:54:18 -07002656 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002657 wpa_s->multi_ap_ie = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002658#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002659 wmm_ac_clear_saved_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002660#endif /* CONFIG_NO_WMM_AC */
2661#ifdef CONFIG_WNM
2662 wpa_s->wnm_mode = 0;
Sunil Ravi99c035e2024-07-12 01:42:03 +00002663 wpa_s->wnm_target_bss = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002664#endif /* CONFIG_WNM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002665 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002666 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002667#ifdef CONFIG_TESTING_OPTIONS
2668 wpa_s->testing_resend_assoc = 0;
2669#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002670
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002671 if (wpa_s->last_ssid == ssid) {
2672 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002673 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002674 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002675#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002676 wmm_ac_save_tspecs(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002677#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002678 wpa_s->reassoc_same_bss = 1;
Sunil Ravi7f769292024-07-23 22:21:32 +00002679 clear_rejected = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08002680 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2681 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002682 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002683 }
Sunil Ravi7f769292024-07-23 22:21:32 +00002684
2685 if (clear_rejected)
2686 wpa_s_clear_sae_rejected(wpa_s);
2687
Hai Shalomc1a21442022-02-04 13:43:00 -08002688#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002689 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002690#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002691
Sunil Ravi77d572f2023-01-17 23:58:31 +00002692 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2693 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2694
2695 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002696 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002697 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2698 status > 0) /* MAC changed */
2699 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2700 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2701 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002702 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002703 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002704 }
2705 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706
2707#ifdef CONFIG_IBSS_RSN
2708 ibss_rsn_deinit(wpa_s->ibss_rsn);
2709 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002710#else /* CONFIG_IBSS_RSN */
2711 if (ssid->mode == WPAS_MODE_IBSS &&
2712 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2713 wpa_msg(wpa_s, MSG_INFO,
2714 "IBSS RSN not supported in the build");
2715 return;
2716 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717#endif /* CONFIG_IBSS_RSN */
2718
2719 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2720 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2721#ifdef CONFIG_AP
2722 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2723 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2724 "mode");
2725 return;
2726 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002727 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2728 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302729 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
2730 ssid->mode == WPAS_MODE_P2P_GO) {
2731 wpa_msg(wpa_s, MSG_ERROR, "create ap failed. clean up the states");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002732 wpas_p2p_ap_setup_failed(wpa_s);
Ajay Davanageri10b3c662024-05-02 19:19:24 +05302733 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002734 return;
2735 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002736 wpa_s->current_bss = bss;
2737#else /* CONFIG_AP */
2738 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2739 "the build");
2740#endif /* CONFIG_AP */
2741 return;
2742 }
2743
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002744 if (ssid->mode == WPAS_MODE_MESH) {
2745#ifdef CONFIG_MESH
2746 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2747 wpa_msg(wpa_s, MSG_INFO,
2748 "Driver does not support mesh mode");
2749 return;
2750 }
2751 if (bss)
2752 ssid->frequency = bss->freq;
2753 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002754 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002755 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2756 return;
2757 }
2758 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002759#else /* CONFIG_MESH */
2760 wpa_msg(wpa_s, MSG_ERROR,
2761 "mesh mode support not included in the build");
2762#endif /* CONFIG_MESH */
2763 return;
2764 }
2765
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002766 /*
2767 * Set WPA state machine configuration to match the selected network now
2768 * so that the information is available before wpas_start_assoc_cb()
2769 * gets called. This is needed at least for RSN pre-authentication where
2770 * candidate APs are added to a list based on scan result processing
2771 * before completion of the first association.
2772 */
2773 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2774
2775#ifdef CONFIG_DPP
2776 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2777 return;
2778#endif /* CONFIG_DPP */
2779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780#ifdef CONFIG_TDLS
2781 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002782 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783#endif /* CONFIG_TDLS */
2784
Hai Shalomc3565922019-10-28 11:58:20 -07002785#ifdef CONFIG_MBO
2786 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2787#endif /* CONFIG_MBO */
2788
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002790 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 sme_authenticate(wpa_s, bss, ssid);
2792 return;
2793 }
2794
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002795 if (wpa_s->connect_work) {
2796 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2797 return;
2798 }
2799
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002800 if (radio_work_pending(wpa_s, "connect")) {
2801 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2802 return;
2803 }
2804
Dmitry Shmidt29333592017-01-09 12:27:11 -08002805#ifdef CONFIG_SME
2806 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2807 /* Clear possibly set auth_alg, if any, from last attempt. */
2808 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2809 }
2810#endif /* CONFIG_SME */
2811
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002812 wpas_abort_ongoing_scan(wpa_s);
2813
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002814 cwork = os_zalloc(sizeof(*cwork));
2815 if (cwork == NULL)
2816 return;
2817
2818 cwork->bss = bss;
2819 cwork->ssid = ssid;
2820
2821 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2822 wpas_start_assoc_cb, cwork) < 0) {
2823 os_free(cwork);
2824 }
2825}
2826
2827
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002828static int bss_is_ibss(struct wpa_bss *bss)
2829{
2830 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2831 IEEE80211_CAP_IBSS;
2832}
2833
2834
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002835static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2836 const struct wpa_ssid *ssid)
2837{
2838 enum hostapd_hw_mode hw_mode;
2839 struct hostapd_hw_modes *mode = NULL;
2840 u8 channel;
2841 int i;
2842
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002843 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2844 if (hw_mode == NUM_HOSTAPD_MODES)
2845 return 0;
2846 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2847 if (wpa_s->hw.modes[i].mode == hw_mode) {
2848 mode = &wpa_s->hw.modes[i];
2849 break;
2850 }
2851 }
2852
2853 if (!mode)
2854 return 0;
2855
2856 return mode->vht_capab != 0;
2857}
2858
2859
Hai Shalomc1a21442022-02-04 13:43:00 -08002860static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2861{
2862 int i;
2863
2864 for (i = channel; i < channel + 16; i += 4) {
2865 struct hostapd_channel_data *chan;
2866
2867 chan = hw_get_channel_chan(mode, i, NULL);
2868 if (!chan ||
2869 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2870 return false;
2871 }
2872
2873 return true;
2874}
2875
2876
Sunil Ravi036cec52023-03-29 11:35:17 -07002877static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2878 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002879{
Sunil Ravi036cec52023-03-29 11:35:17 -07002880 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002881
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002882 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2883 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2884
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002885 if (!bss_is_ibss(bss))
2886 continue;
2887
2888 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002889 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2890 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002891 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002892 return NULL;
2893}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002894
Sunil Ravi036cec52023-03-29 11:35:17 -07002895
2896static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2897 const struct wpa_ssid *ssid,
2898 struct hostapd_hw_modes *mode)
2899{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002900 /* For IBSS check HT_IBSS flag */
2901 if (ssid->mode == WPAS_MODE_IBSS &&
2902 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002903 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002904
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002905 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2906 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2907 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2908 wpa_printf(MSG_DEBUG,
2909 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002910 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002911 }
2912
Sunil Ravi036cec52023-03-29 11:35:17 -07002913 if (!ht_supported(mode))
2914 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002915
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002916#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002917 if (ssid->disable_ht)
2918 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002919#endif /* CONFIG_HT_OVERRIDES */
2920
Sunil Ravi036cec52023-03-29 11:35:17 -07002921 return true;
2922}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002923
Sunil Ravi036cec52023-03-29 11:35:17 -07002924
2925static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2926 const struct wpa_ssid *ssid,
2927 struct hostapd_hw_modes *mode)
2928{
2929 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2930 return false;
2931
2932 if (!drv_supports_vht(wpa_s, ssid))
2933 return false;
2934
2935 /* For IBSS check VHT_IBSS flag */
2936 if (ssid->mode == WPAS_MODE_IBSS &&
2937 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2938 return false;
2939
2940 if (!vht_supported(mode))
2941 return false;
2942
2943#ifdef CONFIG_VHT_OVERRIDES
2944 if (ssid->disable_vht)
2945 return false;
2946#endif /* CONFIG_VHT_OVERRIDES */
2947
2948 return true;
2949}
2950
2951
2952static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2953 const struct wpa_ssid *ssid,
2954 const struct hostapd_hw_modes *mode,
2955 int ieee80211_mode)
2956{
Hai Shalomfdcde762020-04-02 11:19:20 -07002957#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002958 if (ssid->disable_he)
2959 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002960#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002961
Sunil Ravi036cec52023-03-29 11:35:17 -07002962 switch (mode->mode) {
2963 case HOSTAPD_MODE_IEEE80211G:
2964 case HOSTAPD_MODE_IEEE80211B:
2965 case HOSTAPD_MODE_IEEE80211A:
2966 return mode->he_capab[ieee80211_mode].he_supported;
2967 default:
2968 return false;
2969 }
2970}
2971
2972
2973static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2974 const struct wpa_ssid *ssid,
2975 const struct hostapd_hw_modes *mode,
2976 int ieee80211_mode)
2977{
2978 if (ssid->disable_eht)
2979 return false;
2980
2981 switch(mode->mode) {
2982 case HOSTAPD_MODE_IEEE80211G:
2983 case HOSTAPD_MODE_IEEE80211B:
2984 case HOSTAPD_MODE_IEEE80211A:
2985 return mode->eht_capab[ieee80211_mode].eht_supported;
2986 default:
2987 return false;
2988 }
2989}
2990
2991
2992static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2993 const struct wpa_ssid *ssid,
2994 struct hostapd_hw_modes *mode,
2995 struct hostapd_freq_params *freq,
2996 int obss_scan) {
2997 int chan_idx;
2998 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2999 int i, res;
3000 unsigned int j;
3001 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003002 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
3003 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07003004 };
3005 int ht40 = -1;
3006
3007 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003008 return;
3009
3010 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
3011 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07003012 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003013 break;
3014 pri_chan = NULL;
3015 }
3016 if (!pri_chan)
3017 return;
3018
3019 /* Check primary channel flags */
3020 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
3021 return;
3022
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003023#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07003024 if (ssid->disable_ht40)
3025 return;
3026#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003027
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003028 /* Check/setup HT40+/HT40- */
3029 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07003030 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003031 ht40 = 1;
3032 break;
3033 }
3034 }
3035
3036 /* Find secondary channel */
3037 for (i = 0; i < mode->num_channels; i++) {
3038 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07003039 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003040 break;
3041 sec_chan = NULL;
3042 }
3043 if (!sec_chan)
3044 return;
3045
3046 /* Check secondary channel flags */
3047 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
3048 return;
3049
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003050 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003051 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
3052 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003053 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003054 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
3055 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003056 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003057 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003058
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003059 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003060 struct wpa_scan_results *scan_res;
3061
Sunil Ravi99c035e2024-07-12 01:42:03 +00003062 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
3063 NULL);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003064 if (scan_res == NULL) {
3065 /* Back to HT20 */
3066 freq->sec_channel_offset = 0;
3067 return;
3068 }
3069
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003070 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003071 switch (res) {
3072 case 0:
3073 /* Back to HT20 */
3074 freq->sec_channel_offset = 0;
3075 break;
3076 case 1:
3077 /* Configuration allowed */
3078 break;
3079 case 2:
3080 /* Switch pri/sec channels */
3081 freq->freq = hw_get_freq(mode, sec_chan->chan);
3082 freq->sec_channel_offset = -freq->sec_channel_offset;
3083 freq->channel = sec_chan->chan;
3084 break;
3085 default:
3086 freq->sec_channel_offset = 0;
3087 break;
3088 }
3089
3090 wpa_scan_results_free(scan_res);
3091 }
3092
3093 wpa_printf(MSG_DEBUG,
3094 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
3095 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07003096}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003097
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003098
Sunil Ravi036cec52023-03-29 11:35:17 -07003099static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
3100 const struct wpa_ssid *ssid,
3101 struct hostapd_hw_modes *mode,
3102 struct hostapd_freq_params *freq,
3103 int ieee80211_mode, bool is_6ghz) {
3104 static const int bw80[] = {
3105 5180, 5260, 5500, 5580, 5660, 5745, 5825,
3106 5955, 6035, 6115, 6195, 6275, 6355, 6435,
3107 6515, 6595, 6675, 6755, 6835, 6915, 6995
3108 };
3109 static const int bw160[] = {
3110 5955, 6115, 6275, 6435, 6595, 6755, 6915
3111 };
3112 struct hostapd_freq_params vht_freq;
3113 int i;
3114 unsigned int j, k;
3115 int chwidth, seg0, seg1;
3116 u32 vht_caps = 0;
3117 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003118
Sunil Ravi036cec52023-03-29 11:35:17 -07003119 if (!freq->vht_enabled && !freq->he_enabled)
3120 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08003121
Hai Shalomc1a21442022-02-04 13:43:00 -08003122 vht_freq = *freq;
3123
Sunil Ravi036cec52023-03-29 11:35:17 -07003124 chwidth = CONF_OPER_CHWIDTH_USE_HT;
3125 seg0 = freq->channel + 2 * freq->sec_channel_offset;
3126 seg1 = 0;
3127 if (freq->sec_channel_offset == 0) {
3128 seg0 = 0;
3129 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
3130 if (freq->ht_enabled && !is_6ghz)
3131 goto skip_80mhz;
3132 }
3133 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
3134 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07003135
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003136 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003137 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
3138 if (freq->freq >= bw80[j] &&
3139 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003140 break;
3141 }
3142
Hai Shalomc1a21442022-02-04 13:43:00 -08003143 if (j == ARRAY_SIZE(bw80) ||
3144 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003145 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003146
Sunil Ravi036cec52023-03-29 11:35:17 -07003147 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08003148 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07003149 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003150
Sunil8cd6f4d2022-06-28 18:40:46 +00003151 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003152 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003153 seg1 = 0;
3154
Sunil Ravi036cec52023-03-29 11:35:17 -07003155 /* In 160 MHz, the initial four 20 MHz channels were validated
3156 * above. If 160 MHz is supported, check the remaining four 20 MHz
3157 * channels for the total of 160 MHz bandwidth for 6 GHz.
3158 */
Hai Shalomc1a21442022-02-04 13:43:00 -08003159 if ((mode->he_capab[ieee80211_mode].phy_cap[
3160 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07003161 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
3162 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003163 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
3164 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003165 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003166 seg0 = channel + 14;
3167 break;
3168 }
3169 }
3170 }
3171
Sunil8cd6f4d2022-06-28 18:40:46 +00003172 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003173 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08003174 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003175 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003176 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003177 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003178
3179 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3180 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003181 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003182
3183 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003184 struct hostapd_channel_data *chan;
3185
3186 chan = hw_get_channel_chan(mode, i, NULL);
3187 if (!chan)
3188 continue;
3189
3190 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3191 HOSTAPD_CHAN_NO_IR |
3192 HOSTAPD_CHAN_RADAR))
3193 continue;
3194
3195 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003196 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003197 if (!is_6ghz)
3198 vht_caps |=
3199 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3200 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003201 }
3202
Sunil8cd6f4d2022-06-28 18:40:46 +00003203 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003204 break;
3205 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003206 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003207 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003208 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003209 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3210 seg0 = 50;
3211 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003212 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003213 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3214 seg0 = 114;
3215 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003216 }
3217
Sunil Ravi036cec52023-03-29 11:35:17 -07003218skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003219 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003220 freq->channel, ssid->enable_edmg,
3221 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003222 freq->vht_enabled, freq->he_enabled,
3223 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003224 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003225 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003226 &mode->he_capab[ieee80211_mode],
Sunil Ravi99c035e2024-07-12 01:42:03 +00003227 &mode->eht_capab[ieee80211_mode], 0) != 0)
Sunil Ravi036cec52023-03-29 11:35:17 -07003228 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003229
3230 *freq = vht_freq;
3231
3232 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3233 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003234 return true;
3235}
3236
3237
3238void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3239 const struct wpa_ssid *ssid,
3240 struct hostapd_freq_params *freq)
3241{
3242 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3243 enum hostapd_hw_mode hw_mode;
3244 struct hostapd_hw_modes *mode = NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +00003245 int obss_scan = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -07003246 u8 channel;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003247 bool is_6ghz, is_24ghz;
Sunil Ravi036cec52023-03-29 11:35:17 -07003248
3249 freq->freq = ssid->frequency;
3250
3251 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3252 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3253
3254 if (bss) {
3255 wpa_printf(MSG_DEBUG,
3256 "IBSS already found in scan results, adjust control freq: %d",
3257 bss->freq);
3258 freq->freq = bss->freq;
3259 obss_scan = 0;
3260 }
3261 }
3262
3263 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Sunil Ravi7f769292024-07-23 22:21:32 +00003264 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3265 hw_mode, is_6ghz_freq(ssid->frequency));
Sunil Ravi036cec52023-03-29 11:35:17 -07003266
3267 if (!mode)
3268 return;
3269
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003270 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
3271 hw_mode == HOSTAPD_MODE_IEEE80211B;
3272
Sunil Ravi036cec52023-03-29 11:35:17 -07003273 is_6ghz = is_6ghz_freq(freq->freq);
3274
3275 freq->ht_enabled = 0;
3276 freq->vht_enabled = 0;
3277 freq->he_enabled = 0;
3278 freq->eht_enabled = 0;
3279
3280 if (!is_6ghz)
3281 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3282 if (freq->ht_enabled)
3283 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003284 if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
Sunil Ravi036cec52023-03-29 11:35:17 -07003285 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3286 ieee80211_mode);
3287 freq->channel = channel;
3288 /* Setup higher BW only for 5 GHz */
3289 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3290 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3291 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3292 ieee80211_mode, is_6ghz))
3293 freq->he_enabled = freq->vht_enabled = false;
3294 }
3295
3296 if (freq->he_enabled)
3297 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3298 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003299}
3300
3301
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003302#ifdef CONFIG_FILS
3303static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3304 size_t ie_buf_len)
3305{
3306 struct fils_hlp_req *req;
3307 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3308 const u8 *pos;
3309 u8 *buf = ie_buf;
3310
3311 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3312 list) {
3313 rem_len = ie_buf_len - ie_len;
3314 pos = wpabuf_head(req->pkt);
3315 hdr_len = 1 + 2 * ETH_ALEN + 6;
3316 hlp_len = wpabuf_len(req->pkt);
3317
3318 if (rem_len < 2 + hdr_len + hlp_len) {
3319 wpa_printf(MSG_ERROR,
3320 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3321 (unsigned long) rem_len,
3322 (unsigned long) (2 + hdr_len + hlp_len));
3323 break;
3324 }
3325
3326 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3327 /* Element ID */
3328 *buf++ = WLAN_EID_EXTENSION;
3329 /* Length */
3330 *buf++ = len;
3331 /* Element ID Extension */
3332 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3333 /* Destination MAC address */
3334 os_memcpy(buf, req->dst, ETH_ALEN);
3335 buf += ETH_ALEN;
3336 /* Source MAC address */
3337 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3338 buf += ETH_ALEN;
3339 /* LLC/SNAP Header */
3340 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3341 buf += 6;
3342 /* HLP Packet */
3343 os_memcpy(buf, pos, len - hdr_len);
3344 buf += len - hdr_len;
3345 pos += len - hdr_len;
3346
3347 hlp_len -= len - hdr_len;
3348 ie_len += 2 + len;
3349 rem_len -= 2 + len;
3350
3351 while (hlp_len) {
3352 len = (hlp_len > 255) ? 255 : hlp_len;
3353 if (rem_len < 2 + len)
3354 break;
3355 *buf++ = WLAN_EID_FRAGMENT;
3356 *buf++ = len;
3357 os_memcpy(buf, pos, len);
3358 buf += len;
3359 pos += len;
3360
3361 hlp_len -= len;
3362 ie_len += 2 + len;
3363 rem_len -= 2 + len;
3364 }
3365 }
3366
3367 return ie_len;
3368}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003369
3370
3371int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3372{
3373 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3374 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3375 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3376 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3377}
3378
3379
3380int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3381{
3382#ifdef CONFIG_FILS_SK_PFS
3383 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3384 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3385#else /* CONFIG_FILS_SK_PFS */
3386 return 0;
3387#endif /* CONFIG_FILS_SK_PFS */
3388}
3389
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390#endif /* CONFIG_FILS */
3391
3392
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003393bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3394{
3395 const u8 *wfa_capa;
3396
3397 if (!bss)
3398 return false;
3399
3400 /* Get WFA capability from Beacon or Probe Response frame elements */
3401 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3402 if (!wfa_capa)
3403 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3404 bss, WFA_CAPA_IE_VENDOR_TYPE);
3405
3406 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3407 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3408 /* AP does not enable QM non EHT traffic description policy */
3409 return false;
3410 }
3411
3412 return true;
3413}
3414
3415
Hai Shalomc1a21442022-02-04 13:43:00 -08003416static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3417 struct wpa_bss *bss,
3418 u8 *wpa_ie, size_t wpa_ie_len,
3419 size_t max_wpa_ie_len)
3420{
3421 struct wpabuf *wfa_ie = NULL;
3422 u8 wfa_capa[1];
3423 size_t wfa_ie_len, buf_len;
3424
3425 os_memset(wfa_capa, 0, sizeof(wfa_capa));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003426#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003427 if (wpa_s->enable_dscp_policy_capa)
3428 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003429#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003430
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003431 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3432 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3433
Hai Shalomc1a21442022-02-04 13:43:00 -08003434 if (!wfa_capa[0])
3435 return wpa_ie_len;
3436
3437 /* Wi-Fi Alliance element */
3438 buf_len = 1 + /* Element ID */
3439 1 + /* Length */
3440 3 + /* OUI */
3441 1 + /* OUI Type */
3442 1 + /* Capabilities Length */
3443 sizeof(wfa_capa); /* Capabilities */
3444 wfa_ie = wpabuf_alloc(buf_len);
3445 if (!wfa_ie)
3446 return wpa_ie_len;
3447
3448 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3449 wpabuf_put_u8(wfa_ie, buf_len - 2);
3450 wpabuf_put_be24(wfa_ie, OUI_WFA);
3451 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3452 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3453 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3454
3455 wfa_ie_len = wpabuf_len(wfa_ie);
3456 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3457 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3458 wfa_ie);
3459 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3460 wfa_ie_len);
3461 wpa_ie_len += wfa_ie_len;
3462 }
3463
3464 wpabuf_free(wfa_ie);
3465 return wpa_ie_len;
3466}
3467
3468
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003469static u8 * wpas_populate_assoc_ies(
3470 struct wpa_supplicant *wpa_s,
3471 struct wpa_bss *bss, struct wpa_ssid *ssid,
3472 struct wpa_driver_associate_params *params,
3473 enum wpa_drv_update_connect_params_mask *mask)
3474{
3475 u8 *wpa_ie;
3476 size_t max_wpa_ie_len = 500;
3477 size_t wpa_ie_len;
3478 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003479#ifdef CONFIG_MBO
3480 const u8 *mbo_ie;
3481#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303482#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3483 int pmksa_cached = 0;
3484#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003485#ifdef CONFIG_FILS
3486 const u8 *realm, *username, *rrk;
3487 size_t realm_len, username_len, rrk_len;
3488 u16 next_seq_num;
3489 struct fils_hlp_req *req;
3490
3491 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3492 list) {
3493 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3494 2 + 2 * wpabuf_len(req->pkt) / 255;
3495 }
3496#endif /* CONFIG_FILS */
3497
3498 wpa_ie = os_malloc(max_wpa_ie_len);
3499 if (!wpa_ie) {
3500 wpa_printf(MSG_ERROR,
3501 "Failed to allocate connect IE buffer for %lu bytes",
3502 (unsigned long) max_wpa_ie_len);
3503 return NULL;
3504 }
3505
3506 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
Sunil Ravi7f769292024-07-23 22:21:32 +00003507 wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003508 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3509 int try_opportunistic;
3510 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003511 const u8 *addr = bss->bssid;
3512
Sunil Ravi036cec52023-03-29 11:35:17 -07003513 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3514 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3515 !is_zero_ether_addr(bss->mld_addr))
3516 addr = bss->mld_addr;
3517
3518 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3519 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003520 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003521
3522 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3523 wpa_s->conf->okc :
3524 ssid->proactive_key_caching) &&
3525 (ssid->proto & WPA_PROTO_RSN);
3526#ifdef CONFIG_FILS
3527 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3528 cache_id = wpa_bss_get_fils_cache_id(bss);
3529#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003530 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003531 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003532 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003533 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303534#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3535 pmksa_cached = 1;
3536#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003537 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003538 wpa_ie_len = max_wpa_ie_len;
3539 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003540 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003541 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3542 "key management and encryption suites");
3543 os_free(wpa_ie);
3544 return NULL;
3545 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003546#ifdef CONFIG_HS20
3547 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3548 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3549 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3550 wpa_ie_len = max_wpa_ie_len;
3551 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003552 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003553 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3554 "key management and encryption suites");
3555 os_free(wpa_ie);
3556 return NULL;
3557 }
3558#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003559 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3560 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3561 /*
3562 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3563 * use non-WPA since the scan results did not indicate that the
3564 * AP is using WPA or WPA2.
3565 */
3566 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3567 wpa_ie_len = 0;
3568 wpa_s->wpa_proto = 0;
3569 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3570 wpa_ie_len = max_wpa_ie_len;
3571 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003572 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003573 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3574 "key management and encryption suites (no "
3575 "scan results)");
3576 os_free(wpa_ie);
3577 return NULL;
3578 }
3579#ifdef CONFIG_WPS
3580 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3581 struct wpabuf *wps_ie;
3582 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3583 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3584 wpa_ie_len = wpabuf_len(wps_ie);
3585 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3586 } else
3587 wpa_ie_len = 0;
3588 wpabuf_free(wps_ie);
3589 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3590 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3591 params->wps = WPS_MODE_PRIVACY;
3592 else
3593 params->wps = WPS_MODE_OPEN;
3594 wpa_s->wpa_proto = 0;
3595#endif /* CONFIG_WPS */
3596 } else {
3597 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3598 wpa_ie_len = 0;
3599 wpa_s->wpa_proto = 0;
3600 }
3601
3602#ifdef IEEE8021X_EAPOL
3603 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3604 if (ssid->leap) {
3605 if (ssid->non_leap == 0)
3606 algs = WPA_AUTH_ALG_LEAP;
3607 else
3608 algs |= WPA_AUTH_ALG_LEAP;
3609 }
3610 }
3611
3612#ifdef CONFIG_FILS
3613 /* Clear FILS association */
3614 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3615
3616 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3617 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3618 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3619 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003620 &next_seq_num, &rrk, &rrk_len) == 0 &&
3621 (!wpa_s->last_con_fail_realm ||
3622 wpa_s->last_con_fail_realm_len != realm_len ||
3623 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003624 algs = WPA_AUTH_ALG_FILS;
3625 params->fils_erp_username = username;
3626 params->fils_erp_username_len = username_len;
3627 params->fils_erp_realm = realm;
3628 params->fils_erp_realm_len = realm_len;
3629 params->fils_erp_next_seq_num = next_seq_num;
3630 params->fils_erp_rrk = rrk;
3631 params->fils_erp_rrk_len = rrk_len;
3632
3633 if (mask)
3634 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303635 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3636 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3637 pmksa_cached) {
3638 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003639 }
3640#endif /* CONFIG_FILS */
3641#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003642#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003643 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003644 algs = WPA_AUTH_ALG_SAE;
3645#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003646
3647 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3648 if (ssid->auth_alg) {
3649 algs = ssid->auth_alg;
3650 wpa_dbg(wpa_s, MSG_DEBUG,
3651 "Overriding auth_alg selection: 0x%x", algs);
3652 }
3653
Hai Shalom5f92bc92019-04-18 11:54:11 -07003654#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303655 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003656 wpa_dbg(wpa_s, MSG_DEBUG,
3657 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3658 algs = WPA_AUTH_ALG_OPEN;
3659 }
3660#endif /* CONFIG_SAE */
3661
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003662#ifdef CONFIG_P2P
3663 if (wpa_s->global->p2p) {
3664 u8 *pos;
3665 size_t len;
3666 int res;
3667 pos = wpa_ie + wpa_ie_len;
3668 len = max_wpa_ie_len - wpa_ie_len;
3669 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3670 ssid->p2p_group);
3671 if (res >= 0)
3672 wpa_ie_len += res;
3673 }
3674
3675 wpa_s->cross_connect_disallowed = 0;
3676 if (bss) {
3677 struct wpabuf *p2p;
3678 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3679 if (p2p) {
3680 wpa_s->cross_connect_disallowed =
3681 p2p_get_cross_connect_disallowed(p2p);
3682 wpabuf_free(p2p);
3683 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3684 "connection",
3685 wpa_s->cross_connect_disallowed ?
3686 "disallows" : "allows");
3687 }
3688 }
3689
3690 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3691#endif /* CONFIG_P2P */
3692
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003693#ifndef CONFIG_NO_RRM
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003694 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003695 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003696 wpa_ie + wpa_ie_len,
3697 max_wpa_ie_len -
3698 wpa_ie_len);
3699 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003700#endif /* CONFIG_NO_RRM */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003701
3702 /*
3703 * Workaround: Add Extended Capabilities element only if the AP
3704 * included this element in Beacon/Probe Response frames. Some older
3705 * APs seem to have interoperability issues if this element is
3706 * included, so while the standard may require us to include the
3707 * element in all cases, it is justifiable to skip it to avoid
3708 * interoperability issues.
3709 */
3710 if (ssid->p2p_group)
3711 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3712 else
3713 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3714
3715 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3716 u8 ext_capab[18];
3717 int ext_capab_len;
3718 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003719 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003720 if (ext_capab_len > 0 &&
3721 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3722 u8 *pos = wpa_ie;
3723 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3724 pos += 2 + pos[1];
3725 os_memmove(pos + ext_capab_len, pos,
3726 wpa_ie_len - (pos - wpa_ie));
3727 wpa_ie_len += ext_capab_len;
3728 os_memcpy(pos, ext_capab, ext_capab_len);
3729 }
3730 }
3731
Sunil Ravi7f769292024-07-23 22:21:32 +00003732 if (ssid->max_idle && wpa_ie_len + 5 <= max_wpa_ie_len) {
3733 u8 *pos = wpa_ie;
3734
3735 *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
3736 *pos++ = 3;
3737 WPA_PUT_LE16(pos, ssid->max_idle);
3738 pos += 2;
3739 *pos = 0; /* Idle Options */
3740 wpa_ie_len += 5;
3741 }
3742
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003743#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003744 if (is_hs20_network(wpa_s, ssid, bss)
3745#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3746 && is_hs20_config(wpa_s)
3747#endif /* ANDROID */
3748 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003749 struct wpabuf *hs20;
3750
Roshan Pius3a1667e2018-07-03 15:17:14 -07003751 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003752 if (hs20) {
3753 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3754 size_t len;
3755
Hai Shalom74f70d42019-02-11 14:42:39 -08003756 wpas_hs20_add_indication(hs20, pps_mo_id,
3757 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003758 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003759 len = max_wpa_ie_len - wpa_ie_len;
3760 if (wpabuf_len(hs20) <= len) {
3761 os_memcpy(wpa_ie + wpa_ie_len,
3762 wpabuf_head(hs20), wpabuf_len(hs20));
3763 wpa_ie_len += wpabuf_len(hs20);
3764 }
3765 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003766 }
3767 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003768 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003769#endif /* CONFIG_HS20 */
3770
3771 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3772 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3773 size_t len;
3774
3775 len = max_wpa_ie_len - wpa_ie_len;
3776 if (wpabuf_len(buf) <= len) {
3777 os_memcpy(wpa_ie + wpa_ie_len,
3778 wpabuf_head(buf), wpabuf_len(buf));
3779 wpa_ie_len += wpabuf_len(buf);
3780 }
3781 }
3782
3783#ifdef CONFIG_FST
3784 if (wpa_s->fst_ies) {
3785 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3786
3787 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3788 os_memcpy(wpa_ie + wpa_ie_len,
3789 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3790 wpa_ie_len += fst_ies_len;
3791 }
3792 }
3793#endif /* CONFIG_FST */
3794
3795#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003796 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003797 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003798 int len;
3799
3800 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003801 max_wpa_ie_len - wpa_ie_len,
3802 !!mbo_attr_from_mbo_ie(mbo_ie,
3803 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003804 if (len >= 0)
3805 wpa_ie_len += len;
3806 }
3807#endif /* CONFIG_MBO */
3808
3809#ifdef CONFIG_FILS
3810 if (algs == WPA_AUTH_ALG_FILS) {
3811 size_t len;
3812
3813 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3814 max_wpa_ie_len - wpa_ie_len);
3815 wpa_ie_len += len;
3816 }
3817#endif /* CONFIG_FILS */
3818
3819#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003820#ifdef CONFIG_TESTING_OPTIONS
3821 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3822 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3823 } else
3824#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003825 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003826 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3827 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003828 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003829 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003830
Roshan Pius3a1667e2018-07-03 15:17:14 -07003831 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003832 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003833 } else if (wpa_s->assoc_status_code ==
3834 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003835 if (wpa_s->last_owe_group == 19)
3836 group = 20;
3837 else if (wpa_s->last_owe_group == 20)
3838 group = 21;
3839 else
3840 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003841 } else {
3842 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003843 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003844
Roshan Pius3a1667e2018-07-03 15:17:14 -07003845 wpa_s->last_owe_group = group;
3846 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003847 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3848 if (owe_ie &&
3849 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3850 os_memcpy(wpa_ie + wpa_ie_len,
3851 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3852 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003853 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003854 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003855 }
3856#endif /* CONFIG_OWE */
3857
Hai Shalom021b0b52019-04-10 11:17:58 -07003858#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003859 if (DPP_VERSION > 1 &&
3860 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003861 ssid->dpp_netaccesskey &&
3862 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003863 struct rsn_pmksa_cache_entry *pmksa;
3864
3865 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3866 if (!pmksa || !pmksa->dpp_pfs)
3867 goto pfs_fail;
3868
Hai Shalom021b0b52019-04-10 11:17:58 -07003869 dpp_pfs_free(wpa_s->dpp_pfs);
3870 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3871 ssid->dpp_netaccesskey_len);
3872 if (!wpa_s->dpp_pfs) {
3873 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3874 /* Try to continue without PFS */
3875 goto pfs_fail;
3876 }
3877 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3878 max_wpa_ie_len - wpa_ie_len) {
3879 os_memcpy(wpa_ie + wpa_ie_len,
3880 wpabuf_head(wpa_s->dpp_pfs->ie),
3881 wpabuf_len(wpa_s->dpp_pfs->ie));
3882 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3883 }
3884 }
3885pfs_fail:
3886#endif /* CONFIG_DPP2 */
3887
Roshan Pius3a1667e2018-07-03 15:17:14 -07003888#ifdef CONFIG_IEEE80211R
3889 /*
3890 * Add MDIE under these conditions: the network profile allows FT,
3891 * the AP supports FT, and the mobility domain ID matches.
3892 */
3893 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3894 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3895
3896 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3897 size_t len = 0;
3898 const u8 *md = mdie + 2;
3899 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3900
3901 if (os_memcmp(md, wpa_md,
3902 MOBILITY_DOMAIN_ID_LEN) == 0) {
3903 /* Add mobility domain IE */
3904 len = wpa_ft_add_mdie(
3905 wpa_s->wpa, wpa_ie + wpa_ie_len,
3906 max_wpa_ie_len - wpa_ie_len, mdie);
3907 wpa_ie_len += len;
3908 }
3909#ifdef CONFIG_SME
3910 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003911 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003912 wpa_dbg(wpa_s, MSG_DEBUG,
3913 "SME: Trying to use FT over-the-air");
3914 algs |= WPA_AUTH_ALG_FT;
3915 }
3916#endif /* CONFIG_SME */
3917 }
3918 }
3919#endif /* CONFIG_IEEE80211R */
3920
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003921#ifdef CONFIG_TESTING_OPTIONS
3922 if (wpa_s->rsnxe_override_assoc &&
3923 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3924 max_wpa_ie_len - wpa_ie_len) {
3925 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3926 os_memcpy(wpa_ie + wpa_ie_len,
3927 wpabuf_head(wpa_s->rsnxe_override_assoc),
3928 wpabuf_len(wpa_s->rsnxe_override_assoc));
3929 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3930 } else
3931#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003932 if (wpa_s->rsnxe_len > 0 &&
3933 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3934 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3935 wpa_ie_len += wpa_s->rsnxe_len;
3936 }
3937
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003938#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08003939#ifdef CONFIG_TESTING_OPTIONS
3940 if (wpa_s->disable_mscs_support)
3941 goto mscs_end;
3942#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003943 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3944 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003945 struct wpabuf *mscs_ie;
3946 size_t mscs_ie_len, buf_len;
3947
Hai Shalom899fcc72020-10-19 14:38:18 -07003948 buf_len = 3 + /* MSCS descriptor IE header */
3949 1 + /* Request type */
3950 2 + /* User priority control */
3951 4 + /* Stream timeout */
3952 3 + /* TCLAS Mask IE header */
3953 wpa_s->robust_av.frame_classifier_len;
3954 mscs_ie = wpabuf_alloc(buf_len);
3955 if (!mscs_ie) {
3956 wpa_printf(MSG_INFO,
3957 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003958 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003959 }
3960
3961 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3962 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3963 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3964 mscs_ie_len = wpabuf_len(mscs_ie);
3965 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3966 mscs_ie_len);
3967 wpa_ie_len += mscs_ie_len;
3968 }
3969
3970 wpabuf_free(mscs_ie);
3971 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003972mscs_end:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003973#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalomc1a21442022-02-04 13:43:00 -08003974
3975 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3976 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003977
Hai Shalom74f70d42019-02-11 14:42:39 -08003978 if (ssid->multi_ap_backhaul_sta) {
3979 size_t multi_ap_ie_len;
Sunil Ravi99c035e2024-07-12 01:42:03 +00003980 struct multi_ap_params multi_ap = { 0 };
3981
3982 multi_ap.capability = MULTI_AP_BACKHAUL_STA;
3983 multi_ap.profile = ssid->multi_ap_profile;
Hai Shalom74f70d42019-02-11 14:42:39 -08003984
3985 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3986 max_wpa_ie_len - wpa_ie_len,
Sunil Ravi99c035e2024-07-12 01:42:03 +00003987 &multi_ap);
Hai Shalom74f70d42019-02-11 14:42:39 -08003988 if (multi_ap_ie_len == 0) {
3989 wpa_printf(MSG_ERROR,
3990 "Multi-AP: Failed to build Multi-AP IE");
3991 os_free(wpa_ie);
3992 return NULL;
3993 }
3994 wpa_ie_len += multi_ap_ie_len;
3995 }
3996
Sunil Ravic0f5d412024-09-11 22:12:49 +00003997 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
3998 wpas_rsn_overriding(wpa_s));
3999 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
4000 RSN_OVERRIDE_NOT_USED);
4001 if (wpas_rsn_overriding(wpa_s) &&
Sunil Ravi7f769292024-07-23 22:21:32 +00004002 wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
Sunil Ravic0f5d412024-09-11 22:12:49 +00004003 wpa_ie_len + 2 + 4 + 1 <= max_wpa_ie_len) {
4004 u8 *pos = wpa_ie + wpa_ie_len, *start = pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004005 const u8 *ie;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004006 enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
Sunil Ravi7f769292024-07-23 22:21:32 +00004007
Sunil Ravic0f5d412024-09-11 22:12:49 +00004008 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
4009 RSN_OVERRIDE_RSNE);
Sunil Ravi7f769292024-07-23 22:21:32 +00004010 ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004011 if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
4012 u32 type;
4013
Sunil Ravi7f769292024-07-23 22:21:32 +00004014 type = WPA_GET_BE32(&ie[2]);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004015 if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
4016 variant = RSN_SELECTION_RSNE_OVERRIDE;
4017 wpa_sm_set_param(wpa_s->wpa,
4018 WPA_PARAM_RSN_OVERRIDE,
4019 RSN_OVERRIDE_RSNE_OVERRIDE);
4020 } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
4021 variant = RSN_SELECTION_RSNE_OVERRIDE_2;
4022 wpa_sm_set_param(wpa_s->wpa,
4023 WPA_PARAM_RSN_OVERRIDE,
4024 RSN_OVERRIDE_RSNE_OVERRIDE_2);
4025 }
Sunil Ravi7f769292024-07-23 22:21:32 +00004026 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00004027
4028 /* Indicate which RSNE variant was used */
4029 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4030 *pos++ = 4 + 1;
4031 WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
4032 pos += 4;
4033 *pos++ = variant;
4034 wpa_hexdump(MSG_MSGDUMP, "RSN Selection", start, pos - start);
4035 wpa_ie_len += pos - start;
Sunil Ravi7f769292024-07-23 22:21:32 +00004036 }
4037
Sunil Ravic0f5d412024-09-11 22:12:49 +00004038 params->rsn_overriding = wpas_rsn_overriding(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004039 params->wpa_ie = wpa_ie;
4040 params->wpa_ie_len = wpa_ie_len;
4041 params->auth_alg = algs;
4042 if (mask)
4043 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
4044
4045 return wpa_ie;
4046}
4047
4048
Hai Shalomc3565922019-10-28 11:58:20 -07004049#ifdef CONFIG_OWE
4050static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
4051{
4052 struct wpa_driver_associate_params params;
4053 u8 *wpa_ie;
4054
4055 os_memset(&params, 0, sizeof(params));
4056 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4057 wpa_s->current_ssid, &params, NULL);
4058 if (!wpa_ie)
4059 return;
4060
4061 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4062 os_free(wpa_ie);
4063}
4064#endif /* CONFIG_OWE */
4065
4066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004067#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
4068static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
4069{
4070 struct wpa_driver_associate_params params;
4071 enum wpa_drv_update_connect_params_mask mask = 0;
4072 u8 *wpa_ie;
4073
4074 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
4075 return; /* nothing to do */
4076
4077 os_memset(&params, 0, sizeof(params));
4078 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4079 wpa_s->current_ssid, &params, &mask);
4080 if (!wpa_ie)
4081 return;
4082
Hai Shalomc1a21442022-02-04 13:43:00 -08004083 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
4084 wpa_s->auth_alg = params.auth_alg;
4085 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004086 }
4087
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004088 os_free(wpa_ie);
4089}
4090#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
4091
4092
Hai Shalomc3565922019-10-28 11:58:20 -07004093static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
4094{
4095 if (!edmg_ie || edmg_ie[1] < 6)
4096 return 0;
4097 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
4098}
4099
4100
4101static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
4102{
4103 if (!edmg_ie || edmg_ie[1] < 6)
4104 return 0;
4105 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
4106}
4107
4108
4109/* Returns the intersection of two EDMG configurations.
4110 * Note: The current implementation is limited to CB2 only (CB1 included),
4111 * i.e., the implementation supports up to 2 contiguous channels.
4112 * For supporting non-contiguous (aggregated) channels and for supporting
4113 * CB3 and above, this function will need to be extended.
4114 */
4115static struct ieee80211_edmg_config
4116get_edmg_intersection(struct ieee80211_edmg_config a,
4117 struct ieee80211_edmg_config b,
4118 u8 primary_channel)
4119{
4120 struct ieee80211_edmg_config result;
4121 int i, contiguous = 0;
4122 int max_contiguous = 0;
4123
4124 result.channels = b.channels & a.channels;
4125 if (!result.channels) {
4126 wpa_printf(MSG_DEBUG,
4127 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
4128 a.channels, b.channels);
4129 goto fail;
4130 }
4131
4132 if (!(result.channels & BIT(primary_channel - 1))) {
4133 wpa_printf(MSG_DEBUG,
4134 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
4135 primary_channel, result.channels);
4136 goto fail;
4137 }
4138
4139 /* Find max contiguous channels */
4140 for (i = 0; i < 6; i++) {
4141 if (result.channels & BIT(i))
4142 contiguous++;
4143 else
4144 contiguous = 0;
4145
4146 if (contiguous > max_contiguous)
4147 max_contiguous = contiguous;
4148 }
4149
4150 /* Assuming AP and STA supports ONLY contiguous channels,
4151 * bw configuration can have value between 4-7.
4152 */
4153 if ((b.bw_config < a.bw_config))
4154 result.bw_config = b.bw_config;
4155 else
4156 result.bw_config = a.bw_config;
4157
4158 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
4159 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
4160 wpa_printf(MSG_DEBUG,
4161 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
4162 max_contiguous);
4163 goto fail;
4164 }
4165
4166 return result;
4167
4168fail:
4169 result.channels = 0;
4170 result.bw_config = 0;
4171 return result;
4172}
4173
4174
4175static struct ieee80211_edmg_config
4176get_supported_edmg(struct wpa_supplicant *wpa_s,
4177 struct hostapd_freq_params *freq,
4178 struct ieee80211_edmg_config request_edmg)
4179{
4180 enum hostapd_hw_mode hw_mode;
4181 struct hostapd_hw_modes *mode = NULL;
4182 u8 primary_channel;
4183
4184 if (!wpa_s->hw.modes)
4185 goto fail;
4186
4187 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
4188 if (hw_mode == NUM_HOSTAPD_MODES)
4189 goto fail;
4190
Hai Shalom60840252021-02-19 19:02:11 -08004191 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004192 if (!mode)
4193 goto fail;
4194
4195 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
4196
4197fail:
4198 request_edmg.channels = 0;
4199 request_edmg.bw_config = 0;
4200 return request_edmg;
4201}
4202
4203
Hai Shalom021b0b52019-04-10 11:17:58 -07004204#ifdef CONFIG_MBO
4205void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
4206{
4207 struct wpa_driver_associate_params params;
4208 u8 *wpa_ie;
4209
4210 /*
4211 * Update MBO connect params only in case of change of MBO attributes
4212 * when connected, if the AP support MBO.
4213 */
4214
4215 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
4216 !wpa_s->current_bss ||
4217 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
4218 return;
4219
4220 os_memset(&params, 0, sizeof(params));
4221 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
4222 wpa_s->current_ssid, &params, NULL);
4223 if (!wpa_ie)
4224 return;
4225
4226 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
4227 os_free(wpa_ie);
4228}
4229#endif /* CONFIG_MBO */
4230
4231
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004232static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
4233{
4234 struct wpa_connect_work *cwork = work->ctx;
4235 struct wpa_bss *bss = cwork->bss;
4236 struct wpa_ssid *ssid = cwork->ssid;
4237 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004238 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004239 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004240 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004241 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004242 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004243 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004244#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004245 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004246#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004247 int assoc_failed = 0;
4248 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004249 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004250#ifdef CONFIG_HT_OVERRIDES
4251 struct ieee80211_ht_capabilities htcaps;
4252 struct ieee80211_ht_capabilities htcaps_mask;
4253#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004254#ifdef CONFIG_VHT_OVERRIDES
4255 struct ieee80211_vht_capabilities vhtcaps;
4256 struct ieee80211_vht_capabilities vhtcaps_mask;
4257#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004258
Hai Shalomc1a21442022-02-04 13:43:00 -08004259 wpa_s->roam_in_progress = false;
4260#ifdef CONFIG_WNM
4261 wpa_s->bss_trans_mgmt_in_progress = false;
4262#endif /* CONFIG_WNM */
Sunil Ravi7f769292024-07-23 22:21:32 +00004263 wpa_s->no_suitable_network = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08004264
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004265 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004266 if (work->started) {
4267 wpa_s->connect_work = NULL;
4268
4269 /* cancel possible auth. timeout */
4270 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4271 NULL);
4272 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004273 wpas_connect_work_free(cwork);
4274 return;
4275 }
4276
4277 wpa_s->connect_work = work;
4278
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004279 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4280 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004281 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4282 wpas_connect_work_done(wpa_s);
4283 return;
4284 }
4285
Sunil Ravi640215c2023-06-28 23:08:09 +00004286 /*
4287 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4288 * (for MLO connection) as the previous BSSID for reassociation requests
4289 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4290 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4291 * will be zero.
4292 */
4293 os_memcpy(prev_bssid,
4294 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4295 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 os_memset(&params, 0, sizeof(params));
4297 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004298 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004299
4300 /* Starting new association, so clear the possibly used WPA IE from the
4301 * previous association. */
4302 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Matthew Wang9ed1c792024-12-02 14:05:18 +00004303#ifndef CONFIG_NO_WPA
Hai Shalom60840252021-02-19 19:02:11 -08004304 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Matthew Wang9ed1c792024-12-02 14:05:18 +00004305#endif /* CONFIG_NO_WPA */
Hai Shalom60840252021-02-19 19:02:11 -08004306 wpa_s->rsnxe_len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004307#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom60840252021-02-19 19:02:11 -08004308 wpa_s->mscs_setup_done = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004309#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08004310
4311 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4312 if (!wpa_ie) {
4313 wpas_connect_work_done(wpa_s);
4314 return;
4315 }
4316
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004317 if (bss &&
4318 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319#ifdef CONFIG_IEEE80211R
4320 const u8 *ie, *md = NULL;
4321#endif /* CONFIG_IEEE80211R */
4322 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4323 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4324 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4325 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4326 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4327 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4328 if (bssid_changed)
4329 wpas_notify_bssid_changed(wpa_s);
4330#ifdef CONFIG_IEEE80211R
4331 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4332 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4333 md = ie + 2;
4334 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4335 if (md) {
4336 /* Prepare for the next transition */
4337 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4338 }
4339#endif /* CONFIG_IEEE80211R */
4340#ifdef CONFIG_WPS
4341 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4342 wpa_s->conf->ap_scan == 2 &&
4343 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4344 /* Use ap_scan==1 style network selection to find the network
4345 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004346 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004347 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 wpa_s->reassociate = 1;
4349 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004350 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004351 return;
4352#endif /* CONFIG_WPS */
4353 } else {
4354 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4355 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004356 if (bss)
4357 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4358 else
4359 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004361 if (!wpa_s->pno)
4362 wpa_supplicant_cancel_sched_scan(wpa_s);
4363
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004364 wpa_supplicant_cancel_scan(wpa_s);
4365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004366 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4367 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004368 cipher_pairwise = wpa_s->pairwise_cipher;
4369 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004370 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004371 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4372 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4373 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4374 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004375#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004376 if (wpa_set_wep_keys(wpa_s, ssid)) {
4377 use_crypt = 1;
4378 wep_keys_set = 1;
4379 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004380#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004381 }
4382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4383 use_crypt = 0;
4384
4385#ifdef IEEE8021X_EAPOL
4386 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4387 if ((ssid->eapol_flags &
4388 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4389 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4390 !wep_keys_set) {
4391 use_crypt = 0;
4392 } else {
4393 /* Assume that dynamic WEP-104 keys will be used and
4394 * set cipher suites in order for drivers to expect
4395 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004396 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 }
4398 }
4399#endif /* IEEE8021X_EAPOL */
4400
4401 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4402 /* Set the key before (and later after) association */
4403 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4404 }
4405
Sunil8cd6f4d2022-06-28 18:40:46 +00004406 /* Set current_ssid before changing state to ASSOCIATING, so that the
4407 * selected SSID is available to wpas_notify_state_changed(). */
4408 old_ssid = wpa_s->current_ssid;
4409 wpa_s->current_ssid = ssid;
4410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004411 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4412 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004413 params.ssid = bss->ssid;
4414 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004415 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4416 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004417 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4418 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004419 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004420 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004421 ssid->bssid_set,
4422 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004423 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004424 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004425 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004426 params.bssid_hint = bss->bssid;
4427 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004428 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004429 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004430 if (ssid->bssid_hint_set)
4431 params.bssid_hint = ssid->bssid_hint;
4432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004433 params.ssid = ssid->ssid;
4434 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004435 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004437
4438 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4439 wpa_s->conf->ap_scan == 2) {
4440 params.bssid = ssid->bssid;
4441 params.fixed_bssid = 1;
4442 }
4443
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004444 /* Initial frequency for IBSS/mesh */
4445 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004446 ssid->frequency > 0 && params.freq.freq == 0)
4447 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004448
4449 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004450 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004451 if (ssid->beacon_int)
4452 params.beacon_int = ssid->beacon_int;
4453 else
4454 params.beacon_int = wpa_s->conf->beacon_int;
4455 }
4456
Hai Shalomc3565922019-10-28 11:58:20 -07004457 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004458 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4459 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004460 else
4461 edmg_ie_oper = NULL;
4462
4463 if (edmg_ie_oper) {
4464 params.freq.edmg.channels =
4465 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4466 params.freq.edmg.bw_config =
4467 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4468 wpa_printf(MSG_DEBUG,
4469 "AP supports EDMG channels 0x%x, bw_config %d",
4470 params.freq.edmg.channels,
4471 params.freq.edmg.bw_config);
4472
4473 /* User may ask for specific EDMG channel for EDMG connection
4474 * (must be supported by AP)
4475 */
4476 if (ssid->edmg_channel) {
4477 struct ieee80211_edmg_config configured_edmg;
4478 enum hostapd_hw_mode hw_mode;
4479 u8 primary_channel;
4480
4481 hw_mode = ieee80211_freq_to_chan(bss->freq,
4482 &primary_channel);
4483 if (hw_mode == NUM_HOSTAPD_MODES)
4484 goto edmg_fail;
4485
4486 hostapd_encode_edmg_chan(ssid->enable_edmg,
4487 ssid->edmg_channel,
4488 primary_channel,
4489 &configured_edmg);
4490
4491 if (ieee802_edmg_is_allowed(params.freq.edmg,
4492 configured_edmg)) {
4493 params.freq.edmg = configured_edmg;
4494 wpa_printf(MSG_DEBUG,
4495 "Use EDMG channel %d for connection",
4496 ssid->edmg_channel);
4497 } else {
4498 edmg_fail:
4499 params.freq.edmg.channels = 0;
4500 params.freq.edmg.bw_config = 0;
4501 wpa_printf(MSG_WARNING,
4502 "EDMG channel %d not supported by AP, fallback to DMG",
4503 ssid->edmg_channel);
4504 }
4505 }
4506
4507 if (params.freq.edmg.channels) {
4508 wpa_printf(MSG_DEBUG,
4509 "EDMG before: channels 0x%x, bw_config %d",
4510 params.freq.edmg.channels,
4511 params.freq.edmg.bw_config);
4512 params.freq.edmg = get_supported_edmg(wpa_s,
4513 &params.freq,
4514 params.freq.edmg);
4515 wpa_printf(MSG_DEBUG,
4516 "EDMG after: channels 0x%x, bw_config %d",
4517 params.freq.edmg.channels,
4518 params.freq.edmg.bw_config);
4519 }
4520 }
4521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 params.pairwise_suite = cipher_pairwise;
4523 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004524 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004525 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004526 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004527 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004528 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004530 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004531#ifdef CONFIG_WEP
4532 {
4533 int i;
4534
4535 for (i = 0; i < NUM_WEP_KEYS; i++) {
4536 if (ssid->wep_key_len[i])
4537 params.wep_key[i] = ssid->wep_key[i];
4538 params.wep_key_len[i] = ssid->wep_key_len[i];
4539 }
4540 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004541 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004542#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004543
Hai Shalom74f70d42019-02-11 14:42:39 -08004544 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004545#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4546 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004547 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4548 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004549#elif (defined(CONFIG_DRIVER_NL80211_BRCM) && defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4550 defined(CONFIG_DRIVER_NL80211_SYNA)
4551 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4552 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4553 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4554 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304555#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004556 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4557 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4558 (params.allowed_key_mgmts &
4559 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004560#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4561 * CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004562 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004563 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4564 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004565 }
4566
Hai Shalom74f70d42019-02-11 14:42:39 -08004567 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4568 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4569 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4570 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004571 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4572 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004573 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004574
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004575 if (wpa_s->conf->key_mgmt_offload) {
4576 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4577 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004578 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004579 params.key_mgmt_suite ==
4580 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4581 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004582 params.req_key_mgmt_offload =
4583 ssid->proactive_key_caching < 0 ?
4584 wpa_s->conf->okc : ssid->proactive_key_caching;
4585 else
4586 params.req_key_mgmt_offload = 1;
4587
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004588#if (defined(CONFIG_DRIVER_NL80211_BRCM) && !defined(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM)) || \
4589 defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004590 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004591 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4592 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004593#else
4594 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4595 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Isaac Chiou6ce580d2024-04-24 17:07:24 +08004596#endif /* (CONFIG_DRIVER_NL80211_BRCM && !WIFI_BRCM_OPEN_SOURCE_MULTI_AKM) ||
4597 * CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004598 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4599 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004600 }
4601
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004602 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4603 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4604 params.auth_alg = WPA_AUTH_ALG_SAE;
4605 if (ssid->sae_password) {
4606 params.sae_password = ssid->sae_password;
4607 params.sae_password_id = ssid->sae_password_id;
4608 } else if (ssid->passphrase) {
4609 params.passphrase = ssid->passphrase;
4610 }
4611 }
4612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 params.drop_unencrypted = use_crypt;
4614
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004615 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004616 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004617 const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004618 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004619 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4620 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004621 ie.capabilities &
4622 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4623 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4624 "MFP: require MFP");
4625 params.mgmt_frame_protection =
4626 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004627#ifdef CONFIG_OWE
4628 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4629 !ssid->owe_only) {
4630 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4631#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632 }
4633 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004635 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004636
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004637 if (wpa_s->p2pdev->set_sta_uapsd)
4638 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004639 else
4640 params.uapsd = -1;
4641
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004642#ifdef CONFIG_HT_OVERRIDES
4643 os_memset(&htcaps, 0, sizeof(htcaps));
4644 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4645 params.htcaps = (u8 *) &htcaps;
4646 params.htcaps_mask = (u8 *) &htcaps_mask;
4647 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4648#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004649#ifdef CONFIG_VHT_OVERRIDES
4650 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4651 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4652 params.vhtcaps = &vhtcaps;
4653 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004654 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004655#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004656#ifdef CONFIG_HE_OVERRIDES
4657 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4658#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004659 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004660
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004661#ifdef CONFIG_P2P
4662 /*
4663 * If multi-channel concurrency is not supported, check for any
4664 * frequency conflict. In case of any frequency conflict, remove the
4665 * least prioritized connection.
4666 */
4667 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004668 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004669 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004670 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004671 wpa_printf(MSG_DEBUG,
4672 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004673 freq, params.freq.freq);
4674 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004675 wpa_s, params.freq.freq, ssid) < 0) {
4676 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004677 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004678 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004679 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004680 }
4681 }
4682#endif /* CONFIG_P2P */
4683
Dmitry Shmidte4663042016-04-04 10:07:49 -07004684 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004685 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004686 params.prev_bssid = prev_bssid;
4687
Hai Shalom60840252021-02-19 19:02:11 -08004688#ifdef CONFIG_SAE
4689 params.sae_pwe = wpa_s->conf->sae_pwe;
4690#endif /* CONFIG_SAE */
4691
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004692 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004693 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004694 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004695 if (ret < 0) {
4696 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4697 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004698 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004699 /*
4700 * The driver is known to mean what is saying, so we
4701 * can stop right here; the association will not
4702 * succeed.
4703 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004704 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
4705 NULL);
Roger Wang4c09cc92020-11-05 18:57:12 +08004706 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004707 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004708 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4710 return;
4711 }
4712 /* try to continue anyway; new association will be tried again
4713 * after timeout */
4714 assoc_failed = 1;
4715 }
4716
4717 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4718 /* Set the key after the association just in case association
4719 * cleared the previously configured key. */
4720 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4721 /* No need to timeout authentication since there is no key
4722 * management. */
4723 wpa_supplicant_cancel_auth_timeout(wpa_s);
4724 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4725#ifdef CONFIG_IBSS_RSN
4726 } else if (ssid->mode == WPAS_MODE_IBSS &&
4727 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4728 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4729 /*
4730 * RSN IBSS authentication is per-STA and we can disable the
4731 * per-BSSID authentication.
4732 */
4733 wpa_supplicant_cancel_auth_timeout(wpa_s);
4734#endif /* CONFIG_IBSS_RSN */
4735 } else {
4736 /* Timeout for IEEE 802.11 authentication and association */
4737 int timeout = 60;
4738
4739 if (assoc_failed) {
4740 /* give IBSS a bit more time */
4741 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4742 } else if (wpa_s->conf->ap_scan == 1) {
4743 /* give IBSS a bit more time */
4744 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4745 }
4746 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4747 }
4748
Hai Shalomfdcde762020-04-02 11:19:20 -07004749#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004750 if (wep_keys_set &&
4751 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004752 /* Set static WEP keys again */
4753 wpa_set_wep_keys(wpa_s, ssid);
4754 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004755#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004756
Sunil8cd6f4d2022-06-28 18:40:46 +00004757 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758 /*
4759 * Do not allow EAP session resumption between different
4760 * network configurations.
4761 */
4762 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4763 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004764
mtk30479d7f89782024-01-24 11:51:43 +08004765 if (!wpas_driver_bss_selection(wpa_s) ||
4766#ifdef CONFIG_P2P
4767 wpa_s->p2p_in_invitation ||
4768#endif /* CONFIG_P2P */
4769 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004770 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004771#ifdef CONFIG_HS20
4772 hs20_configure_frame_filters(wpa_s);
4773#endif /* CONFIG_HS20 */
4774 }
4775
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004776 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
Matthew Wang9ed1c792024-12-02 14:05:18 +00004777#ifndef CONFIG_NO_WPA
Sunil Ravi7f769292024-07-23 22:21:32 +00004778 if (bss)
4779 wpa_sm_set_ssid(wpa_s->wpa, bss->ssid, bss->ssid_len);
Matthew Wang9ed1c792024-12-02 14:05:18 +00004780#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004781 wpa_supplicant_initiate_eapol(wpa_s);
4782 if (old_ssid != wpa_s->current_ssid)
4783 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004784 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4785 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004786}
4787
4788
4789static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4790 const u8 *addr)
4791{
4792 struct wpa_ssid *old_ssid;
4793
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004794 wpa_s->ml_connect_probe_ssid = NULL;
4795 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004796 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004798 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004799 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004800 wpa_sm_set_config(wpa_s->wpa, NULL);
4801 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4802 if (old_ssid != wpa_s->current_ssid)
4803 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004804
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004805#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08004806 wpas_scs_deinit(wpa_s);
4807 wpas_dscp_deinit(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004808#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4810}
4811
4812
4813/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004814 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4815 * @wpa_s: Pointer to wpa_supplicant data
4816 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4817 *
4818 * This function is used to request %wpa_supplicant to deauthenticate from the
4819 * current AP.
4820 */
4821void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004822 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004823{
4824 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004825 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004826 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004827
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004828 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Sunil Ravi7f769292024-07-23 22:21:32 +00004829 " pending_bssid=" MACSTR
4830 " reason=%d (%s) state=%s valid_links=0x%x ap_mld_addr=" MACSTR,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004831 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004832 reason_code, reason2str(reason_code),
Sunil Ravi7f769292024-07-23 22:21:32 +00004833 wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_s->valid_links,
4834 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004835
Sunil Ravi7f769292024-07-23 22:21:32 +00004836 if (wpa_s->valid_links && !is_zero_ether_addr(wpa_s->ap_mld_addr))
4837 addr = wpa_s->ap_mld_addr;
4838 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4839 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4840 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004841 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004842 else if (!is_zero_ether_addr(wpa_s->bssid))
4843 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004844 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4845 /*
4846 * When using driver-based BSS selection, we may not know the
4847 * BSSID with which we are currently trying to associate. We
4848 * need to notify the driver of this disconnection even in such
4849 * a case, so use the all zeros address here.
4850 */
4851 addr = wpa_s->bssid;
4852 zero_addr = 1;
4853 }
4854
Hai Shalom74f70d42019-02-11 14:42:39 -08004855 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4856 wpa_s->enabled_4addr_mode = 0;
4857
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004858#ifdef CONFIG_TDLS
4859 wpa_tdls_teardown_peers(wpa_s->wpa);
4860#endif /* CONFIG_TDLS */
4861
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004862#ifdef CONFIG_MESH
4863 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004864 struct mesh_conf *mconf;
4865
4866 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004867 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4868 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004869 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4870 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004871 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004872 }
4873#endif /* CONFIG_MESH */
4874
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004875 if (addr) {
4876 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004877 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004878 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004879 event.deauth_info.locally_generated = 1;
4880 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004881 if (zero_addr)
4882 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 }
4884
4885 wpa_supplicant_clear_connection(wpa_s, addr);
4886}
4887
Hai Shalomfdcde762020-04-02 11:19:20 -07004888
4889void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4890{
4891 wpa_s->own_reconnect_req = 1;
4892 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4893
4894}
4895
4896
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004897static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4898 struct wpa_ssid *ssid)
4899{
4900 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4901 return;
4902
4903 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004904 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004905 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4906 wpas_notify_network_enabled_changed(wpa_s, ssid);
4907
4908 /*
4909 * Try to reassociate since there is no current configuration and a new
4910 * network was made available.
4911 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004912 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004913 wpa_s->reassociate = 1;
4914}
4915
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004916
Roshan Pius950bec92016-07-19 09:49:24 -07004917/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004918 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004919 * @wpa_s: wpa_supplicant structure for a network interface
4920 * Returns: The new network configuration or %NULL if operation failed
4921 *
4922 * This function performs the following operations:
4923 * 1. Adds a new network.
4924 * 2. Send network addition notification.
4925 * 3. Marks the network disabled.
4926 * 4. Set network default parameters.
4927 */
4928struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4929{
4930 struct wpa_ssid *ssid;
4931
4932 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004933 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004934 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004935 wpas_notify_network_added(wpa_s, ssid);
4936 ssid->disabled = 1;
4937 wpa_config_set_network_defaults(ssid);
4938
4939 return ssid;
4940}
4941
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004942
Roshan Pius950bec92016-07-19 09:49:24 -07004943/**
4944 * wpa_supplicant_remove_network - Remove a configured network based on id
4945 * @wpa_s: wpa_supplicant structure for a network interface
4946 * @id: Unique network id to search for
4947 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4948 * could not be removed
4949 *
4950 * This function performs the following operations:
4951 * 1. Removes the network.
4952 * 2. Send network removal notification.
4953 * 3. Update internal state machines.
4954 * 4. Stop any running sched scans.
4955 */
4956int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4957{
Sunil Ravia04bd252022-05-02 22:54:18 -07004958 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004959 int was_disabled;
4960
4961 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004962 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004963 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004964 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004965
Sunil Ravia04bd252022-05-02 22:54:18 -07004966 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004967#ifdef CONFIG_SME
4968 wpa_s->sme.prev_bssid_set = 0;
4969#endif /* CONFIG_SME */
4970 /*
4971 * Invalidate the EAP session cache if the current or
4972 * previously used network is removed.
4973 */
4974 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4975 }
4976
Sunil Ravia04bd252022-05-02 22:54:18 -07004977 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004978 wpa_sm_set_config(wpa_s->wpa, NULL);
4979 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4980
4981 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4982 wpa_s->own_disconnect_req = 1;
4983 wpa_supplicant_deauthenticate(wpa_s,
4984 WLAN_REASON_DEAUTH_LEAVING);
4985 }
4986
4987 was_disabled = ssid->disabled;
4988
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004989 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004990 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004991
4992 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004993 wpa_printf(MSG_DEBUG,
4994 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004995 wpa_supplicant_cancel_sched_scan(wpa_s);
4996 wpa_supplicant_req_scan(wpa_s, 0, 0);
4997 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004998
Roshan Pius950bec92016-07-19 09:49:24 -07004999 return 0;
5000}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005001
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005003/**
Hai Shalom899fcc72020-10-19 14:38:18 -07005004 * wpa_supplicant_remove_all_networks - Remove all configured networks
5005 * @wpa_s: wpa_supplicant structure for a network interface
5006 * Returns: 0 on success (errors are currently ignored)
5007 *
5008 * This function performs the following operations:
5009 * 1. Remove all networks.
5010 * 2. Send network removal notifications.
5011 * 3. Update internal state machines.
5012 * 4. Stop any running sched scans.
5013 */
5014int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
5015{
5016 struct wpa_ssid *ssid;
5017
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05305018 if (wpa_s->drv_flags2 &
5019 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
5020 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
5021 wpa_drv_flush_pmkid(wpa_s);
5022
Hai Shalom899fcc72020-10-19 14:38:18 -07005023 if (wpa_s->sched_scanning)
5024 wpa_supplicant_cancel_sched_scan(wpa_s);
5025
5026 eapol_sm_invalidate_cached_session(wpa_s->eapol);
5027 if (wpa_s->current_ssid) {
5028#ifdef CONFIG_SME
5029 wpa_s->sme.prev_bssid_set = 0;
5030#endif /* CONFIG_SME */
5031 wpa_sm_set_config(wpa_s->wpa, NULL);
5032 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
5033 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5034 wpa_s->own_disconnect_req = 1;
5035 wpa_supplicant_deauthenticate(
5036 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5037 }
5038 ssid = wpa_s->conf->ssid;
5039 while (ssid) {
5040 struct wpa_ssid *remove_ssid = ssid;
5041 int id;
5042
5043 id = ssid->id;
5044 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07005045 wpas_notify_network_removed(wpa_s, remove_ssid);
5046 wpa_config_remove_network(wpa_s->conf, id);
5047 }
5048 return 0;
5049}
5050
5051
5052/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005053 * wpa_supplicant_enable_network - Mark a configured network as enabled
5054 * @wpa_s: wpa_supplicant structure for a network interface
5055 * @ssid: wpa_ssid structure for a configured network or %NULL
5056 *
5057 * Enables the specified network or all networks if no network specified.
5058 */
5059void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
5060 struct wpa_ssid *ssid)
5061{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005062 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005063 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5064 wpa_supplicant_enable_one_network(wpa_s, ssid);
5065 } else
5066 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005067
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005068 if (wpa_s->reassociate && !wpa_s->disconnected &&
5069 (!wpa_s->current_ssid ||
5070 wpa_s->wpa_state == WPA_DISCONNECTED ||
5071 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005072 if (wpa_s->sched_scanning) {
5073 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
5074 "new network to scan filters");
5075 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005076 }
5077
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005078 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
5079 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07005080 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005081 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005082 }
5083}
5084
5085
5086/**
5087 * wpa_supplicant_disable_network - Mark a configured network as disabled
5088 * @wpa_s: wpa_supplicant structure for a network interface
5089 * @ssid: wpa_ssid structure for a configured network or %NULL
5090 *
5091 * Disables the specified network or all networks if no network specified.
5092 */
5093void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
5094 struct wpa_ssid *ssid)
5095{
5096 struct wpa_ssid *other_ssid;
5097 int was_disabled;
5098
5099 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005100 if (wpa_s->sched_scanning)
5101 wpa_supplicant_cancel_sched_scan(wpa_s);
5102
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005103 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5104 other_ssid = other_ssid->next) {
5105 was_disabled = other_ssid->disabled;
5106 if (was_disabled == 2)
5107 continue; /* do not change persistent P2P group
5108 * data */
5109
5110 other_ssid->disabled = 1;
5111
5112 if (was_disabled != other_ssid->disabled)
5113 wpas_notify_network_enabled_changed(
5114 wpa_s, other_ssid);
5115 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005116 if (wpa_s->current_ssid) {
5117 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5118 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005119 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005120 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005121 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005123 if (ssid == wpa_s->current_ssid) {
5124 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5125 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005126 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005127 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005129
5130 was_disabled = ssid->disabled;
5131
5132 ssid->disabled = 1;
5133
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005134 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005135 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005136 if (wpa_s->sched_scanning) {
5137 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
5138 "to remove network from filters");
5139 wpa_supplicant_cancel_sched_scan(wpa_s);
5140 wpa_supplicant_req_scan(wpa_s, 0, 0);
5141 }
5142 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005143 }
5144}
5145
5146
5147/**
5148 * wpa_supplicant_select_network - Attempt association with a network
5149 * @wpa_s: wpa_supplicant structure for a network interface
5150 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
5151 */
5152void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
5153 struct wpa_ssid *ssid)
5154{
5155
5156 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005157 int disconnected = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00005158 bool request_new_scan = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005159
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005160 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005161 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5162 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005163 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005164 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005165 disconnected = 1;
5166 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005167
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005168 if (ssid)
5169 wpas_clear_temp_disabled(wpa_s, ssid, 1);
5170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005171 /*
5172 * Mark all other networks disabled or mark all networks enabled if no
5173 * network specified.
5174 */
5175 for (other_ssid = wpa_s->conf->ssid; other_ssid;
5176 other_ssid = other_ssid->next) {
5177 int was_disabled = other_ssid->disabled;
5178 if (was_disabled == 2)
5179 continue; /* do not change persistent P2P group data */
5180
5181 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005182 if (was_disabled && !other_ssid->disabled)
5183 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005184
5185 if (was_disabled != other_ssid->disabled)
5186 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
5187 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005188
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005189 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
5190 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005191 /* We are already associated with the selected network */
5192 wpa_printf(MSG_DEBUG, "Already associated with the "
5193 "selected network - do nothing");
5194 return;
5195 }
5196
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005197 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005198 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005199 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005200 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00005201 (ssid->mode == WPAS_MODE_MESH ||
5202 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005203
Sunil Ravi7f769292024-07-23 22:21:32 +00005204 if (ssid->scan_ssid &&
5205 (wpa_s->no_suitable_network || wpa_s->last_scan_external)) {
5206 wpa_printf(MSG_DEBUG,
5207 "Request a new scan for hidden network");
5208 request_new_scan = true;
5209 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
5210 !ssid->owe_only) {
5211 wpa_printf(MSG_DEBUG,
5212 "Request a new scan for OWE transition SSID");
5213 request_new_scan = true;
5214 }
5215
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07005216 /*
5217 * Don't optimize next scan freqs since a new ESS has been
5218 * selected.
5219 */
5220 os_free(wpa_s->next_scan_freqs);
5221 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005222 } else {
5223 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005224 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005226 wpa_s->disconnected = 0;
5227 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005228 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005229 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005230 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005231 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07005232 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07005233 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005234
Sunil Ravi7f769292024-07-23 22:21:32 +00005235 if (wpa_s->connect_without_scan || request_new_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005236 wpa_supplicant_fast_associate(wpa_s) != 1) {
5237 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005238 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005239 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005240 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241
5242 if (ssid)
5243 wpas_notify_network_selected(wpa_s, ssid);
5244}
5245
5246
5247/**
Hai Shalomc1a21442022-02-04 13:43:00 -08005248 * wpas_remove_cred - Remove the specified credential and all the network
5249 * entries created based on the removed credential
5250 * @wpa_s: wpa_supplicant structure for a network interface
5251 * @cred: The credential to remove
5252 * Returns: 0 on success, -1 on failure
5253 */
5254int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
5255{
5256 struct wpa_ssid *ssid, *next;
5257 int id;
5258
5259 if (!cred) {
5260 wpa_printf(MSG_DEBUG, "Could not find cred");
5261 return -1;
5262 }
5263
5264 id = cred->id;
5265 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
5266 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
5267 return -1;
5268 }
5269
5270 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
5271
5272 /* Remove any network entry created based on the removed credential */
5273 ssid = wpa_s->conf->ssid;
5274 while (ssid) {
5275 next = ssid->next;
5276
5277 if (ssid->parent_cred == cred) {
5278 wpa_printf(MSG_DEBUG,
5279 "Remove network id %d since it used the removed credential",
5280 ssid->id);
5281 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5282 -1) {
5283 wpa_printf(MSG_DEBUG,
5284 "Could not find network id=%d",
5285 ssid->id);
5286 }
5287 }
5288
5289 ssid = next;
5290 }
5291
5292 return 0;
5293}
5294
5295
5296/**
5297 * wpas_remove_cred - Remove all the Interworking credentials
5298 * @wpa_s: wpa_supplicant structure for a network interface
5299 * Returns: 0 on success, -1 on failure
5300 */
5301int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5302{
5303 int res, ret = 0;
5304 struct wpa_cred *cred, *prev;
5305
5306 cred = wpa_s->conf->cred;
5307 while (cred) {
5308 prev = cred;
5309 cred = cred->next;
5310 res = wpas_remove_cred(wpa_s, prev);
5311 if (res < 0) {
5312 wpa_printf(MSG_DEBUG,
5313 "Removal of all credentials failed - failed to remove credential id=%d",
5314 prev->id);
5315 ret = -1;
5316 }
5317 }
5318
5319 return ret;
5320}
5321
5322
5323/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005324 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5325 * @wpa_s: wpa_supplicant structure for a network interface
5326 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5327 * @pkcs11_module_path: PKCS #11 module path or NULL
5328 * Returns: 0 on success; -1 on failure
5329 *
5330 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5331 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5332 * module path fails the paths will be reset to the default value (NULL).
5333 */
5334int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5335 const char *pkcs11_engine_path,
5336 const char *pkcs11_module_path)
5337{
5338 char *pkcs11_engine_path_copy = NULL;
5339 char *pkcs11_module_path_copy = NULL;
5340
5341 if (pkcs11_engine_path != NULL) {
5342 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5343 if (pkcs11_engine_path_copy == NULL)
5344 return -1;
5345 }
5346 if (pkcs11_module_path != NULL) {
5347 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005348 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005349 os_free(pkcs11_engine_path_copy);
5350 return -1;
5351 }
5352 }
5353
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005354#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005355 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005356 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005357#endif /* CONFIG_PKCS11_ENGINE_PATH */
5358#ifndef CONFIG_PKCS11_MODULE_PATH
5359 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005360 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005361#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005362
5363 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5364 eapol_sm_deinit(wpa_s->eapol);
5365 wpa_s->eapol = NULL;
5366 if (wpa_supplicant_init_eapol(wpa_s)) {
5367 /* Error -> Reset paths to the default value (NULL) once. */
5368 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5369 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5370 NULL);
5371
5372 return -1;
5373 }
5374 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5375
5376 return 0;
5377}
5378
5379
5380/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005381 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5382 * @wpa_s: wpa_supplicant structure for a network interface
5383 * @ap_scan: AP scan mode
5384 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5385 *
5386 */
5387int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5388{
5389
5390 int old_ap_scan;
5391
5392 if (ap_scan < 0 || ap_scan > 2)
5393 return -1;
5394
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005395 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5396 wpa_printf(MSG_INFO,
5397 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5398 }
5399
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005400#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005401 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5402 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5403 wpa_s->wpa_state < WPA_COMPLETED) {
5404 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5405 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005406 return 0;
5407 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005408#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005410 old_ap_scan = wpa_s->conf->ap_scan;
5411 wpa_s->conf->ap_scan = ap_scan;
5412
5413 if (old_ap_scan != wpa_s->conf->ap_scan)
5414 wpas_notify_ap_scan_changed(wpa_s);
5415
5416 return 0;
5417}
5418
5419
5420/**
5421 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5422 * @wpa_s: wpa_supplicant structure for a network interface
5423 * @expire_age: Expiration age in seconds
5424 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5425 *
5426 */
5427int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5428 unsigned int bss_expire_age)
5429{
5430 if (bss_expire_age < 10) {
5431 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5432 bss_expire_age);
5433 return -1;
5434 }
5435 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5436 bss_expire_age);
5437 wpa_s->conf->bss_expiration_age = bss_expire_age;
5438
5439 return 0;
5440}
5441
5442
5443/**
5444 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5445 * @wpa_s: wpa_supplicant structure for a network interface
5446 * @expire_count: number of scans after which an unseen BSS is reclaimed
5447 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5448 *
5449 */
5450int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5451 unsigned int bss_expire_count)
5452{
5453 if (bss_expire_count < 1) {
5454 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5455 bss_expire_count);
5456 return -1;
5457 }
5458 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5459 bss_expire_count);
5460 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5461
5462 return 0;
5463}
5464
5465
5466/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005467 * wpa_supplicant_set_scan_interval - Set scan interval
5468 * @wpa_s: wpa_supplicant structure for a network interface
5469 * @scan_interval: scan interval in seconds
5470 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5471 *
5472 */
5473int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5474 int scan_interval)
5475{
5476 if (scan_interval < 0) {
5477 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5478 scan_interval);
5479 return -1;
5480 }
5481 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5482 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005483 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005484
5485 return 0;
5486}
5487
5488
5489/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005490 * wpa_supplicant_set_debug_params - Set global debug params
5491 * @global: wpa_global structure
5492 * @debug_level: debug level
5493 * @debug_timestamp: determines if show timestamp in debug data
5494 * @debug_show_keys: determines if show keys in debug data
5495 * Returns: 0 if succeed or -1 if debug_level has wrong value
5496 */
5497int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5498 int debug_timestamp, int debug_show_keys)
5499{
5500
5501 int old_level, old_timestamp, old_show_keys;
5502
5503 /* check for allowed debuglevels */
5504 if (debug_level != MSG_EXCESSIVE &&
5505 debug_level != MSG_MSGDUMP &&
5506 debug_level != MSG_DEBUG &&
5507 debug_level != MSG_INFO &&
5508 debug_level != MSG_WARNING &&
5509 debug_level != MSG_ERROR)
5510 return -1;
5511
5512 old_level = wpa_debug_level;
5513 old_timestamp = wpa_debug_timestamp;
5514 old_show_keys = wpa_debug_show_keys;
5515
5516 wpa_debug_level = debug_level;
5517 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5518 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5519
5520 if (wpa_debug_level != old_level)
5521 wpas_notify_debug_level_changed(global);
5522 if (wpa_debug_timestamp != old_timestamp)
5523 wpas_notify_debug_timestamp_changed(global);
5524 if (wpa_debug_show_keys != old_show_keys)
5525 wpas_notify_debug_show_keys_changed(global);
5526
5527 return 0;
5528}
5529
5530
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005531#ifdef CONFIG_OWE
5532static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5533 const u8 *entry_ssid, size_t entry_ssid_len)
5534{
Sunil Ravic0f5d412024-09-11 22:12:49 +00005535 const u8 *owe, *owe_bssid, *owe_ssid;
5536 size_t owe_ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005537 struct wpa_bss *bss;
5538
5539 /* Check network profile SSID aganst the SSID in the
5540 * OWE Transition Mode element. */
5541
5542 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5543 if (!bss)
5544 return 0;
5545
5546 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5547 if (!owe)
5548 return 0;
5549
Sunil Ravic0f5d412024-09-11 22:12:49 +00005550 if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
5551 &owe_ssid_len))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005552 return 0;
5553
Sunil Ravic0f5d412024-09-11 22:12:49 +00005554 return entry_ssid_len == owe_ssid_len &&
5555 os_memcmp(owe_ssid, entry_ssid, owe_ssid_len) == 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005556}
5557#endif /* CONFIG_OWE */
5558
5559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005560/**
5561 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5562 * @wpa_s: Pointer to wpa_supplicant data
5563 * Returns: A pointer to the current network structure or %NULL on failure
5564 */
5565struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5566{
5567 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005568 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569 int res;
5570 size_t ssid_len;
5571 u8 bssid[ETH_ALEN];
5572 int wired;
5573
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005574 res = wpa_drv_get_ssid(wpa_s, ssid);
5575 if (res < 0) {
5576 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5577 "driver");
5578 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005580 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005581
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005582 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5584 "driver");
5585 return NULL;
5586 }
5587
5588 wired = wpa_s->conf->ap_scan == 0 &&
5589 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5590
5591 entry = wpa_s->conf->ssid;
5592 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005593 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005594 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005595 (!entry->ssid ||
5596 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5597 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005598 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005599 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005600 return entry;
5601#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005602 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005603 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5604 (entry->ssid == NULL || entry->ssid_len == 0) &&
5605 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005606 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005607 return entry;
5608#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005609
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005610#ifdef CONFIG_OWE
5611 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005612 (entry->ssid &&
5613 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5614 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005615 (!entry->bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005616 ether_addr_equal(bssid, entry->bssid)))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005617 return entry;
5618#endif /* CONFIG_OWE */
5619
Dmitry Shmidt04949592012-07-19 12:16:46 -07005620 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005621 entry->ssid_len == 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005622 ether_addr_equal(bssid, entry->bssid))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005623 return entry;
5624
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005625 entry = entry->next;
5626 }
5627
5628 return NULL;
5629}
5630
5631
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005632static int select_driver(struct wpa_supplicant *wpa_s, int i)
5633{
5634 struct wpa_global *global = wpa_s->global;
5635
5636 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005637 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005638 if (global->drv_priv[i] == NULL) {
5639 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5640 "'%s'", wpa_drivers[i]->name);
5641 return -1;
5642 }
5643 }
5644
5645 wpa_s->driver = wpa_drivers[i];
5646 wpa_s->global_drv_priv = global->drv_priv[i];
5647
5648 return 0;
5649}
5650
5651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005652static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5653 const char *name)
5654{
5655 int i;
5656 size_t len;
5657 const char *pos, *driver = name;
5658
5659 if (wpa_s == NULL)
5660 return -1;
5661
5662 if (wpa_drivers[0] == NULL) {
5663 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5664 "wpa_supplicant");
5665 return -1;
5666 }
5667
5668 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005669 /* Default to first successful driver in the list */
5670 for (i = 0; wpa_drivers[i]; i++) {
5671 if (select_driver(wpa_s, i) == 0)
5672 return 0;
5673 }
5674 /* Drivers have each reported failure, so no wpa_msg() here. */
5675 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005676 }
5677
5678 do {
5679 pos = os_strchr(driver, ',');
5680 if (pos)
5681 len = pos - driver;
5682 else
5683 len = os_strlen(driver);
5684
5685 for (i = 0; wpa_drivers[i]; i++) {
5686 if (os_strlen(wpa_drivers[i]->name) == len &&
5687 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005688 0) {
5689 /* First driver that succeeds wins */
5690 if (select_driver(wpa_s, i) == 0)
5691 return 0;
5692 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005693 }
5694
5695 driver = pos + 1;
5696 } while (pos);
5697
5698 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5699 return -1;
5700}
5701
5702
5703/**
5704 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5705 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5706 * with struct wpa_driver_ops::init()
5707 * @src_addr: Source address of the EAPOL frame
5708 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5709 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005710 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005711 *
5712 * This function is called for each received EAPOL frame. Most driver
5713 * interfaces rely on more generic OS mechanism for receiving frames through
5714 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5715 * take care of received EAPOL frames and deliver them to the core supplicant
5716 * code by calling this function.
5717 */
5718void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005719 const u8 *buf, size_t len,
5720 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005721{
5722 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005723 const u8 *connected_addr = wpa_s->valid_links ?
5724 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005725
Sunil8cd6f4d2022-06-28 18:40:46 +00005726 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5727 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005728 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5729
Hai Shalomc1a21442022-02-04 13:43:00 -08005730 if (wpa_s->own_disconnect_req) {
5731 wpa_printf(MSG_DEBUG,
5732 "Drop received EAPOL frame as we are disconnecting");
5733 return;
5734 }
5735
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005736#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005737 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5738 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005739 if (wpa_s->ignore_auth_resp) {
5740 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5741 return;
5742 }
5743#endif /* CONFIG_TESTING_OPTIONS */
5744
Jouni Malinena05074c2012-12-21 21:35:35 +02005745 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5746 (wpa_s->last_eapol_matches_bssid &&
5747#ifdef CONFIG_AP
5748 !wpa_s->ap_iface &&
5749#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005750 !ether_addr_equal(src_addr, connected_addr))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 /*
5752 * There is possible race condition between receiving the
5753 * association event and the EAPOL frame since they are coming
5754 * through different paths from the driver. In order to avoid
5755 * issues in trying to process the EAPOL frame before receiving
5756 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005757 * the association event is received. This may also be needed in
5758 * driver-based roaming case, so also use src_addr != BSSID as a
5759 * trigger if we have previously confirmed that the
5760 * Authenticator uses BSSID as the src_addr (which is not the
5761 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005762 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005763 wpa_dbg(wpa_s, MSG_DEBUG,
5764 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5765 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005766 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005767 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005768 wpabuf_free(wpa_s->pending_eapol_rx);
5769 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5770 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005771 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005772 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5773 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005774 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005775 }
5776 return;
5777 }
5778
Jouni Malinena05074c2012-12-21 21:35:35 +02005779 wpa_s->last_eapol_matches_bssid =
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005780 ether_addr_equal(src_addr, connected_addr);
Jouni Malinena05074c2012-12-21 21:35:35 +02005781
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005782#ifdef CONFIG_AP
5783 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005784 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5785 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005786 return;
5787 }
5788#endif /* CONFIG_AP */
5789
5790 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5791 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5792 "no key management is configured");
5793 return;
5794 }
5795
5796 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005797 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005798 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5799 wpa_s->wpa_state != WPA_COMPLETED) &&
5800 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005801 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005802 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005803 int timeout = 10;
5804
5805 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5806 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5807 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5808 /* Use longer timeout for IEEE 802.1X/EAP */
5809 timeout = 70;
5810 }
5811
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005812#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005813 if (wpa_s->current_ssid && wpa_s->current_bss &&
5814 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5815 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5816 /*
5817 * Use shorter timeout if going through WPS AP iteration
5818 * for PIN config method with an AP that does not
5819 * advertise Selected Registrar.
5820 */
5821 struct wpabuf *wps_ie;
5822
5823 wps_ie = wpa_bss_get_vendor_ie_multi(
5824 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5825 if (wps_ie &&
5826 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5827 timeout = 10;
5828 wpabuf_free(wps_ie);
5829 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005830#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005831
5832 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833 }
5834 wpa_s->eapol_received++;
5835
5836 if (wpa_s->countermeasures) {
5837 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5838 "EAPOL packet");
5839 return;
5840 }
5841
5842#ifdef CONFIG_IBSS_RSN
5843 if (wpa_s->current_ssid &&
5844 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005845 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5846 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005847 return;
5848 }
5849#endif /* CONFIG_IBSS_RSN */
5850
5851 /* Source address of the incoming EAPOL frame could be compared to the
5852 * current BSSID. However, it is possible that a centralized
5853 * Authenticator could be using another MAC address than the BSSID of
5854 * an AP, so just allow any address to be used for now. The replies are
5855 * still sent to the current BSSID (if available), though. */
5856
5857 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5858 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005859 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5860 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005861 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5862 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005863 return;
5864 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005865 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005866 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5868 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005869 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005870 * handshake processing which would normally set portValid. We
5871 * need this to allow the EAPOL state machines to be completed
5872 * without going through EAPOL-Key handshake.
5873 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005874 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005875 }
5876}
5877
5878
Sunil8cd6f4d2022-06-28 18:40:46 +00005879static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5880 const u8 *buf, size_t len)
5881{
5882 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5883 FRAME_ENCRYPTION_UNKNOWN);
5884}
5885
5886
Hai Shalomb755a2a2020-04-23 21:49:02 -07005887static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5888{
5889 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5890 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5891}
5892
5893
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005894int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005895{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005896 u8 prev_mac_addr[ETH_ALEN];
5897
5898 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5899
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005900 if ((!wpa_s->p2p_mgmt ||
5901 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5902 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005903 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005904 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5905 wpa_drv_get_mac_addr(wpa_s),
5906 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005907 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005908 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005909 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005910 if (wpa_s->l2 == NULL)
5911 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005912
5913 if (l2_packet_set_packet_filter(wpa_s->l2,
5914 L2_PACKET_FILTER_PKTTYPE))
5915 wpa_dbg(wpa_s, MSG_DEBUG,
5916 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005917
5918 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5919 wpa_msg(wpa_s, MSG_ERROR,
5920 "Failed to get own L2 address");
5921 return -1;
5922 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005923 } else {
5924 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5925 if (addr)
5926 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5927 }
5928
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005929 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005930 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005931
Hai Shalomc3565922019-10-28 11:58:20 -07005932#ifdef CONFIG_FST
5933 if (wpa_s->fst)
5934 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5935#endif /* CONFIG_FST */
5936
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005937 if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00005938 wpas_notify_mac_address_changed(wpa_s);
5939
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005940 return 0;
5941}
5942
5943
Dmitry Shmidt04949592012-07-19 12:16:46 -07005944static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5945 const u8 *buf, size_t len)
5946{
5947 struct wpa_supplicant *wpa_s = ctx;
5948 const struct l2_ethhdr *eth;
5949
5950 if (len < sizeof(*eth))
5951 return;
5952 eth = (const struct l2_ethhdr *) buf;
5953
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005954 if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
Dmitry Shmidt04949592012-07-19 12:16:46 -07005955 !(eth->h_dest[0] & 0x01)) {
5956 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5957 " (bridge - not for this interface - ignore)",
5958 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5959 return;
5960 }
5961
5962 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5963 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5964 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005965 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005966}
5967
5968
Hai Shalom899fcc72020-10-19 14:38:18 -07005969int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5970 const char *bridge_ifname)
5971{
5972 if (wpa_s->wpa_state > WPA_SCANNING)
5973 return -EBUSY;
5974
5975 if (bridge_ifname &&
5976 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5977 return -EINVAL;
5978
5979 if (!bridge_ifname)
5980 bridge_ifname = "";
5981
5982 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5983 return 0;
5984
5985 if (wpa_s->l2_br) {
5986 l2_packet_deinit(wpa_s->l2_br);
5987 wpa_s->l2_br = NULL;
5988 }
5989
5990 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5991 sizeof(wpa_s->bridge_ifname));
5992
5993 if (wpa_s->bridge_ifname[0]) {
5994 wpa_dbg(wpa_s, MSG_DEBUG,
5995 "Receiving packets from bridge interface '%s'",
5996 wpa_s->bridge_ifname);
5997 wpa_s->l2_br = l2_packet_init_bridge(
5998 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5999 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
6000 if (!wpa_s->l2_br) {
6001 wpa_msg(wpa_s, MSG_ERROR,
6002 "Failed to open l2_packet connection for the bridge interface '%s'",
6003 wpa_s->bridge_ifname);
6004 goto fail;
6005 }
6006 }
6007
6008#ifdef CONFIG_TDLS
6009 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
6010 goto fail;
6011#endif /* CONFIG_TDLS */
6012
6013 return 0;
6014fail:
6015 wpa_s->bridge_ifname[0] = 0;
6016 if (wpa_s->l2_br) {
6017 l2_packet_deinit(wpa_s->l2_br);
6018 wpa_s->l2_br = NULL;
6019 }
6020#ifdef CONFIG_TDLS
6021 if (!wpa_s->p2p_mgmt)
6022 wpa_tdls_init(wpa_s->wpa);
6023#endif /* CONFIG_TDLS */
6024 return -EIO;
6025}
6026
6027
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006028/**
6029 * wpa_supplicant_driver_init - Initialize driver interface parameters
6030 * @wpa_s: Pointer to wpa_supplicant data
6031 * Returns: 0 on success, -1 on failure
6032 *
6033 * This function is called to initialize driver interface parameters.
6034 * wpa_drv_init() must have been called before this function to initialize the
6035 * driver interface.
6036 */
6037int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
6038{
6039 static int interface_count = 0;
6040
6041 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
6042 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006043
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006044 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
6045 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006046 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006047 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
6048
Hai Shalomb755a2a2020-04-23 21:49:02 -07006049 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006050 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
6051 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006052 wpa_s->l2_br = l2_packet_init_bridge(
6053 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
6054 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006055 if (wpa_s->l2_br == NULL) {
6056 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
6057 "connection for the bridge interface '%s'",
6058 wpa_s->bridge_ifname);
6059 return -1;
6060 }
6061 }
6062
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006063 if (wpa_s->conf->ap_scan == 2 &&
6064 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
6065 wpa_printf(MSG_INFO,
6066 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
6067 }
6068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006069 wpa_clear_keys(wpa_s, NULL);
6070
6071 /* Make sure that TKIP countermeasures are not left enabled (could
6072 * happen if wpa_supplicant is killed during countermeasures. */
6073 wpa_drv_set_countermeasures(wpa_s, 0);
6074
6075 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
6076 wpa_drv_flush_pmkid(wpa_s);
6077
6078 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006079 wpa_s->prev_scan_wildcard = 0;
6080
Dmitry Shmidt04949592012-07-19 12:16:46 -07006081 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08006082 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6083 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
6084 interface_count = 0;
6085 }
Keith Mok4389c282022-11-23 21:36:48 +00006086#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08006087 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07006088 wpa_supplicant_delayed_sched_scan(wpa_s,
6089 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006090 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07006091 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006092 100000);
Keith Mok4389c282022-11-23 21:36:48 +00006093#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006094 interface_count++;
6095 } else
6096 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
6097
6098 return 0;
6099}
6100
6101
6102static int wpa_supplicant_daemon(const char *pid_file)
6103{
6104 wpa_printf(MSG_DEBUG, "Daemonize..");
6105 return os_daemonize(pid_file);
6106}
6107
6108
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006109static struct wpa_supplicant *
6110wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006111{
6112 struct wpa_supplicant *wpa_s;
6113
6114 wpa_s = os_zalloc(sizeof(*wpa_s));
6115 if (wpa_s == NULL)
6116 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006117 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006118 wpa_s->scan_interval = 5;
6119 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006120 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006121 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006122 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08006123 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006124
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006125 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08006126 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07006127#ifdef CONFIG_TESTING_OPTIONS
6128 dl_list_init(&wpa_s->drv_signal_override);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006129 wpa_s->test_assoc_comeback_type = -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07006130#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006131#ifndef CONFIG_NO_ROBUST_AV
Hai Shalomc1a21442022-02-04 13:43:00 -08006132 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006133#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00006134 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006136 return wpa_s;
6137}
6138
6139
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006140#ifdef CONFIG_HT_OVERRIDES
6141
6142static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
6143 struct ieee80211_ht_capabilities *htcaps,
6144 struct ieee80211_ht_capabilities *htcaps_mask,
6145 const char *ht_mcs)
6146{
6147 /* parse ht_mcs into hex array */
6148 int i;
6149 const char *tmp = ht_mcs;
6150 char *end = NULL;
6151
6152 /* If ht_mcs is null, do not set anything */
6153 if (!ht_mcs)
6154 return 0;
6155
6156 /* This is what we are setting in the kernel */
6157 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
6158
6159 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
6160
6161 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08006162 long v;
6163
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006164 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08006165 v = strtol(tmp, &end, 16);
6166
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006167 if (errno == 0) {
6168 wpa_msg(wpa_s, MSG_DEBUG,
6169 "htcap value[%i]: %ld end: %p tmp: %p",
6170 i, v, end, tmp);
6171 if (end == tmp)
6172 break;
6173
6174 htcaps->supported_mcs_set[i] = v;
6175 tmp = end;
6176 } else {
6177 wpa_msg(wpa_s, MSG_ERROR,
6178 "Failed to parse ht-mcs: %s, error: %s\n",
6179 ht_mcs, strerror(errno));
6180 return -1;
6181 }
6182 }
6183
6184 /*
6185 * If we were able to parse any values, then set mask for the MCS set.
6186 */
6187 if (i) {
6188 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
6189 IEEE80211_HT_MCS_MASK_LEN - 1);
6190 /* skip the 3 reserved bits */
6191 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
6192 0x1f;
6193 }
6194
6195 return 0;
6196}
6197
6198
6199static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
6200 struct ieee80211_ht_capabilities *htcaps,
6201 struct ieee80211_ht_capabilities *htcaps_mask,
6202 int disabled)
6203{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006204 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006205
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006206 if (disabled == -1)
6207 return 0;
6208
Hai Shalom74f70d42019-02-11 14:42:39 -08006209 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
6210
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006211 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
6212 htcaps_mask->ht_capabilities_info |= msk;
6213 if (disabled)
6214 htcaps->ht_capabilities_info &= msk;
6215 else
6216 htcaps->ht_capabilities_info |= msk;
6217
6218 return 0;
6219}
6220
6221
6222static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
6223 struct ieee80211_ht_capabilities *htcaps,
6224 struct ieee80211_ht_capabilities *htcaps_mask,
6225 int factor)
6226{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006227 if (factor == -1)
6228 return 0;
6229
Hai Shalom74f70d42019-02-11 14:42:39 -08006230 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
6231
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006232 if (factor < 0 || factor > 3) {
6233 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
6234 "Must be 0-3 or -1", factor);
6235 return -EINVAL;
6236 }
6237
6238 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
6239 htcaps->a_mpdu_params &= ~0x3;
6240 htcaps->a_mpdu_params |= factor & 0x3;
6241
6242 return 0;
6243}
6244
6245
6246static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
6247 struct ieee80211_ht_capabilities *htcaps,
6248 struct ieee80211_ht_capabilities *htcaps_mask,
6249 int density)
6250{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006251 if (density == -1)
6252 return 0;
6253
Hai Shalom74f70d42019-02-11 14:42:39 -08006254 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
6255
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006256 if (density < 0 || density > 7) {
6257 wpa_msg(wpa_s, MSG_ERROR,
6258 "ampdu_density: %d out of range. Must be 0-7 or -1.",
6259 density);
6260 return -EINVAL;
6261 }
6262
6263 htcaps_mask->a_mpdu_params |= 0x1C;
6264 htcaps->a_mpdu_params &= ~(0x1C);
6265 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
6266
6267 return 0;
6268}
6269
6270
6271static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6272 struct ieee80211_ht_capabilities *htcaps,
6273 struct ieee80211_ht_capabilities *htcaps_mask,
6274 int disabled)
6275{
Hai Shalom74f70d42019-02-11 14:42:39 -08006276 if (disabled)
6277 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006278
Paul Stewart092955c2017-02-06 09:13:09 -08006279 set_disable_ht40(htcaps, disabled);
6280 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006281
6282 return 0;
6283}
6284
6285
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006286static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6287 struct ieee80211_ht_capabilities *htcaps,
6288 struct ieee80211_ht_capabilities *htcaps_mask,
6289 int disabled)
6290{
6291 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006292 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6293 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006294
Hai Shalom74f70d42019-02-11 14:42:39 -08006295 if (disabled)
6296 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006297
6298 if (disabled)
6299 htcaps->ht_capabilities_info &= ~msk;
6300 else
6301 htcaps->ht_capabilities_info |= msk;
6302
6303 htcaps_mask->ht_capabilities_info |= msk;
6304
6305 return 0;
6306}
6307
6308
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006309static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6310 struct ieee80211_ht_capabilities *htcaps,
6311 struct ieee80211_ht_capabilities *htcaps_mask,
6312 int disabled)
6313{
6314 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006315 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006316
Hai Shalom74f70d42019-02-11 14:42:39 -08006317 if (disabled)
6318 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006319
6320 if (disabled)
6321 htcaps->ht_capabilities_info &= ~msk;
6322 else
6323 htcaps->ht_capabilities_info |= msk;
6324
6325 htcaps_mask->ht_capabilities_info |= msk;
6326
6327 return 0;
6328}
6329
6330
Hai Shalom74f70d42019-02-11 14:42:39 -08006331static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6332 struct ieee80211_ht_capabilities *htcaps,
6333 struct ieee80211_ht_capabilities *htcaps_mask,
6334 int tx_stbc)
6335{
6336 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6337
6338 if (tx_stbc == -1)
6339 return 0;
6340
6341 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6342
6343 if (tx_stbc < 0 || tx_stbc > 1) {
6344 wpa_msg(wpa_s, MSG_ERROR,
6345 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6346 return -EINVAL;
6347 }
6348
6349 htcaps_mask->ht_capabilities_info |= msk;
6350 htcaps->ht_capabilities_info &= ~msk;
6351 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6352
6353 return 0;
6354}
6355
6356
6357static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6358 struct ieee80211_ht_capabilities *htcaps,
6359 struct ieee80211_ht_capabilities *htcaps_mask,
6360 int rx_stbc)
6361{
6362 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6363
6364 if (rx_stbc == -1)
6365 return 0;
6366
6367 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6368
6369 if (rx_stbc < 0 || rx_stbc > 3) {
6370 wpa_msg(wpa_s, MSG_ERROR,
6371 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6372 return -EINVAL;
6373 }
6374
6375 htcaps_mask->ht_capabilities_info |= msk;
6376 htcaps->ht_capabilities_info &= ~msk;
6377 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6378
6379 return 0;
6380}
6381
6382
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006383void wpa_supplicant_apply_ht_overrides(
6384 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6385 struct wpa_driver_associate_params *params)
6386{
6387 struct ieee80211_ht_capabilities *htcaps;
6388 struct ieee80211_ht_capabilities *htcaps_mask;
6389
6390 if (!ssid)
6391 return;
6392
6393 params->disable_ht = ssid->disable_ht;
6394 if (!params->htcaps || !params->htcaps_mask)
6395 return;
6396
6397 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6398 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6399 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6400 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6401 ssid->disable_max_amsdu);
6402 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6403 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6404 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006405 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006406 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006407 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6408 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006409
6410 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006411 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006412 htcaps->ht_capabilities_info |= bit;
6413 htcaps_mask->ht_capabilities_info |= bit;
6414 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006415}
6416
6417#endif /* CONFIG_HT_OVERRIDES */
6418
6419
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006420#ifdef CONFIG_VHT_OVERRIDES
6421void wpa_supplicant_apply_vht_overrides(
6422 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6423 struct wpa_driver_associate_params *params)
6424{
6425 struct ieee80211_vht_capabilities *vhtcaps;
6426 struct ieee80211_vht_capabilities *vhtcaps_mask;
6427
6428 if (!ssid)
6429 return;
6430
6431 params->disable_vht = ssid->disable_vht;
6432
6433 vhtcaps = (void *) params->vhtcaps;
6434 vhtcaps_mask = (void *) params->vhtcaps_mask;
6435
6436 if (!vhtcaps || !vhtcaps_mask)
6437 return;
6438
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006439 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6440 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006441
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006442#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006443 if (ssid->disable_sgi) {
6444 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6445 VHT_CAP_SHORT_GI_160);
6446 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6447 VHT_CAP_SHORT_GI_160);
6448 wpa_msg(wpa_s, MSG_DEBUG,
6449 "disable-sgi override specified, vht-caps: 0x%x",
6450 vhtcaps->vht_capabilities_info);
6451 }
6452
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006453 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006454 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6455 int max_ampdu;
6456
6457 max_ampdu = (ssid->vht_capa &
6458 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6459 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006460
6461 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6462 wpa_set_ampdu_factor(wpa_s,
6463 (void *) params->htcaps,
6464 (void *) params->htcaps_mask,
6465 max_ampdu);
6466 }
6467#endif /* CONFIG_HT_OVERRIDES */
6468
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006469#define OVERRIDE_MCS(i) \
6470 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6471 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006472 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006473 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006474 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6475 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006476 } \
6477 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6478 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006479 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006480 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006481 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6482 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006483 }
6484
6485 OVERRIDE_MCS(1);
6486 OVERRIDE_MCS(2);
6487 OVERRIDE_MCS(3);
6488 OVERRIDE_MCS(4);
6489 OVERRIDE_MCS(5);
6490 OVERRIDE_MCS(6);
6491 OVERRIDE_MCS(7);
6492 OVERRIDE_MCS(8);
6493}
6494#endif /* CONFIG_VHT_OVERRIDES */
6495
6496
Hai Shalomfdcde762020-04-02 11:19:20 -07006497#ifdef CONFIG_HE_OVERRIDES
6498void wpa_supplicant_apply_he_overrides(
6499 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6500 struct wpa_driver_associate_params *params)
6501{
6502 if (!ssid)
6503 return;
6504
6505 params->disable_he = ssid->disable_he;
6506}
6507#endif /* CONFIG_HE_OVERRIDES */
6508
6509
Sunil Ravi77d572f2023-01-17 23:58:31 +00006510void wpa_supplicant_apply_eht_overrides(
6511 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6512 struct wpa_driver_associate_params *params)
6513{
6514 if (!ssid)
6515 return;
6516
6517 params->disable_eht = ssid->disable_eht;
6518}
6519
6520
Dmitry Shmidt04949592012-07-19 12:16:46 -07006521static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6522{
6523#ifdef PCSC_FUNCS
6524 size_t len;
6525
6526 if (!wpa_s->conf->pcsc_reader)
6527 return 0;
6528
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006529 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006530 if (!wpa_s->scard)
6531 return 1;
6532
6533 if (wpa_s->conf->pcsc_pin &&
6534 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6535 scard_deinit(wpa_s->scard);
6536 wpa_s->scard = NULL;
6537 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6538 return -1;
6539 }
6540
6541 len = sizeof(wpa_s->imsi) - 1;
6542 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6543 scard_deinit(wpa_s->scard);
6544 wpa_s->scard = NULL;
6545 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6546 return -1;
6547 }
6548 wpa_s->imsi[len] = '\0';
6549
6550 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6551
6552 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6553 wpa_s->imsi, wpa_s->mnc_len);
6554
6555 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6556 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6557#endif /* PCSC_FUNCS */
6558
6559 return 0;
6560}
6561
6562
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006563int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6564{
6565 char *val, *pos;
6566
6567 ext_password_deinit(wpa_s->ext_pw);
6568 wpa_s->ext_pw = NULL;
6569 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6570
6571 if (!wpa_s->conf->ext_password_backend)
6572 return 0;
6573
6574 val = os_strdup(wpa_s->conf->ext_password_backend);
6575 if (val == NULL)
6576 return -1;
6577 pos = os_strchr(val, ':');
6578 if (pos)
6579 *pos++ = '\0';
6580
6581 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6582
6583 wpa_s->ext_pw = ext_password_init(val, pos);
6584 os_free(val);
6585 if (wpa_s->ext_pw == NULL) {
6586 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6587 return -1;
6588 }
6589 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6590
6591 return 0;
6592}
6593
6594
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006595#ifdef CONFIG_FST
6596
6597static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6598{
6599 struct wpa_supplicant *wpa_s = ctx;
6600
6601 return (is_zero_ether_addr(wpa_s->bssid) ||
6602 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6603}
6604
6605
6606static void wpas_fst_get_channel_info_cb(void *ctx,
6607 enum hostapd_hw_mode *hw_mode,
6608 u8 *channel)
6609{
6610 struct wpa_supplicant *wpa_s = ctx;
6611
6612 if (wpa_s->current_bss) {
6613 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6614 channel);
6615 } else if (wpa_s->hw.num_modes) {
6616 *hw_mode = wpa_s->hw.modes[0].mode;
6617 } else {
6618 WPA_ASSERT(0);
6619 *hw_mode = 0;
6620 }
6621}
6622
6623
6624static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6625{
6626 struct wpa_supplicant *wpa_s = ctx;
6627
6628 *modes = wpa_s->hw.modes;
6629 return wpa_s->hw.num_modes;
6630}
6631
6632
6633static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6634{
6635 struct wpa_supplicant *wpa_s = ctx;
6636
6637 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6638 wpa_s->fst_ies = fst_ies;
6639}
6640
6641
6642static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6643{
6644 struct wpa_supplicant *wpa_s = ctx;
6645
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006646 if (!ether_addr_equal(wpa_s->bssid, da)) {
Paul Stewart092955c2017-02-06 09:13:09 -08006647 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6648 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6649 return -1;
6650 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006651 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006652 wpa_s->own_addr, wpa_s->bssid,
6653 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006654 0);
6655}
6656
6657
6658static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6659{
6660 struct wpa_supplicant *wpa_s = ctx;
6661
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006662 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006663 return wpa_s->received_mb_ies;
6664}
6665
6666
6667static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6668 const u8 *buf, size_t size)
6669{
6670 struct wpa_supplicant *wpa_s = ctx;
6671 struct mb_ies_info info;
6672
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006673 WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006674
6675 if (!mb_ies_info_by_ies(&info, buf, size)) {
6676 wpabuf_free(wpa_s->received_mb_ies);
6677 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6678 }
6679}
6680
6681
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006682static const u8 * wpas_fst_get_peer_first(void *ctx,
6683 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006684 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006685{
6686 struct wpa_supplicant *wpa_s = ctx;
6687
6688 *get_ctx = NULL;
6689 if (!is_zero_ether_addr(wpa_s->bssid))
6690 return (wpa_s->received_mb_ies || !mb_only) ?
6691 wpa_s->bssid : NULL;
6692 return NULL;
6693}
6694
6695
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006696static const u8 * wpas_fst_get_peer_next(void *ctx,
6697 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006698 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006699{
6700 return NULL;
6701}
6702
6703void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6704 struct fst_wpa_obj *iface_obj)
6705{
Sunil8cd6f4d2022-06-28 18:40:46 +00006706 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006707 iface_obj->ctx = wpa_s;
6708 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6709 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6710 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6711 iface_obj->set_ies = wpas_fst_set_ies_cb;
6712 iface_obj->send_action = wpas_fst_send_action_cb;
6713 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6714 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6715 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6716 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6717}
6718#endif /* CONFIG_FST */
6719
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006720static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006721 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006722{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006723 struct wowlan_triggers *triggers;
6724 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006725
6726 if (!wpa_s->conf->wowlan_triggers)
6727 return 0;
6728
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006729 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6730 if (triggers) {
6731 ret = wpa_drv_wowlan(wpa_s, triggers);
6732 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006733 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006734 return ret;
6735}
6736
6737
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006738enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006739{
6740 if (freq < 3000)
6741 return BAND_2_4_GHZ;
6742 if (freq > 50000)
6743 return BAND_60_GHZ;
6744 return BAND_5_GHZ;
6745}
6746
6747
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006748unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006749{
6750 int i;
6751 unsigned int band = 0;
6752
6753 if (freqs) {
6754 /* freqs are specified for the radio work */
6755 for (i = 0; freqs[i]; i++)
6756 band |= wpas_freq_to_band(freqs[i]);
6757 } else {
6758 /*
6759 * freqs are not specified, implies all
6760 * the supported freqs by HW
6761 */
6762 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6763 if (wpa_s->hw.modes[i].num_channels != 0) {
6764 if (wpa_s->hw.modes[i].mode ==
6765 HOSTAPD_MODE_IEEE80211B ||
6766 wpa_s->hw.modes[i].mode ==
6767 HOSTAPD_MODE_IEEE80211G)
6768 band |= BAND_2_4_GHZ;
6769 else if (wpa_s->hw.modes[i].mode ==
6770 HOSTAPD_MODE_IEEE80211A)
6771 band |= BAND_5_GHZ;
6772 else if (wpa_s->hw.modes[i].mode ==
6773 HOSTAPD_MODE_IEEE80211AD)
6774 band |= BAND_60_GHZ;
6775 else if (wpa_s->hw.modes[i].mode ==
6776 HOSTAPD_MODE_IEEE80211ANY)
6777 band = BAND_2_4_GHZ | BAND_5_GHZ |
6778 BAND_60_GHZ;
6779 }
6780 }
6781 }
6782
6783 return band;
6784}
6785
6786
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006787static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6788 const char *rn)
6789{
6790 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6791 struct wpa_radio *radio;
6792
6793 while (rn && iface) {
6794 radio = iface->radio;
6795 if (radio && os_strcmp(rn, radio->name) == 0) {
6796 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6797 wpa_s->ifname, rn);
6798 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6799 return radio;
6800 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006801
6802 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006803 }
6804
6805 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6806 wpa_s->ifname, rn ? rn : "N/A");
6807 radio = os_zalloc(sizeof(*radio));
6808 if (radio == NULL)
6809 return NULL;
6810
6811 if (rn)
6812 os_strlcpy(radio->name, rn, sizeof(radio->name));
6813 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006814 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006815 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6816
6817 return radio;
6818}
6819
6820
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006821static void radio_work_free(struct wpa_radio_work *work)
6822{
6823 if (work->wpa_s->scan_work == work) {
6824 /* This should not really happen. */
6825 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6826 work->type, work, work->started);
6827 work->wpa_s->scan_work = NULL;
6828 }
6829
6830#ifdef CONFIG_P2P
6831 if (work->wpa_s->p2p_scan_work == work) {
6832 /* This should not really happen. */
6833 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6834 work->type, work, work->started);
6835 work->wpa_s->p2p_scan_work = NULL;
6836 }
6837#endif /* CONFIG_P2P */
6838
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006839 if (work->started) {
6840 work->wpa_s->radio->num_active_works--;
6841 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006842 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006843 work->type, work,
6844 work->wpa_s->radio->num_active_works);
6845 }
6846
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006847 dl_list_del(&work->list);
6848 os_free(work);
6849}
6850
6851
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006852static int radio_work_is_connect(struct wpa_radio_work *work)
6853{
6854 return os_strcmp(work->type, "sme-connect") == 0 ||
6855 os_strcmp(work->type, "connect") == 0;
6856}
6857
6858
6859static int radio_work_is_scan(struct wpa_radio_work *work)
6860{
6861 return os_strcmp(work->type, "scan") == 0 ||
6862 os_strcmp(work->type, "p2p-scan") == 0;
6863}
6864
6865
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006866static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6867{
6868 struct wpa_radio_work *active_work = NULL;
6869 struct wpa_radio_work *tmp;
6870
6871 /* Get the active work to know the type and band. */
6872 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6873 if (tmp->started) {
6874 active_work = tmp;
6875 break;
6876 }
6877 }
6878
6879 if (!active_work) {
6880 /* No active work, start one */
6881 radio->num_active_works = 0;
6882 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6883 list) {
6884 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006885 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006886 (((struct wpa_driver_scan_params *)
6887 tmp->ctx)->only_new_results ||
6888 tmp->wpa_s->clear_driver_scan_cache))
6889 continue;
6890 return tmp;
6891 }
6892 return NULL;
6893 }
6894
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006895 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006896 /*
6897 * If the active work is either connect or sme-connect,
6898 * do not parallelize them with other radio works.
6899 */
6900 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6901 "Do not parallelize radio work with %s",
6902 active_work->type);
6903 return NULL;
6904 }
6905
6906 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6907 if (tmp->started)
6908 continue;
6909
6910 /*
6911 * If connect or sme-connect are enqueued, parallelize only
6912 * those operations ahead of them in the queue.
6913 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006914 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006915 break;
6916
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006917 /* Serialize parallel scan and p2p_scan operations on the same
6918 * interface since the driver_nl80211 mechanism for tracking
6919 * scan cookies does not yet have support for this. */
6920 if (active_work->wpa_s == tmp->wpa_s &&
6921 radio_work_is_scan(active_work) &&
6922 radio_work_is_scan(tmp)) {
6923 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6924 "Do not start work '%s' when another work '%s' is already scheduled",
6925 tmp->type, active_work->type);
6926 continue;
6927 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006928 /*
6929 * Check that the radio works are distinct and
6930 * on different bands.
6931 */
6932 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6933 (active_work->bands != tmp->bands)) {
6934 /*
6935 * If a scan has to be scheduled through nl80211 scan
6936 * interface and if an external scan is already running,
6937 * do not schedule the scan since it is likely to get
6938 * rejected by kernel.
6939 */
6940 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006941 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006942 (((struct wpa_driver_scan_params *)
6943 tmp->ctx)->only_new_results ||
6944 tmp->wpa_s->clear_driver_scan_cache))
6945 continue;
6946
6947 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6948 "active_work:%s new_work:%s",
6949 active_work->type, tmp->type);
6950 return tmp;
6951 }
6952 }
6953
6954 /* Did not find a radio work to schedule in parallel. */
6955 return NULL;
6956}
6957
6958
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006959static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6960{
6961 struct wpa_radio *radio = eloop_ctx;
6962 struct wpa_radio_work *work;
6963 struct os_reltime now, diff;
6964 struct wpa_supplicant *wpa_s;
6965
6966 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006967 if (work == NULL) {
6968 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006969 return;
6970 }
6971
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006972 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6973 radio_list);
6974
6975 if (!(wpa_s &&
6976 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6977 if (work->started)
6978 return; /* already started and still in progress */
6979
Hai Shalom60840252021-02-19 19:02:11 -08006980 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006981 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6982 return;
6983 }
6984 } else {
6985 work = NULL;
6986 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6987 /* get the work to schedule next */
6988 work = radio_work_get_next_work(radio);
6989 }
6990 if (!work)
6991 return;
6992 }
6993
6994 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006995 os_get_reltime(&now);
6996 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006997 wpa_dbg(wpa_s, MSG_DEBUG,
6998 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006999 work->type, work, diff.sec, diff.usec);
7000 work->started = 1;
7001 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007002 radio->num_active_works++;
7003
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007004 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007005
7006 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
7007 radio->num_active_works < MAX_ACTIVE_WORKS)
7008 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007009}
7010
7011
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007012/*
7013 * This function removes both started and pending radio works running on
7014 * the provided interface's radio.
7015 * Prior to the removal of the radio work, its callback (cb) is called with
7016 * deinit set to be 1. Each work's callback is responsible for clearing its
7017 * internal data and restoring to a correct state.
7018 * @wpa_s: wpa_supplicant data
7019 * @type: type of works to be removed
7020 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
7021 * this interface's works.
7022 */
7023void radio_remove_works(struct wpa_supplicant *wpa_s,
7024 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007025{
7026 struct wpa_radio_work *work, *tmp;
7027 struct wpa_radio *radio = wpa_s->radio;
7028
7029 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
7030 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007031 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007032 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007033
7034 /* skip other ifaces' works */
7035 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007036 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007037
7038 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
7039 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007040 work->cb(work, 1);
7041 radio_work_free(work);
7042 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007043
7044 /* in case we removed the started work */
7045 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007046}
7047
7048
Roshan Pius3a1667e2018-07-03 15:17:14 -07007049void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
7050{
7051 struct wpa_radio_work *work;
7052 struct wpa_radio *radio = wpa_s->radio;
7053
7054 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7055 if (work->ctx != ctx)
7056 continue;
7057 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
7058 work->type, work, work->started ? " (started)" : "");
7059 radio_work_free(work);
7060 break;
7061 }
7062}
7063
7064
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007065static void radio_remove_interface(struct wpa_supplicant *wpa_s)
7066{
7067 struct wpa_radio *radio = wpa_s->radio;
7068
7069 if (!radio)
7070 return;
7071
7072 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
7073 wpa_s->ifname, radio->name);
7074 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007075 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08007076 /* If the interface that triggered the external scan was removed, the
7077 * external scan is no longer running. */
7078 if (wpa_s == radio->external_scan_req_interface)
7079 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007080 wpa_s->radio = NULL;
7081 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007082 return; /* Interfaces remain for this radio */
7083
7084 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007085 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007086 os_free(radio);
7087}
7088
7089
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007090void radio_work_check_next(struct wpa_supplicant *wpa_s)
7091{
7092 struct wpa_radio *radio = wpa_s->radio;
7093
7094 if (dl_list_empty(&radio->work))
7095 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007096 if (wpa_s->ext_work_in_progress) {
7097 wpa_printf(MSG_DEBUG,
7098 "External radio work in progress - delay start of pending item");
7099 return;
7100 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007101 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
7102 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
7103}
7104
7105
7106/**
7107 * radio_add_work - Add a radio work item
7108 * @wpa_s: Pointer to wpa_supplicant data
7109 * @freq: Frequency of the offchannel operation in MHz or 0
7110 * @type: Unique identifier for each type of work
7111 * @next: Force as the next work to be executed
7112 * @cb: Callback function for indicating when radio is available
7113 * @ctx: Context pointer for the work (work->ctx in cb())
7114 * Returns: 0 on success, -1 on failure
7115 *
7116 * This function is used to request time for an operation that requires
7117 * exclusive radio control. Once the radio is available, the registered callback
7118 * function will be called. radio_work_done() must be called once the exclusive
7119 * radio operation has been completed, so that the radio is freed for other
7120 * operations. The special case of deinit=1 is used to free the context data
7121 * during interface removal. That does not allow the callback function to start
7122 * the radio operation, i.e., it must free any resources allocated for the radio
7123 * work and return.
7124 *
7125 * The @freq parameter can be used to indicate a single channel on which the
7126 * offchannel operation will occur. This may allow multiple radio work
7127 * operations to be performed in parallel if they apply for the same channel.
7128 * Setting this to 0 indicates that the work item may use multiple channels or
7129 * requires exclusive control of the radio.
7130 */
7131int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
7132 const char *type, int next,
7133 void (*cb)(struct wpa_radio_work *work, int deinit),
7134 void *ctx)
7135{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007136 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007137 struct wpa_radio_work *work;
7138 int was_empty;
7139
7140 work = os_zalloc(sizeof(*work));
7141 if (work == NULL)
7142 return -1;
7143 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
7144 os_get_reltime(&work->time);
7145 work->freq = freq;
7146 work->type = type;
7147 work->wpa_s = wpa_s;
7148 work->cb = cb;
7149 work->ctx = ctx;
7150
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007151 if (freq)
7152 work->bands = wpas_freq_to_band(freq);
7153 else if (os_strcmp(type, "scan") == 0 ||
7154 os_strcmp(type, "p2p-scan") == 0)
7155 work->bands = wpas_get_bands(wpa_s,
7156 ((struct wpa_driver_scan_params *)
7157 ctx)->freqs);
7158 else
7159 work->bands = wpas_get_bands(wpa_s, NULL);
7160
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007161 was_empty = dl_list_empty(&wpa_s->radio->work);
7162 if (next)
7163 dl_list_add(&wpa_s->radio->work, &work->list);
7164 else
7165 dl_list_add_tail(&wpa_s->radio->work, &work->list);
7166 if (was_empty) {
7167 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
7168 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007169 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
7170 && radio->num_active_works < MAX_ACTIVE_WORKS) {
7171 wpa_dbg(wpa_s, MSG_DEBUG,
7172 "Try to schedule a radio work (num_active_works=%u)",
7173 radio->num_active_works);
7174 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007175 }
7176
7177 return 0;
7178}
7179
7180
7181/**
7182 * radio_work_done - Indicate that a radio work item has been completed
7183 * @work: Completed work
7184 *
7185 * This function is called once the callback function registered with
7186 * radio_add_work() has completed its work.
7187 */
7188void radio_work_done(struct wpa_radio_work *work)
7189{
7190 struct wpa_supplicant *wpa_s = work->wpa_s;
7191 struct os_reltime now, diff;
7192 unsigned int started = work->started;
7193
7194 os_get_reltime(&now);
7195 os_reltime_sub(&now, &work->time, &diff);
7196 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
7197 work->type, work, started ? "done" : "canceled",
7198 diff.sec, diff.usec);
7199 radio_work_free(work);
7200 if (started)
7201 radio_work_check_next(wpa_s);
7202}
7203
7204
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007205struct wpa_radio_work *
7206radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007207{
7208 struct wpa_radio_work *work;
7209 struct wpa_radio *radio = wpa_s->radio;
7210
7211 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
7212 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007213 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007214 }
7215
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08007216 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007217}
7218
7219
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007220static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007221 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007222{
7223 const char *ifname, *driver, *rn;
7224
7225 driver = iface->driver;
7226next_driver:
7227 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
7228 return -1;
7229
7230 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
7231 if (wpa_s->drv_priv == NULL) {
7232 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07007233 int level = MSG_ERROR;
7234
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007235 pos = driver ? os_strchr(driver, ',') : NULL;
7236 if (pos) {
7237 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
7238 "driver interface - try next driver wrapper");
7239 driver = pos + 1;
7240 goto next_driver;
7241 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007242
7243#ifdef CONFIG_MATCH_IFACE
7244 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
7245 level = MSG_DEBUG;
7246#endif /* CONFIG_MATCH_IFACE */
7247 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007248 return -1;
7249 }
7250 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
7251 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
7252 "driver_param '%s'", wpa_s->conf->driver_param);
7253 return -1;
7254 }
7255
7256 ifname = wpa_drv_get_ifname(wpa_s);
7257 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
7258 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
7259 "interface name with '%s'", ifname);
7260 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
7261 }
7262
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07007263 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007264 if (rn && rn[0] == '\0')
7265 rn = NULL;
7266
7267 wpa_s->radio = radio_add_interface(wpa_s, rn);
7268 if (wpa_s->radio == NULL)
7269 return -1;
7270
7271 return 0;
7272}
7273
7274
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007275#ifdef CONFIG_GAS_SERVER
7276
7277static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7278 unsigned int freq, const u8 *dst,
7279 const u8 *src, const u8 *bssid,
7280 const u8 *data, size_t data_len,
7281 enum offchannel_send_action_result result)
7282{
7283 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7284 " result=%s",
7285 freq, MAC2STR(dst),
7286 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7287 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7288 "FAILED"));
7289 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7290 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7291}
7292
7293
7294static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7295 struct wpabuf *buf, unsigned int wait_time)
7296{
7297 struct wpa_supplicant *wpa_s = ctx;
7298 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7299
7300 if (wait_time > wpa_s->max_remain_on_chan)
7301 wait_time = wpa_s->max_remain_on_chan;
7302
7303 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7304 wpabuf_head(buf), wpabuf_len(buf),
7305 wait_time, wpas_gas_server_tx_status, 0);
7306}
7307
7308#endif /* CONFIG_GAS_SERVER */
7309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007310static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007311 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007312{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007313 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007314 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007315 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007316
7317 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7318 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7319 iface->confname ? iface->confname : "N/A",
7320 iface->driver ? iface->driver : "default",
7321 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7322 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7323
7324 if (iface->confname) {
7325#ifdef CONFIG_BACKEND_FILE
7326 wpa_s->confname = os_rel2abs_path(iface->confname);
7327 if (wpa_s->confname == NULL) {
7328 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7329 "for configuration file '%s'.",
7330 iface->confname);
7331 return -1;
7332 }
7333 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7334 iface->confname, wpa_s->confname);
7335#else /* CONFIG_BACKEND_FILE */
7336 wpa_s->confname = os_strdup(iface->confname);
7337#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007338 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007339 if (wpa_s->conf == NULL) {
7340 wpa_printf(MSG_ERROR, "Failed to read or parse "
7341 "configuration '%s'.", wpa_s->confname);
7342 return -1;
7343 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007344 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007345 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007346 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007347 wpa_printf(MSG_ERROR,
7348 "Failed to read or parse configuration '%s'.",
7349 wpa_s->confanother);
7350 return -1;
7351 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007352
7353 /*
7354 * Override ctrl_interface and driver_param if set on command
7355 * line.
7356 */
7357 if (iface->ctrl_interface) {
7358 os_free(wpa_s->conf->ctrl_interface);
7359 wpa_s->conf->ctrl_interface =
7360 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007361 if (!wpa_s->conf->ctrl_interface) {
7362 wpa_printf(MSG_ERROR,
7363 "Failed to duplicate control interface '%s'.",
7364 iface->ctrl_interface);
7365 return -1;
7366 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007367 }
7368
7369 if (iface->driver_param) {
7370 os_free(wpa_s->conf->driver_param);
7371 wpa_s->conf->driver_param =
7372 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007373 if (!wpa_s->conf->driver_param) {
7374 wpa_printf(MSG_ERROR,
7375 "Failed to duplicate driver param '%s'.",
7376 iface->driver_param);
7377 return -1;
7378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007379 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007380
7381 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7382 os_free(wpa_s->conf->ctrl_interface);
7383 wpa_s->conf->ctrl_interface = NULL;
7384 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007385 } else
7386 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7387 iface->driver_param);
7388
7389 if (wpa_s->conf == NULL) {
7390 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7391 return -1;
7392 }
7393
7394 if (iface->ifname == NULL) {
7395 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7396 return -1;
7397 }
7398 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7399 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7400 iface->ifname);
7401 return -1;
7402 }
7403 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007404#ifdef CONFIG_MATCH_IFACE
7405 wpa_s->matched = iface->matched;
7406#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007407
7408 if (iface->bridge_ifname) {
7409 if (os_strlen(iface->bridge_ifname) >=
7410 sizeof(wpa_s->bridge_ifname)) {
7411 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7412 "name '%s'.", iface->bridge_ifname);
7413 return -1;
7414 }
7415 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7416 sizeof(wpa_s->bridge_ifname));
7417 }
7418
7419 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007420 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7421 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007422
7423 /* Initialize driver interface and register driver event handler before
7424 * L2 receive handler so that association events are processed before
7425 * EAPOL-Key packets if both become available for the same select()
7426 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007427 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428 return -1;
7429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007430 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7431 return -1;
7432
7433 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7434 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7435 NULL);
7436 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7437
7438 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7439 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7440 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7441 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7442 "dot11RSNAConfigPMKLifetime");
7443 return -1;
7444 }
7445
7446 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7447 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7448 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7449 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7450 "dot11RSNAConfigPMKReauthThreshold");
7451 return -1;
7452 }
7453
7454 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7455 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7456 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7457 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7458 "dot11RSNAConfigSATimeout");
7459 return -1;
7460 }
7461
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007462 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
7463 wpa_s->conf->ft_prepend_pmkid);
7464
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007465 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7466 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007467 &wpa_s->hw.flags,
7468 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007469 if (wpa_s->hw.modes) {
7470 u16 i;
7471
7472 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7473 if (wpa_s->hw.modes[i].vht_capab) {
7474 wpa_s->hw_capab = CAPAB_VHT;
7475 break;
7476 }
7477
7478 if (wpa_s->hw.modes[i].ht_capab &
7479 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7480 wpa_s->hw_capab = CAPAB_HT40;
7481 else if (wpa_s->hw.modes[i].ht_capab &&
7482 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7483 wpa_s->hw_capab = CAPAB_HT;
7484 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007485 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007486 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007487
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007488 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7489 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007490 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007491 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007492 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007493 wpa_s->drv_enc = capa.enc;
Sunil Ravi7f769292024-07-23 22:21:32 +00007494 wpa_s->drv_key_mgmt = capa.key_mgmt;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007495 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007496 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007497 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007498 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007499 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007500 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7501 wpa_s->max_sched_scan_plan_interval =
7502 capa.max_sched_scan_plan_interval;
7503 wpa_s->max_sched_scan_plan_iterations =
7504 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007505 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7506 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007507 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7508 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007509 wpa_s->extended_capa = capa.extended_capa;
7510 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7511 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007512 wpa_s->num_multichan_concurrent =
7513 capa.num_multichan_concurrent;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007514#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007515 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007516#endif /* CONFIG_NO_WMM_AC */
Sunil Ravi89eba102022-09-13 21:04:37 -07007517 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007518
7519 if (capa.mac_addr_rand_scan_supported)
7520 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7521 if (wpa_s->sched_scan_supported &&
7522 capa.mac_addr_rand_sched_scan_supported)
7523 wpa_s->mac_addr_rand_supported |=
7524 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007525
7526 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7527 if (wpa_s->extended_capa &&
7528 wpa_s->extended_capa_len >= 3 &&
7529 wpa_s->extended_capa[2] & 0x40)
7530 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007531 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007532#ifdef CONFIG_PASN
7533 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7534#endif /* CONFIG_PASN */
Matthew Wang9ed1c792024-12-02 14:05:18 +00007535#ifndef CONFIG_NO_WPA
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007536 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7537 !!(wpa_s->drv_flags &
7538 WPA_DRIVER_FLAGS_BSS_SELECTION));
Matthew Wang9ed1c792024-12-02 14:05:18 +00007539#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007540 if (wpa_s->max_remain_on_chan == 0)
7541 wpa_s->max_remain_on_chan = 1000;
7542
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007543 /*
7544 * Only take p2p_mgmt parameters when P2P Device is supported.
7545 * Doing it here as it determines whether l2_packet_init() will be done
7546 * during wpa_supplicant_driver_init().
7547 */
7548 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7549 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007550
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007551 if (wpa_s->num_multichan_concurrent == 0)
7552 wpa_s->num_multichan_concurrent = 1;
7553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007554 if (wpa_supplicant_driver_init(wpa_s) < 0)
7555 return -1;
7556
7557#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007558 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007559 return -1;
7560#endif /* CONFIG_TDLS */
7561
7562 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7563 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7564 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7565 return -1;
7566 }
7567
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007568#ifdef CONFIG_FST
7569 if (wpa_s->conf->fst_group_id) {
7570 struct fst_iface_cfg cfg;
7571 struct fst_wpa_obj iface_obj;
7572
7573 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7574 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7575 sizeof(cfg.group_id));
7576 cfg.priority = wpa_s->conf->fst_priority;
7577 cfg.llt = wpa_s->conf->fst_llt;
7578
7579 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7580 &iface_obj, &cfg);
7581 if (!wpa_s->fst) {
7582 wpa_msg(wpa_s, MSG_ERROR,
7583 "FST: Cannot attach iface %s to group %s",
7584 wpa_s->ifname, cfg.group_id);
7585 return -1;
7586 }
7587 }
7588#endif /* CONFIG_FST */
7589
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007590 if (wpas_wps_init(wpa_s))
7591 return -1;
7592
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007593#ifdef CONFIG_GAS_SERVER
7594 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7595 if (!wpa_s->gas_server) {
7596 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7597 return -1;
7598 }
7599#endif /* CONFIG_GAS_SERVER */
7600
7601#ifdef CONFIG_DPP
7602 if (wpas_dpp_init(wpa_s) < 0)
7603 return -1;
7604#endif /* CONFIG_DPP */
7605
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007606#ifdef CONFIG_NAN_USD
7607 if (wpas_nan_usd_init(wpa_s) < 0)
7608 return -1;
7609#endif /* CONFIG_NAN_USD */
7610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007611 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7612 return -1;
7613 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7614
7615 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7616 if (wpa_s->ctrl_iface == NULL) {
7617 wpa_printf(MSG_ERROR,
7618 "Failed to initialize control interface '%s'.\n"
7619 "You may have another wpa_supplicant process "
7620 "already running or the file was\n"
7621 "left by an unclean termination of wpa_supplicant "
7622 "in which case you will need\n"
7623 "to manually remove this file before starting "
7624 "wpa_supplicant again.\n",
7625 wpa_s->conf->ctrl_interface);
7626 return -1;
7627 }
7628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007629 wpa_s->gas = gas_query_init(wpa_s);
7630 if (wpa_s->gas == NULL) {
7631 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7632 return -1;
7633 }
7634
Roshan Pius3a1667e2018-07-03 15:17:14 -07007635 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7636 wpa_s->p2p_mgmt) &&
7637 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007638 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7639 return -1;
7640 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007641
7642 if (wpa_bss_init(wpa_s) < 0)
7643 return -1;
7644
Paul Stewart092955c2017-02-06 09:13:09 -08007645#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7646#ifdef CONFIG_MESH
7647 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7648#endif /* CONFIG_MESH */
7649#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7650
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007651 /*
7652 * Set Wake-on-WLAN triggers, if configured.
7653 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7654 * have effect anyway when the interface is down).
7655 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007656 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007657 return -1;
7658
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007659#ifdef CONFIG_EAP_PROXY
7660{
7661 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007662 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7663 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007664 if (wpa_s->mnc_len > 0) {
7665 wpa_s->imsi[len] = '\0';
7666 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7667 wpa_s->imsi, wpa_s->mnc_len);
7668 } else {
7669 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7670 }
7671}
7672#endif /* CONFIG_EAP_PROXY */
7673
Dmitry Shmidt04949592012-07-19 12:16:46 -07007674 if (pcsc_reader_init(wpa_s) < 0)
7675 return -1;
7676
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007677 if (wpas_init_ext_pw(wpa_s) < 0)
7678 return -1;
7679
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007680#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007681 wpas_rrm_reset(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007682#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007683
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007684 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7685
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007686#ifdef CONFIG_HS20
7687 hs20_init(wpa_s);
7688#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007689#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007690 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007691 if ((wpa_s->conf->oce & OCE_STA) &&
7692 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7693 wpa_s->enable_oce = OCE_STA;
7694 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7695 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7696 /* TODO: Need to add STA-CFON support */
7697 wpa_printf(MSG_ERROR,
7698 "OCE STA-CFON feature is not yet supported");
7699 }
7700 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007701 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7702#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007703
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007704 wpa_supplicant_set_default_scan_ies(wpa_s);
7705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007706 return 0;
7707}
7708
7709
7710static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007711 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007712{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007713 struct wpa_global *global = wpa_s->global;
7714 struct wpa_supplicant *iface, *prev;
7715
Jimmy Chen0e73c002021-08-18 13:21:30 +08007716 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007717 wpas_p2p_group_remove(wpa_s, "*");
7718
7719 iface = global->ifaces;
7720 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007721 if (iface->p2pdev == wpa_s)
7722 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007723 if (iface == wpa_s || iface->parent != wpa_s) {
7724 iface = iface->next;
7725 continue;
7726 }
7727 wpa_printf(MSG_DEBUG,
7728 "Remove remaining child interface %s from parent %s",
7729 iface->ifname, wpa_s->ifname);
7730 prev = iface;
7731 iface = iface->next;
7732 wpa_supplicant_remove_iface(global, prev, terminate);
7733 }
7734
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007735 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007736 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007737 /*
7738 * Don't deauthenticate if WoWLAN is enable and not explicitly
7739 * been configured to disconnect.
7740 */
7741 if (!wpa_drv_get_wowlan(wpa_s) ||
7742 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007743 wpa_supplicant_deauthenticate(
7744 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007745
Hai Shalomfdcde762020-04-02 11:19:20 -07007746 wpa_drv_set_countermeasures(wpa_s, 0);
7747 wpa_clear_keys(wpa_s, NULL);
7748 } else {
7749 wpa_msg(wpa_s, MSG_INFO,
7750 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7751 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007752 }
7753
7754 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007755 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007756
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007757 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007758 radio_remove_interface(wpa_s);
7759
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007760#ifdef CONFIG_FST
7761 if (wpa_s->fst) {
7762 fst_detach(wpa_s->fst);
7763 wpa_s->fst = NULL;
7764 }
7765 if (wpa_s->received_mb_ies) {
7766 wpabuf_free(wpa_s->received_mb_ies);
7767 wpa_s->received_mb_ies = NULL;
7768 }
7769#endif /* CONFIG_FST */
7770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771 if (wpa_s->drv_priv)
7772 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007773
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007774 if (notify)
7775 wpas_notify_iface_removed(wpa_s);
7776
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007777 if (terminate)
7778 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007779
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007780 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7781 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007782
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007783#ifdef CONFIG_MESH
7784 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007785 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007786 wpa_s->ifmsh = NULL;
7787 }
7788#endif /* CONFIG_MESH */
7789
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007790 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007791 wpa_config_free(wpa_s->conf);
7792 wpa_s->conf = NULL;
7793 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007794
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007795 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007796 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007797
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007798 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007799}
7800
7801
Dmitry Shmidte4663042016-04-04 10:07:49 -07007802#ifdef CONFIG_MATCH_IFACE
7803
7804/**
7805 * wpa_supplicant_match_iface - Match an interface description to a name
7806 * @global: Pointer to global data from wpa_supplicant_init()
7807 * @ifname: Name of the interface to match
7808 * Returns: Pointer to the created interface description or %NULL on failure
7809 */
7810struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7811 const char *ifname)
7812{
7813 int i;
7814 struct wpa_interface *iface, *miface;
7815
7816 for (i = 0; i < global->params.match_iface_count; i++) {
7817 miface = &global->params.match_ifaces[i];
7818 if (!miface->ifname ||
7819 fnmatch(miface->ifname, ifname, 0) == 0) {
7820 iface = os_zalloc(sizeof(*iface));
7821 if (!iface)
7822 return NULL;
7823 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007824 if (!miface->ifname)
7825 iface->matched = WPA_IFACE_MATCHED_NULL;
7826 else
7827 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007828 iface->ifname = ifname;
7829 return iface;
7830 }
7831 }
7832
7833 return NULL;
7834}
7835
7836
7837/**
7838 * wpa_supplicant_match_existing - Match existing interfaces
7839 * @global: Pointer to global data from wpa_supplicant_init()
7840 * Returns: 0 on success, -1 on failure
7841 */
7842static int wpa_supplicant_match_existing(struct wpa_global *global)
7843{
7844 struct if_nameindex *ifi, *ifp;
7845 struct wpa_supplicant *wpa_s;
7846 struct wpa_interface *iface;
7847
7848 ifp = if_nameindex();
7849 if (!ifp) {
7850 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7851 return -1;
7852 }
7853
7854 for (ifi = ifp; ifi->if_name; ifi++) {
7855 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7856 if (wpa_s)
7857 continue;
7858 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7859 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007860 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007861 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007862 }
7863 }
7864
7865 if_freenameindex(ifp);
7866 return 0;
7867}
7868
7869#endif /* CONFIG_MATCH_IFACE */
7870
7871
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007872/**
7873 * wpa_supplicant_add_iface - Add a new network interface
7874 * @global: Pointer to global data from wpa_supplicant_init()
7875 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007876 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007877 * Returns: Pointer to the created interface or %NULL on failure
7878 *
7879 * This function is used to add new network interfaces for %wpa_supplicant.
7880 * This can be called before wpa_supplicant_run() to add interfaces before the
7881 * main event loop has been started. In addition, new interfaces can be added
7882 * dynamically while %wpa_supplicant is already running. This could happen,
7883 * e.g., when a hotplug network adapter is inserted.
7884 */
7885struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007886 struct wpa_interface *iface,
7887 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007888{
7889 struct wpa_supplicant *wpa_s;
7890 struct wpa_interface t_iface;
7891 struct wpa_ssid *ssid;
7892
7893 if (global == NULL || iface == NULL)
7894 return NULL;
7895
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007896 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007897 if (wpa_s == NULL)
7898 return NULL;
7899
7900 wpa_s->global = global;
7901
7902 t_iface = *iface;
7903 if (global->params.override_driver) {
7904 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7905 "('%s' -> '%s')",
7906 iface->driver, global->params.override_driver);
7907 t_iface.driver = global->params.override_driver;
7908 }
7909 if (global->params.override_ctrl_interface) {
7910 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7911 "ctrl_interface ('%s' -> '%s')",
7912 iface->ctrl_interface,
7913 global->params.override_ctrl_interface);
7914 t_iface.ctrl_interface =
7915 global->params.override_ctrl_interface;
7916 }
7917 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7918 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7919 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007920 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007921 return NULL;
7922 }
7923
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007924 /* Notify the control interfaces about new iface */
7925 if (wpas_notify_iface_added(wpa_s)) {
7926 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7927 return NULL;
7928 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007929
Jimmy Chene2206be2022-07-10 10:25:21 +08007930 /* Notify the control interfaces about new networks */
7931 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7932 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007933 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007934 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7935 && os_strncmp((const char *) ssid->ssid,
7936 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7937 wpas_notify_persistent_group_added(wpa_s, ssid);
7938 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007939 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007940
7941 wpa_s->next = global->ifaces;
7942 global->ifaces = wpa_s;
7943
7944 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007945 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007946
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007947#ifdef CONFIG_P2P
7948 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007949 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007950 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007951 wpas_p2p_add_p2pdev_interface(
7952 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007953 wpa_printf(MSG_INFO,
7954 "P2P: Failed to enable P2P Device interface");
7955 /* Try to continue without. P2P will be disabled. */
7956 }
7957#endif /* CONFIG_P2P */
7958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007959 return wpa_s;
7960}
7961
7962
7963/**
7964 * wpa_supplicant_remove_iface - Remove a network interface
7965 * @global: Pointer to global data from wpa_supplicant_init()
7966 * @wpa_s: Pointer to the network interface to be removed
7967 * Returns: 0 if interface was removed, -1 if interface was not found
7968 *
7969 * This function can be used to dynamically remove network interfaces from
7970 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7971 * addition, this function is used to remove all remaining interfaces when
7972 * %wpa_supplicant is terminated.
7973 */
7974int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007975 struct wpa_supplicant *wpa_s,
7976 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007977{
7978 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007979#ifdef CONFIG_MESH
7980 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7981 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007982 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007983#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007984
7985 /* Remove interface from the global list of interfaces */
7986 prev = global->ifaces;
7987 if (prev == wpa_s) {
7988 global->ifaces = wpa_s->next;
7989 } else {
7990 while (prev && prev->next != wpa_s)
7991 prev = prev->next;
7992 if (prev == NULL)
7993 return -1;
7994 prev->next = wpa_s->next;
7995 }
7996
7997 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7998
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007999#ifdef CONFIG_MESH
8000 if (mesh_if_created) {
8001 ifname = os_strdup(wpa_s->ifname);
8002 if (ifname == NULL) {
8003 wpa_dbg(wpa_s, MSG_ERROR,
8004 "mesh: Failed to malloc ifname");
8005 return -1;
8006 }
8007 }
8008#endif /* CONFIG_MESH */
8009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008010 if (global->p2p_group_formation == wpa_s)
8011 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008012 if (global->p2p_invite_group == wpa_s)
8013 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008014 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008015
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008016#ifdef CONFIG_MESH
8017 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008018 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008019 os_free(ifname);
8020 }
8021#endif /* CONFIG_MESH */
8022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008023 return 0;
8024}
8025
8026
8027/**
8028 * wpa_supplicant_get_eap_mode - Get the current EAP mode
8029 * @wpa_s: Pointer to the network interface
8030 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
8031 */
8032const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
8033{
8034 const char *eapol_method;
8035
8036 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
8037 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
8038 return "NO-EAP";
8039 }
8040
8041 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
8042 if (eapol_method == NULL)
8043 return "UNKNOWN-EAP";
8044
8045 return eapol_method;
8046}
8047
8048
8049/**
8050 * wpa_supplicant_get_iface - Get a new network interface
8051 * @global: Pointer to global data from wpa_supplicant_init()
8052 * @ifname: Interface name
8053 * Returns: Pointer to the interface or %NULL if not found
8054 */
8055struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
8056 const char *ifname)
8057{
8058 struct wpa_supplicant *wpa_s;
8059
8060 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8061 if (os_strcmp(wpa_s->ifname, ifname) == 0)
8062 return wpa_s;
8063 }
8064 return NULL;
8065}
8066
8067
8068#ifndef CONFIG_NO_WPA_MSG
8069static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
8070{
8071 struct wpa_supplicant *wpa_s = ctx;
8072 if (wpa_s == NULL)
8073 return NULL;
8074 return wpa_s->ifname;
8075}
8076#endif /* CONFIG_NO_WPA_MSG */
8077
8078
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008079#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
8080#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
8081#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
8082
8083/* Periodic cleanup tasks */
8084static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
8085{
8086 struct wpa_global *global = eloop_ctx;
8087 struct wpa_supplicant *wpa_s;
8088
8089 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8090 wpas_periodic, global, NULL);
8091
8092#ifdef CONFIG_P2P
8093 if (global->p2p)
8094 p2p_expire_peers(global->p2p);
8095#endif /* CONFIG_P2P */
8096
8097 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8098 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
8099#ifdef CONFIG_AP
8100 ap_periodic(wpa_s);
8101#endif /* CONFIG_AP */
8102 }
8103}
8104
8105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008106/**
8107 * wpa_supplicant_init - Initialize %wpa_supplicant
8108 * @params: Parameters for %wpa_supplicant
8109 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
8110 *
8111 * This function is used to initialize %wpa_supplicant. After successful
8112 * initialization, the returned data pointer can be used to add and remove
8113 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
8114 */
8115struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
8116{
8117 struct wpa_global *global;
8118 int ret, i;
8119
8120 if (params == NULL)
8121 return NULL;
8122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008123#ifdef CONFIG_DRIVER_NDIS
8124 {
8125 void driver_ndis_init_ops(void);
8126 driver_ndis_init_ops();
8127 }
8128#endif /* CONFIG_DRIVER_NDIS */
8129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008130#ifndef CONFIG_NO_WPA_MSG
8131 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
8132#endif /* CONFIG_NO_WPA_MSG */
8133
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008134 if (params->wpa_debug_file_path)
8135 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07008136 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008137 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008138 if (params->wpa_debug_syslog)
8139 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008140 if (params->wpa_debug_tracing) {
8141 ret = wpa_debug_open_linux_tracing();
8142 if (ret) {
8143 wpa_printf(MSG_ERROR,
8144 "Failed to enable trace logging");
8145 return NULL;
8146 }
8147 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008148
8149 ret = eap_register_methods();
8150 if (ret) {
8151 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
8152 if (ret == -2)
8153 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
8154 "the same EAP type.");
8155 return NULL;
8156 }
8157
8158 global = os_zalloc(sizeof(*global));
8159 if (global == NULL)
8160 return NULL;
8161 dl_list_init(&global->p2p_srv_bonjour);
8162 dl_list_init(&global->p2p_srv_upnp);
8163 global->params.daemonize = params->daemonize;
8164 global->params.wait_for_monitor = params->wait_for_monitor;
8165 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008166
8167 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008168 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008169 if (!global->params.pid_file) {
8170 wpa_supplicant_deinit(global);
8171 return NULL;
8172 }
8173 }
8174
8175 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008176 global->params.ctrl_interface =
8177 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008178 if (!global->params.ctrl_interface) {
8179 wpa_supplicant_deinit(global);
8180 return NULL;
8181 }
8182 }
8183
8184 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008185 global->params.ctrl_interface_group =
8186 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008187 if (!global->params.ctrl_interface_group) {
8188 wpa_supplicant_deinit(global);
8189 return NULL;
8190 }
8191 }
8192
8193 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008194 global->params.override_driver =
8195 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008196 if (!global->params.override_driver) {
8197 wpa_supplicant_deinit(global);
8198 return NULL;
8199 }
8200 }
8201
8202 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008203 global->params.override_ctrl_interface =
8204 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008205 if (!global->params.override_ctrl_interface) {
8206 wpa_supplicant_deinit(global);
8207 return NULL;
8208 }
8209 }
8210
Dmitry Shmidte4663042016-04-04 10:07:49 -07008211#ifdef CONFIG_MATCH_IFACE
8212 global->params.match_iface_count = params->match_iface_count;
8213 if (params->match_iface_count) {
8214 global->params.match_ifaces =
8215 os_calloc(params->match_iface_count,
8216 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00008217 if (!global->params.match_ifaces) {
8218 wpa_printf(MSG_ERROR,
8219 "Failed to allocate match interfaces");
8220 wpa_supplicant_deinit(global);
8221 return NULL;
8222 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07008223 os_memcpy(global->params.match_ifaces,
8224 params->match_ifaces,
8225 params->match_iface_count *
8226 sizeof(struct wpa_interface));
8227 }
8228#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008229#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00008230 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008231 global->params.conf_p2p_dev =
8232 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008233 if (!global->params.conf_p2p_dev) {
8234 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
8235 wpa_supplicant_deinit(global);
8236 return NULL;
8237 }
8238 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008239#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008240 wpa_debug_level = global->params.wpa_debug_level =
8241 params->wpa_debug_level;
8242 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
8243 params->wpa_debug_show_keys;
8244 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
8245 params->wpa_debug_timestamp;
8246
Hai Shalomfdcde762020-04-02 11:19:20 -07008247 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008248
8249 if (eloop_init()) {
8250 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
8251 wpa_supplicant_deinit(global);
8252 return NULL;
8253 }
8254
Jouni Malinen75ecf522011-06-27 15:19:46 -07008255 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008256
8257 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
8258 if (global->ctrl_iface == NULL) {
8259 wpa_supplicant_deinit(global);
8260 return NULL;
8261 }
8262
8263 if (wpas_notify_supplicant_initialized(global)) {
8264 wpa_supplicant_deinit(global);
8265 return NULL;
8266 }
8267
8268 for (i = 0; wpa_drivers[i]; i++)
8269 global->drv_count++;
8270 if (global->drv_count == 0) {
8271 wpa_printf(MSG_ERROR, "No drivers enabled");
8272 wpa_supplicant_deinit(global);
8273 return NULL;
8274 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008275 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008276 if (global->drv_priv == NULL) {
8277 wpa_supplicant_deinit(global);
8278 return NULL;
8279 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008280
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008281#ifdef CONFIG_WIFI_DISPLAY
8282 if (wifi_display_init(global) < 0) {
8283 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
8284 wpa_supplicant_deinit(global);
8285 return NULL;
8286 }
8287#endif /* CONFIG_WIFI_DISPLAY */
8288
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008289 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8290 wpas_periodic, global, NULL);
8291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008292 return global;
8293}
8294
8295
8296/**
8297 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8298 * @global: Pointer to global data from wpa_supplicant_init()
8299 * Returns: 0 after successful event loop run, -1 on failure
8300 *
8301 * This function starts the main event loop and continues running as long as
8302 * there are any remaining events. In most cases, this function is running as
8303 * long as the %wpa_supplicant process in still in use.
8304 */
8305int wpa_supplicant_run(struct wpa_global *global)
8306{
8307 struct wpa_supplicant *wpa_s;
8308
8309 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008310 (wpa_supplicant_daemon(global->params.pid_file) ||
8311 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008312 return -1;
8313
Dmitry Shmidte4663042016-04-04 10:07:49 -07008314#ifdef CONFIG_MATCH_IFACE
8315 if (wpa_supplicant_match_existing(global))
8316 return -1;
8317#endif
8318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008319 if (global->params.wait_for_monitor) {
8320 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008321 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008322 wpa_supplicant_ctrl_iface_wait(
8323 wpa_s->ctrl_iface);
8324 }
8325
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008326#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008327 // If daemonize is enabled, initialize AIDL here.
8328 if (global->params.daemonize) {
8329 global->aidl = wpas_aidl_init(global);
8330 if (!global->aidl)
8331 return -1;
8332 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008333#endif /* CONFIG_AIDL */
8334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008335 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8336 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8337
8338 eloop_run();
8339
8340 return 0;
8341}
8342
8343
8344/**
8345 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8346 * @global: Pointer to global data from wpa_supplicant_init()
8347 *
8348 * This function is called to deinitialize %wpa_supplicant and to free all
8349 * allocated resources. Remaining network interfaces will also be removed.
8350 */
8351void wpa_supplicant_deinit(struct wpa_global *global)
8352{
8353 int i;
8354
8355 if (global == NULL)
8356 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008357
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008358 eloop_cancel_timeout(wpas_periodic, global, NULL);
8359
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008360#ifdef CONFIG_WIFI_DISPLAY
8361 wifi_display_deinit(global);
8362#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008363
8364 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008365 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008366
8367 if (global->ctrl_iface)
8368 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8369
8370 wpas_notify_supplicant_deinitialized(global);
8371
8372 eap_peer_unregister_methods();
8373#ifdef CONFIG_AP
8374 eap_server_unregister_methods();
8375#endif /* CONFIG_AP */
8376
8377 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8378 if (!global->drv_priv[i])
8379 continue;
8380 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8381 }
8382 os_free(global->drv_priv);
8383
8384 random_deinit();
8385
8386 eloop_destroy();
8387
8388 if (global->params.pid_file) {
8389 os_daemonize_terminate(global->params.pid_file);
8390 os_free(global->params.pid_file);
8391 }
8392 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008393 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008394 os_free(global->params.override_driver);
8395 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008396#ifdef CONFIG_MATCH_IFACE
8397 os_free(global->params.match_ifaces);
8398#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008399#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008400 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008401#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008402
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008403 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008404 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008405 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008407 os_free(global);
8408 wpa_debug_close_syslog();
8409 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008410 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008411}
8412
8413
8414void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8415{
8416 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8417 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8418 char country[3];
8419 country[0] = wpa_s->conf->country[0];
8420 country[1] = wpa_s->conf->country[1];
8421 country[2] = '\0';
8422 if (wpa_drv_set_country(wpa_s, country) < 0) {
8423 wpa_printf(MSG_ERROR, "Failed to set country code "
8424 "'%s'", country);
8425 }
8426 }
8427
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008428 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8429 wpas_init_ext_pw(wpa_s);
8430
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008431 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8432 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8433
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008434 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8435 struct wpa_driver_capa capa;
8436 int res = wpa_drv_get_capa(wpa_s, &capa);
8437
8438 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8439 wpa_printf(MSG_ERROR,
8440 "Failed to update wowlan_triggers to '%s'",
8441 wpa_s->conf->wowlan_triggers);
8442 }
8443
Hai Shalom81f62d82019-07-22 12:10:00 -07008444 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8445 wpa_supplicant_set_default_scan_ies(wpa_s);
8446
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008447 if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
8448 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
8449 wpa_s->conf->ft_prepend_pmkid);
8450
Hai Shalom899fcc72020-10-19 14:38:18 -07008451#ifdef CONFIG_BGSCAN
8452 /*
8453 * We default to global bgscan parameters only when per-network bgscan
8454 * parameters aren't set. Only bother resetting bgscan parameters if
8455 * this is the case.
8456 */
8457 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8458 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8459 wpa_s->wpa_state == WPA_COMPLETED)
8460 wpa_supplicant_reset_bgscan(wpa_s);
8461#endif /* CONFIG_BGSCAN */
8462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008463#ifdef CONFIG_WPS
8464 wpas_wps_update_config(wpa_s);
8465#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008466 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008467 wpa_s->conf->changed_parameters = 0;
8468}
8469
8470
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008471void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008472{
8473 int i;
8474
8475 for (i = 0; i < *num_freqs; i++) {
8476 if (freqs[i] == freq)
8477 return;
8478 }
8479
8480 freqs[*num_freqs] = freq;
8481 (*num_freqs)++;
8482}
8483
8484
8485static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8486{
8487 struct wpa_bss *bss, *cbss;
8488 const int max_freqs = 10;
8489 int *freqs;
8490 int num_freqs = 0;
8491
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008492 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008493 if (freqs == NULL)
8494 return NULL;
8495
8496 cbss = wpa_s->current_bss;
8497
8498 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8499 if (bss == cbss)
8500 continue;
8501 if (bss->ssid_len == cbss->ssid_len &&
8502 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008503 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008504 add_freq(freqs, &num_freqs, bss->freq);
8505 if (num_freqs == max_freqs)
8506 break;
8507 }
8508 }
8509
8510 if (num_freqs == 0) {
8511 os_free(freqs);
8512 freqs = NULL;
8513 }
8514
8515 return freqs;
8516}
8517
8518
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008519void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
8520 const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008521{
8522 int timeout;
8523 int count;
8524 int *freqs = NULL;
8525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008526 wpas_connect_work_done(wpa_s);
8527
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008528 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008529 * Remove possible authentication timeout since the connection failed.
8530 */
8531 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8532
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008533 /*
Hai Shalom60840252021-02-19 19:02:11 -08008534 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008535 * generated based on local request to disconnect.
8536 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008537 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008538 wpa_s->own_disconnect_req = 0;
8539 wpa_dbg(wpa_s, MSG_DEBUG,
8540 "Ignore connection failure due to local request to disconnect");
8541 return;
8542 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008543 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008544 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8545 "indication since interface has been put into "
8546 "disconnected state");
8547 return;
8548 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008549 if (wpa_s->auto_reconnect_disabled) {
8550 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8551 "indication since auto connect is disabled");
8552 return;
8553 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008554
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008555 /* Also mark links as failed */
8556 while (link_bssids && *link_bssids) {
8557 wpa_bssid_ignore_add(wpa_s, *link_bssids);
8558 link_bssids++;
8559 }
8560
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008561 /*
Hai Shalom60840252021-02-19 19:02:11 -08008562 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008563 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008564 */
Hai Shalom60840252021-02-19 19:02:11 -08008565 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008566 if (count == 1 && wpa_s->current_bss) {
8567 /*
Hai Shalom60840252021-02-19 19:02:11 -08008568 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008569 * another BSS available for the same ESS, we should try that
8570 * next. Otherwise, we may as well try this one once more
8571 * before allowing other, likely worse, ESSes to be considered.
8572 */
8573 freqs = get_bss_freqs_in_ess(wpa_s);
8574 if (freqs) {
8575 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8576 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008577 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008578 /*
8579 * On the next scan, go through only the known channels
8580 * used in this ESS based on previous scans to speed up
8581 * common load balancing use case.
8582 */
8583 os_free(wpa_s->next_scan_freqs);
8584 wpa_s->next_scan_freqs = freqs;
8585 }
8586 }
8587
Hai Shalom899fcc72020-10-19 14:38:18 -07008588 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008589
Hai Shalom899fcc72020-10-19 14:38:18 -07008590 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008591 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8592 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008593 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008594 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008595 /*
8596 * Multiple consecutive connection failures mean that other APs are
8597 * either not available or have already been tried, so we can start
8598 * increasing the delay here to avoid constant scanning.
8599 */
8600 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008601 case 1:
8602 timeout = 100;
8603 break;
8604 case 2:
8605 timeout = 500;
8606 break;
8607 case 3:
8608 timeout = 1000;
8609 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008610 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008611 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008612 break;
8613 default:
8614 timeout = 10000;
8615 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008616 }
8617
Hai Shalom899fcc72020-10-19 14:38:18 -07008618 wpa_dbg(wpa_s, MSG_DEBUG,
8619 "Consecutive connection failures: %d --> request scan in %d ms",
8620 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008622 /*
8623 * TODO: if more than one possible AP is available in scan results,
8624 * could try the other ones before requesting a new scan.
8625 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008626
8627 /* speed up the connection attempt with normal scan */
8628 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008629 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8630 1000 * (timeout % 1000));
8631}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008632
8633
Hai Shalomce48b4a2018-09-05 11:41:35 -07008634#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008635
8636void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8637{
8638 struct wpa_ssid *ssid = wpa_s->current_ssid;
8639 const u8 *realm, *username, *rrk;
8640 size_t realm_len, username_len, rrk_len;
8641 u16 next_seq_num;
8642
8643 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8644 * Check for ERP keys existing to limit when this can be done since
8645 * the rejection response is not protected and such triggers should
8646 * really not allow internal state to be modified unless required to
8647 * avoid significant issues in functionality. In addition, drop
8648 * externally configure PMKSA entries even without ERP keys since it
8649 * is possible for an external component to add PMKSA entries for FILS
8650 * authentication without restoring previously generated ERP keys.
8651 *
8652 * In this case, this is needed to allow recovery from cases where the
8653 * AP or authentication server has dropped PMKSAs and ERP keys. */
8654 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8655 return;
8656
8657 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8658 &username, &username_len,
8659 &realm, &realm_len, &next_seq_num,
8660 &rrk, &rrk_len) != 0 ||
8661 !realm) {
8662 wpa_dbg(wpa_s, MSG_DEBUG,
8663 "FILS: Drop external PMKSA cache entry");
8664 wpa_sm_aborted_external_cached(wpa_s->wpa);
8665 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8666 return;
8667 }
8668
8669 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8670 wpa_sm_aborted_cached(wpa_s->wpa);
8671 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8672}
8673
8674
Hai Shalomce48b4a2018-09-05 11:41:35 -07008675void fils_connection_failure(struct wpa_supplicant *wpa_s)
8676{
8677 struct wpa_ssid *ssid = wpa_s->current_ssid;
8678 const u8 *realm, *username, *rrk;
8679 size_t realm_len, username_len, rrk_len;
8680 u16 next_seq_num;
8681
8682 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8683 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8684 &username, &username_len,
8685 &realm, &realm_len, &next_seq_num,
8686 &rrk, &rrk_len) != 0 ||
8687 !realm)
8688 return;
8689
8690 wpa_hexdump_ascii(MSG_DEBUG,
8691 "FILS: Store last connection failure realm",
8692 realm, realm_len);
8693 os_free(wpa_s->last_con_fail_realm);
8694 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8695 if (wpa_s->last_con_fail_realm) {
8696 wpa_s->last_con_fail_realm_len = realm_len;
8697 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8698 }
8699}
8700#endif /* CONFIG_FILS */
8701
8702
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008703int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8704{
8705 return wpa_s->conf->ap_scan == 2 ||
8706 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8707}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008708
Dmitry Shmidt04949592012-07-19 12:16:46 -07008709
Sunil Ravi7f769292024-07-23 22:21:32 +00008710static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
8711{
8712 return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
8713}
8714
8715
8716bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
8717{
8718 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
8719 return false;
8720
8721 if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
8722 return true;
8723
8724 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
8725 wpas_driver_bss_selection(wpa_s))
8726 return wpas_driver_rsn_override(wpa_s);
8727
8728 return true;
8729}
8730
8731
Gabriel Biren57ededa2021-09-03 16:08:50 +00008732#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008733int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8734 struct wpa_ssid *ssid,
8735 const char *field,
8736 const char *value)
8737{
8738#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008739 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008740
8741 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8742 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8743 (const u8 *) value, os_strlen(value));
8744
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008745 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008746 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008747#else /* IEEE8021X_EAPOL */
8748 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8749 return -1;
8750#endif /* IEEE8021X_EAPOL */
8751}
8752
8753int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8754 struct wpa_ssid *ssid,
8755 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008756 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008757{
8758#ifdef IEEE8021X_EAPOL
8759 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008760 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008761
8762 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008763 case WPA_CTRL_REQ_EAP_IDENTITY:
8764 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008765 os_free(eap->imsi_identity);
8766 if (value == NULL)
8767 return -1;
8768 identity = os_strchr(value, ':');
8769 if (identity == NULL) {
8770 /* plain identity */
8771 eap->identity = (u8 *)os_strdup(value);
8772 eap->identity_len = os_strlen(value);
8773 } else {
8774 /* have both plain identity and encrypted identity */
8775 imsi_identity = value;
8776 *identity++ = '\0';
8777 /* plain identity */
8778 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8779 eap->imsi_identity_len = strlen(imsi_identity);
8780 /* encrypted identity */
8781 eap->identity = (u8 *)dup_binstr(identity,
8782 value_len - strlen(imsi_identity) - 1);
8783 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8784 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008785 eap->pending_req_identity = 0;
8786 if (ssid == wpa_s->current_ssid)
8787 wpa_s->reassociate = 1;
8788 break;
8789 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008790 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008791 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008792 if (!eap->password)
8793 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008794 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008795 eap->pending_req_password = 0;
8796 if (ssid == wpa_s->current_ssid)
8797 wpa_s->reassociate = 1;
8798 break;
8799 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008800 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008801 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008802 if (!eap->new_password)
8803 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008804 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008805 eap->pending_req_new_password = 0;
8806 if (ssid == wpa_s->current_ssid)
8807 wpa_s->reassociate = 1;
8808 break;
8809 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008810 str_clear_free(eap->cert.pin);
8811 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008812 if (!eap->cert.pin)
8813 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008814 eap->pending_req_pin = 0;
8815 if (ssid == wpa_s->current_ssid)
8816 wpa_s->reassociate = 1;
8817 break;
8818 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008819 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008820 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008821 if (!eap->otp)
8822 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008823 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008824 os_free(eap->pending_req_otp);
8825 eap->pending_req_otp = NULL;
8826 eap->pending_req_otp_len = 0;
8827 break;
8828 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008829 str_clear_free(eap->cert.private_key_passwd);
8830 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008831 if (!eap->cert.private_key_passwd)
8832 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008833 eap->pending_req_passphrase = 0;
8834 if (ssid == wpa_s->current_ssid)
8835 wpa_s->reassociate = 1;
8836 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008837 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008838 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008839 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008840 if (!eap->external_sim_resp)
8841 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008842 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008843 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008844 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8845 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8846 return -1;
8847 ssid->mem_only_psk = 1;
8848 if (ssid->passphrase)
8849 wpa_config_update_psk(ssid);
8850 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8851 wpa_supplicant_req_scan(wpa_s, 0, 0);
8852 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008853 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8854 if (eap->pending_ext_cert_check != PENDING_CHECK)
8855 return -1;
8856 if (os_strcmp(value, "good") == 0)
8857 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8858 else if (os_strcmp(value, "bad") == 0)
8859 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8860 else
8861 return -1;
8862 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008863 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008864 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008865 return -1;
8866 }
8867
8868 return 0;
8869#else /* IEEE8021X_EAPOL */
8870 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8871 return -1;
8872#endif /* IEEE8021X_EAPOL */
8873}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008874#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008875
8876
8877int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8878{
Hai Shalomfdcde762020-04-02 11:19:20 -07008879#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008880 int i;
8881 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008882#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008883
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008884 if (wpa_s->p2p_mgmt)
8885 return 1; /* no normal network profiles on p2p_mgmt interface */
8886
Dmitry Shmidt04949592012-07-19 12:16:46 -07008887 if (ssid == NULL)
8888 return 1;
8889
8890 if (ssid->disabled)
8891 return 1;
8892
Hai Shalomfdcde762020-04-02 11:19:20 -07008893#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008894 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008895 drv_enc = wpa_s->drv_enc;
8896 else
8897 drv_enc = (unsigned int) -1;
8898
8899 for (i = 0; i < NUM_WEP_KEYS; i++) {
8900 size_t len = ssid->wep_key_len[i];
8901 if (len == 0)
8902 continue;
8903 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8904 continue;
8905 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8906 continue;
8907 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8908 continue;
8909 return 1; /* invalid WEP key */
8910 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008911#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008912
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008913 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008914 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008915 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008916 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008917 return 1;
8918
Sunil Ravi89eba102022-09-13 21:04:37 -07008919#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008920#ifdef CRYPTO_RSA_OAEP_SHA256
8921 if (ssid->eap.imsi_privacy_cert) {
8922 struct crypto_rsa_key *key;
8923 bool failed = false;
8924
8925 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8926 if (!key)
8927 failed = true;
8928 crypto_rsa_key_free(key);
8929 if (failed) {
8930 wpa_printf(MSG_DEBUG,
8931 "Invalid imsi_privacy_cert (%s) - disable network",
8932 ssid->eap.imsi_privacy_cert);
8933 return 1;
8934 }
8935 }
8936#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008937#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008938
Dmitry Shmidt04949592012-07-19 12:16:46 -07008939 return 0;
8940}
8941
8942
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008943int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8944{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008945 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8946 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8947 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8948 /*
8949 * Driver does not support BIP -- ignore pmf=1 default
8950 * since the connection with PMF would fail and the
8951 * configuration does not require PMF to be enabled.
8952 */
8953 return NO_MGMT_FRAME_PROTECTION;
8954 }
8955
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008956 if (ssid &&
8957 (ssid->key_mgmt &
8958 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8959 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8960 /*
8961 * Do not use the default PMF value for non-RSN networks
8962 * since PMF is available only with RSN and pmf=2
8963 * configuration would otherwise prevent connections to
8964 * all open networks.
8965 */
8966 return NO_MGMT_FRAME_PROTECTION;
8967 }
8968
Sunil Ravi77d572f2023-01-17 23:58:31 +00008969#ifdef CONFIG_OCV
8970 /* Enable PMF if OCV is being enabled */
8971 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8972 ssid && ssid->ocv)
8973 return MGMT_FRAME_PROTECTION_OPTIONAL;
8974#endif /* CONFIG_OCV */
8975
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008976 return wpa_s->conf->pmf;
8977 }
8978
8979 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008980}
8981
8982
Sunil Ravi77d572f2023-01-17 23:58:31 +00008983#ifdef CONFIG_SAE
8984bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8985 struct wpa_ssid *ssid,
8986 const struct wpa_ie_data *ie)
8987{
8988 return wpa_s->conf->sae_check_mfp &&
8989 (!(ie->capabilities &
8990 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8991 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8992}
8993#endif /* CONFIG_SAE */
8994
8995
Hai Shalomc1a21442022-02-04 13:43:00 -08008996int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8997{
8998 if (wpa_s->current_ssid == NULL ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008999 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
Hai Shalomc1a21442022-02-04 13:43:00 -08009000 return 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009001 if (wpa_s->valid_links) {
9002 if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
9003 !wpas_ap_link_address(wpa_s, addr))
9004 return 0;
9005 } else {
9006 if (!ether_addr_equal(addr, wpa_s->bssid))
9007 return 0;
9008 }
Hai Shalomc1a21442022-02-04 13:43:00 -08009009 return wpa_sm_pmf_enabled(wpa_s->wpa);
9010}
9011
9012
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009013int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009014{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07009015 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009016 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07009017 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009018 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07009019 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009020}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009021
9022
Sunil Ravi77d572f2023-01-17 23:58:31 +00009023void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
9024 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009025{
9026 struct wpa_ssid *ssid = wpa_s->current_ssid;
9027 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009028 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009029
9030 if (ssid == NULL) {
9031 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
9032 "SSID block");
9033 return;
9034 }
9035
9036 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
9037 return;
9038
9039 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07009040
9041#ifdef CONFIG_P2P
9042 if (ssid->p2p_group &&
9043 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
9044 /*
9045 * Skip the wait time since there is a short timeout on the
9046 * connection to a P2P group.
9047 */
9048 return;
9049 }
9050#endif /* CONFIG_P2P */
9051
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009052 if (ssid->auth_failures > 50)
9053 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009054 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009055 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009056 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009057 dur = 90;
9058 else if (ssid->auth_failures > 3)
9059 dur = 60;
9060 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009061 dur = 30;
9062 else if (ssid->auth_failures > 1)
9063 dur = 20;
9064 else
9065 dur = 10;
9066
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009067 if (ssid->auth_failures > 1 &&
9068 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
9069 dur += os_random() % (ssid->auth_failures * 10);
9070
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009071 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009072 if (now.sec + dur <= ssid->disabled_until.sec)
9073 return;
9074
9075 ssid->disabled_until.sec = now.sec + dur;
9076
9077 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009078 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009079 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009080 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009081
9082 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
9083 int msg_len = snprintf(NULL, 0, format_str,
9084 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9085 ssid->auth_failures, dur, reason) + 1;
9086 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05309087 if (!msg)
9088 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00009089 snprintf(msg, msg_len, format_str,
9090 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
9091 ssid->auth_failures, dur, reason);
9092 wpas_notify_ssid_temp_disabled(wpa_s, msg);
9093 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009094
9095 if (bssid)
9096 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009097}
9098
9099
9100void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
9101 struct wpa_ssid *ssid, int clear_failures)
9102{
9103 if (ssid == NULL)
9104 return;
9105
9106 if (ssid->disabled_until.sec) {
9107 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
9108 "id=%d ssid=\"%s\"",
9109 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
9110 }
9111 ssid->disabled_until.sec = 0;
9112 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009113 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009114 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00009115 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
9116 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
9117 " ignored to allow a lower priority BSS, if any, to be tried next",
9118 MAC2STR(ssid->disabled_due_to));
9119 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
9120 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
9121 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009122}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009123
9124
9125int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
9126{
9127 size_t i;
9128
9129 if (wpa_s->disallow_aps_bssid == NULL)
9130 return 0;
9131
9132 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009133 if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
9134 bssid))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009135 return 1;
9136 }
9137
9138 return 0;
9139}
9140
9141
9142int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
9143 size_t ssid_len)
9144{
9145 size_t i;
9146
9147 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
9148 return 0;
9149
9150 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
9151 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
9152 if (ssid_len == s->ssid_len &&
9153 os_memcmp(ssid, s->ssid, ssid_len) == 0)
9154 return 1;
9155 }
9156
9157 return 0;
9158}
9159
9160
9161/**
9162 * wpas_request_connection - Request a new connection
9163 * @wpa_s: Pointer to the network interface
9164 *
9165 * This function is used to request a new connection to be found. It will mark
9166 * the interface to allow reassociation and request a new scan to find a
9167 * suitable network to connect to.
9168 */
9169void wpas_request_connection(struct wpa_supplicant *wpa_s)
9170{
9171 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009172 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009173 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009174 wpa_s->disconnected = 0;
9175 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07009176 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08009177
9178 if (wpa_supplicant_fast_associate(wpa_s) != 1)
9179 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009180 else
9181 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08009182}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009183
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009184
Roshan Pius02242d72016-08-09 15:31:48 -07009185/**
9186 * wpas_request_disconnection - Request disconnection
9187 * @wpa_s: Pointer to the network interface
9188 *
9189 * This function is used to request disconnection from the currently connected
9190 * network. This will stop any ongoing scans and initiate deauthentication.
9191 */
9192void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
9193{
9194#ifdef CONFIG_SME
9195 wpa_s->sme.prev_bssid_set = 0;
9196#endif /* CONFIG_SME */
9197 wpa_s->reassociate = 0;
9198 wpa_s->disconnected = 1;
9199 wpa_supplicant_cancel_sched_scan(wpa_s);
9200 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009201 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07009202 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
9203 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07009204 radio_remove_works(wpa_s, "connect", 0);
9205 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08009206 wpa_s->roam_in_progress = false;
9207#ifdef CONFIG_WNM
9208 wpa_s->bss_trans_mgmt_in_progress = false;
9209#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07009210}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009211
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07009212
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009213void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
9214 struct wpa_used_freq_data *freqs_data,
9215 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009216{
9217 unsigned int i;
9218
9219 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
9220 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009221 for (i = 0; i < len; i++) {
9222 struct wpa_used_freq_data *cur = &freqs_data[i];
9223 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
9224 i, cur->freq, cur->flags);
9225 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009226}
9227
9228
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009229/*
9230 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009231 * are using the same radio as the current interface, and in addition, get
9232 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009233 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009234int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
9235 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009236 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009237{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009238 struct wpa_supplicant *ifs;
9239 u8 bssid[ETH_ALEN];
9240 int freq;
9241 unsigned int idx = 0, i;
9242
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009243 wpa_dbg(wpa_s, MSG_DEBUG,
9244 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009245 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009246
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009247 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
9248 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009249 if (idx == len)
9250 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009251
Sunil Ravi77d572f2023-01-17 23:58:31 +00009252 if (exclude_current && ifs == wpa_s)
9253 continue;
9254
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009255 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
9256 continue;
9257
9258 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009259 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
9260 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009261 freq = ifs->current_ssid->frequency;
9262 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
9263 freq = ifs->assoc_freq;
9264 else
9265 continue;
9266
9267 /* Hold only distinct freqs */
9268 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009269 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009270 break;
9271
9272 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009273 freqs_data[idx++].freq = freq;
9274
9275 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009276 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009277 WPA_FREQ_USED_BY_P2P_CLIENT :
9278 WPA_FREQ_USED_BY_INFRA_STATION;
9279 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009280 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08009281
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009282 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009283 return idx;
9284}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009285
9286
9287/*
9288 * Find the operating frequencies of any of the virtual interfaces that
9289 * are using the same radio as the current interface.
9290 */
9291int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009292 int *freq_array, unsigned int len,
9293 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009294{
9295 struct wpa_used_freq_data *freqs_data;
9296 int num, i;
9297
9298 os_memset(freq_array, 0, sizeof(int) * len);
9299
9300 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
9301 if (!freqs_data)
9302 return -1;
9303
Sunil Ravi77d572f2023-01-17 23:58:31 +00009304 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
9305 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009306 for (i = 0; i < num; i++)
9307 freq_array[i] = freqs_data[i].freq;
9308
9309 os_free(freqs_data);
9310
9311 return num;
9312}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009313
9314
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009315struct wpa_supplicant *
9316wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
9317{
9318 switch (frame) {
9319#ifdef CONFIG_P2P
9320 case VENDOR_ELEM_PROBE_REQ_P2P:
9321 case VENDOR_ELEM_PROBE_RESP_P2P:
9322 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
9323 case VENDOR_ELEM_BEACON_P2P_GO:
9324 case VENDOR_ELEM_P2P_PD_REQ:
9325 case VENDOR_ELEM_P2P_PD_RESP:
9326 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9327 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9328 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9329 case VENDOR_ELEM_P2P_INV_REQ:
9330 case VENDOR_ELEM_P2P_INV_RESP:
9331 case VENDOR_ELEM_P2P_ASSOC_REQ:
9332 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009333 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009334#endif /* CONFIG_P2P */
9335 default:
9336 return wpa_s;
9337 }
9338}
9339
9340
9341void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9342{
9343 unsigned int i;
9344 char buf[30];
9345
9346 wpa_printf(MSG_DEBUG, "Update vendor elements");
9347
9348 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9349 if (wpa_s->vendor_elem[i]) {
9350 int res;
9351
9352 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9353 if (!os_snprintf_error(sizeof(buf), res)) {
9354 wpa_hexdump_buf(MSG_DEBUG, buf,
9355 wpa_s->vendor_elem[i]);
9356 }
9357 }
9358 }
9359
9360#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009361 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009362 wpa_s->global->p2p &&
9363 !wpa_s->global->p2p_disabled)
9364 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9365#endif /* CONFIG_P2P */
9366}
9367
9368
9369int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9370 const u8 *elem, size_t len)
9371{
9372 u8 *ie, *end;
9373
9374 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9375 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9376
9377 for (; ie + 1 < end; ie += 2 + ie[1]) {
9378 if (ie + len > end)
9379 break;
9380 if (os_memcmp(ie, elem, len) != 0)
9381 continue;
9382
9383 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9384 wpabuf_free(wpa_s->vendor_elem[frame]);
9385 wpa_s->vendor_elem[frame] = NULL;
9386 } else {
9387 os_memmove(ie, ie + len, end - (ie + len));
9388 wpa_s->vendor_elem[frame]->used -= len;
9389 }
9390 wpas_vendor_elem_update(wpa_s);
9391 return 0;
9392 }
9393
9394 return -1;
9395}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009396
9397
9398struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009399 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009400 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009401{
9402 u16 i;
9403
Hai Shalomc1a21442022-02-04 13:43:00 -08009404 if (!modes)
9405 return NULL;
9406
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009407 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009408 if (modes[i].mode != mode ||
9409 !modes[i].num_channels || !modes[i].channels)
9410 continue;
Sunil Ravi99c035e2024-07-12 01:42:03 +00009411 if (is_6ghz == modes[i].is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009412 return &modes[i];
9413 }
9414
9415 return NULL;
9416}
9417
9418
Hai Shalomc1a21442022-02-04 13:43:00 -08009419struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9420 u16 num_modes, int freq)
9421{
9422 int i, j;
9423
9424 for (i = 0; i < num_modes; i++) {
9425 for (j = 0; j < modes[i].num_channels; j++) {
9426 if (freq == modes[i].channels[j].freq)
9427 return &modes[i];
9428 }
9429 }
9430
9431 return NULL;
9432}
9433
9434
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009435static struct
9436wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9437 const u8 *bssid)
9438{
9439 struct wpa_bss_tmp_disallowed *bss;
9440
9441 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9442 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009443 if (ether_addr_equal(bssid, bss->bssid))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009444 return bss;
9445 }
9446
9447 return NULL;
9448}
9449
9450
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009451static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9452{
9453 struct wpa_bss_tmp_disallowed *tmp;
9454 unsigned int num_bssid = 0;
9455 u8 *bssids;
9456 int ret;
9457
9458 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9459 if (!bssids)
9460 return -1;
9461 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9462 struct wpa_bss_tmp_disallowed, list) {
9463 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9464 ETH_ALEN);
9465 num_bssid++;
9466 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009467 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009468 os_free(bssids);
9469 return ret;
9470}
9471
9472
9473static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9474{
9475 struct wpa_supplicant *wpa_s = eloop_ctx;
9476 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9477
9478 /* Make sure the bss is not already freed */
9479 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9480 struct wpa_bss_tmp_disallowed, list) {
9481 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009482 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009483 wpa_set_driver_tmp_disallow_list(wpa_s);
9484 break;
9485 }
9486 }
9487}
9488
9489
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009490void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009491 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009492{
9493 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009494
9495 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9496 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009497 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009498 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009499 }
9500
9501 bss = os_malloc(sizeof(*bss));
9502 if (!bss) {
9503 wpa_printf(MSG_DEBUG,
9504 "Failed to allocate memory for temp disallow BSS");
9505 return;
9506 }
9507
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009508 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9509 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009510 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009511
9512finish:
9513 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009514 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9515 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009516}
9517
9518
Hai Shalom74f70d42019-02-11 14:42:39 -08009519int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9520 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009521{
Hai Shalom74f70d42019-02-11 14:42:39 -08009522 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009523
9524 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9525 struct wpa_bss_tmp_disallowed, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009526 if (ether_addr_equal(bss->bssid, tmp->bssid)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009527 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009528 break;
9529 }
9530 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009531 if (!disallowed)
9532 return 0;
9533
9534 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009535 bss->level > disallowed->rssi_threshold) {
9536 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9537 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009538 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009539 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009540
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009541 return 1;
9542}
Hai Shalom81f62d82019-07-22 12:10:00 -07009543
9544
9545int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9546 unsigned int type, const u8 *addr,
9547 const u8 *mask)
9548{
9549 if ((addr && !mask) || (!addr && mask)) {
9550 wpa_printf(MSG_INFO,
9551 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9552 return -1;
9553 }
9554
9555 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9556 wpa_printf(MSG_INFO,
9557 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9558 return -1;
9559 }
9560
9561 if (type & MAC_ADDR_RAND_SCAN) {
9562 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9563 addr, mask))
9564 return -1;
9565 }
9566
9567 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9568 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9569 addr, mask))
9570 return -1;
9571
9572 if (wpa_s->sched_scanning && !wpa_s->pno)
9573 wpas_scan_restart_sched_scan(wpa_s);
9574 }
9575
9576 if (type & MAC_ADDR_RAND_PNO) {
9577 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9578 addr, mask))
9579 return -1;
9580
9581 if (wpa_s->pno) {
9582 wpas_stop_pno(wpa_s);
9583 wpas_start_pno(wpa_s);
9584 }
9585 }
9586
9587 return 0;
9588}
9589
9590
9591int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9592 unsigned int type)
9593{
9594 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9595 if (wpa_s->pno) {
9596 if (type & MAC_ADDR_RAND_PNO) {
9597 wpas_stop_pno(wpa_s);
9598 wpas_start_pno(wpa_s);
9599 }
9600 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9601 wpas_scan_restart_sched_scan(wpa_s);
9602 }
9603
9604 return 0;
9605}
Hai Shalomfdcde762020-04-02 11:19:20 -07009606
9607
9608int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9609 struct wpa_signal_info *si)
9610{
9611 int res;
9612
9613 if (!wpa_s->driver->signal_poll)
9614 return -1;
9615
9616 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9617
9618#ifdef CONFIG_TESTING_OPTIONS
9619 if (res == 0) {
9620 struct driver_signal_override *dso;
9621
9622 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9623 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009624 if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009625 continue;
9626 wpa_printf(MSG_DEBUG,
9627 "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 +00009628 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009629 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009630 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009631 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009632 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009633 dso->si_avg_beacon_signal,
9634 si->current_noise,
9635 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009636 si->data.signal = dso->si_current_signal;
9637 si->data.avg_signal = dso->si_avg_signal;
9638 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009639 si->current_noise = dso->si_current_noise;
9640 break;
9641 }
9642 }
9643#endif /* CONFIG_TESTING_OPTIONS */
9644
9645 return res;
9646}
9647
9648
9649struct wpa_scan_results *
Sunil Ravi99c035e2024-07-12 01:42:03 +00009650wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07009651{
9652 struct wpa_scan_results *scan_res;
9653#ifdef CONFIG_TESTING_OPTIONS
9654 size_t idx;
9655#endif /* CONFIG_TESTING_OPTIONS */
9656
Sunil Ravi99c035e2024-07-12 01:42:03 +00009657 if (wpa_s->driver->get_scan_results)
9658 scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
9659 bssid);
9660 else if (wpa_s->driver->get_scan_results2)
9661 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9662 else
Hai Shalomfdcde762020-04-02 11:19:20 -07009663 return NULL;
9664
Hai Shalomfdcde762020-04-02 11:19:20 -07009665
9666#ifdef CONFIG_TESTING_OPTIONS
9667 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9668 struct driver_signal_override *dso;
9669 struct wpa_scan_res *res = scan_res->res[idx];
9670
9671 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9672 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009673 if (!ether_addr_equal(res->bssid, dso->bssid))
Hai Shalomfdcde762020-04-02 11:19:20 -07009674 continue;
9675 wpa_printf(MSG_DEBUG,
9676 "Override driver scan signal level %d->%d for "
9677 MACSTR,
9678 res->level, dso->scan_level,
9679 MAC2STR(res->bssid));
9680 res->flags |= WPA_SCAN_QUAL_INVALID;
9681 if (dso->scan_level < 0)
9682 res->flags |= WPA_SCAN_LEVEL_DBM;
9683 else
9684 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9685 res->level = dso->scan_level;
9686 break;
9687 }
9688 }
9689#endif /* CONFIG_TESTING_OPTIONS */
9690
9691 return scan_res;
9692}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009693
9694
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009695bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
Sunil Ravi77d572f2023-01-17 23:58:31 +00009696{
9697 int i;
9698
9699 if (!wpa_s->valid_links)
9700 return false;
9701
Sunil Ravi99c035e2024-07-12 01:42:03 +00009702 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009703 if (ether_addr_equal(wpa_s->links[i].bssid, addr))
Sunil Ravi77d572f2023-01-17 23:58:31 +00009704 return true;
9705 }
9706
9707 return false;
9708}
9709
9710
9711int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9712 unsigned int wait, const u8 *dst, const u8 *src,
9713 const u8 *bssid, const u8 *data, size_t data_len,
9714 int no_cck)
9715{
9716 if (!wpa_s->driver->send_action)
9717 return -1;
9718
9719 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9720 if (wpas_ap_link_address(wpa_s, dst))
9721 dst = wpa_s->ap_mld_addr;
9722
9723 if (wpas_ap_link_address(wpa_s, bssid))
9724 bssid = wpa_s->ap_mld_addr;
9725 }
9726
9727 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9728 bssid, data, data_len, no_cck);
9729}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009730
9731
9732bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9733{
9734 struct hostapd_channel_data *chnl;
9735 int i, j;
9736
9737 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9738 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9739 chnl = wpa_s->hw.modes[i].channels;
9740 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9741 if (only_enabled &&
9742 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9743 continue;
9744 if (is_6ghz_freq(chnl[j].freq))
9745 return true;
9746 }
9747 }
9748 }
9749
9750 return false;
9751}
Sunil Ravi7f769292024-07-23 22:21:32 +00009752
9753
9754bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
9755 struct wpa_bss *bss)
9756{
9757 int i;
9758
9759 if (!bss)
9760 return false;
9761 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9762 wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9763 return true;
9764
9765 if (!wpa_s->valid_links)
9766 return false;
9767
9768 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9769 if (!(wpa_s->valid_links & BIT(i)))
9770 continue;
9771 if (wpa_s->links[i].bss &&
9772 (wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9773 RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
9774 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9775 RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
9776 return true;
9777 }
9778
9779 return false;
9780}
9781
9782
9783bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
9784 struct wpa_bss *bss)
9785{
9786 int i;
9787
9788 if (!bss)
9789 return false;
9790 if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9791 return true;
9792
9793 if (!wpa_s->valid_links)
9794 return false;
9795
9796 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9797 if (!(wpa_s->valid_links & BIT(i)))
9798 continue;
9799 if (wpa_s->links[i].bss &&
9800 wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
9801 RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
9802 return true;
9803 }
9804
9805 return false;
9806}
Sunil Ravic0f5d412024-09-11 22:12:49 +00009807
9808
9809int wpas_get_owe_trans_network(const u8 *owe_ie, const u8 **bssid,
9810 const u8 **ssid, size_t *ssid_len)
9811{
9812#ifdef CONFIG_OWE
9813 const u8 *pos, *end;
9814 u8 ssid_len_tmp;
9815
9816 if (!owe_ie)
9817 return -1;
9818
9819 pos = owe_ie + 6;
9820 end = owe_ie + 2 + owe_ie[1];
9821
9822 if (end - pos < ETH_ALEN + 1)
9823 return -1;
9824 *bssid = pos;
9825 pos += ETH_ALEN;
9826 ssid_len_tmp = *pos++;
9827 if (end - pos < ssid_len_tmp || ssid_len_tmp > SSID_MAX_LEN)
9828 return -1;
9829
9830 *ssid = pos;
9831 *ssid_len = ssid_len_tmp;
9832
9833 return 0;
9834#else /* CONFIG_OWE */
9835 return -1;
9836#endif /* CONFIG_OWE */
9837}