blob: e40937c2ec5c8c68c68e78d1e82dfb57bec604f8 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalomc1a21442022-02-04 13:43:00 -08003 * Copyright (c) 2003-2022, 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"
68#ifdef CONFIG_MESH
69#include "ap/ap_config.h"
70#include "ap/hostapd.h"
71#endif /* CONFIG_MESH */
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -070072#include "aidl/aidl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070074const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080076"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"This software may be distributed under the terms of the BSD license.\n"
80"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070081#ifdef EAP_TLS_OPENSSL
82"\nThis product includes software developed by the OpenSSL Project\n"
83"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
84#endif /* EAP_TLS_OPENSSL */
85;
86
87#ifndef CONFIG_NO_STDOUT_DEBUG
88/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070091const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080092"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070093"\n"
94"Redistribution and use in source and binary forms, with or without\n"
95"modification, are permitted provided that the following conditions are\n"
96"met:\n"
97"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070098const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099"1. Redistributions of source code must retain the above copyright\n"
100" notice, this list of conditions and the following disclaimer.\n"
101"\n"
102"2. Redistributions in binary form must reproduce the above copyright\n"
103" notice, this list of conditions and the following disclaimer in the\n"
104" documentation and/or other materials provided with the distribution.\n"
105"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700106const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
108" names of its contributors may be used to endorse or promote products\n"
109" derived from this software without specific prior written permission.\n"
110"\n"
111"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
112"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
113"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
114"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700115const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700116"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
117"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
118"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
119"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
120"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
121"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
122"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
123"\n";
124#endif /* CONFIG_NO_STDOUT_DEBUG */
125
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700126
127static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
128#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
129static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
130#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700131#ifdef CONFIG_OWE
132static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
133#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700134
135
Hai Shalomfdcde762020-04-02 11:19:20 -0700136#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700137/* Configure default/group WEP keys for static WEP */
138int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
139{
140 int i, set = 0;
141
142 for (i = 0; i < NUM_WEP_KEYS; i++) {
143 if (ssid->wep_key_len[i] == 0)
144 continue;
145
146 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000147 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700148 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700149 ssid->wep_key[i], ssid->wep_key_len[i],
150 i == ssid->wep_tx_keyidx ?
151 KEY_FLAG_GROUP_RX_TX_DEFAULT :
152 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700153 }
154
155 return set;
156}
Hai Shalomfdcde762020-04-02 11:19:20 -0700157#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158
159
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700160int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
161 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700162{
163 u8 key[32];
164 size_t keylen;
165 enum wpa_alg alg;
166 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800167 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700168
169 /* IBSS/WPA-None uses only one key (Group) for both receiving and
170 * sending unicast and multicast packets. */
171
172 if (ssid->mode != WPAS_MODE_IBSS) {
173 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
174 "IBSS/ad-hoc) for WPA-None", ssid->mode);
175 return -1;
176 }
177
178 if (!ssid->psk_set) {
179 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
180 "WPA-None");
181 return -1;
182 }
183
184 switch (wpa_s->group_cipher) {
185 case WPA_CIPHER_CCMP:
186 os_memcpy(key, ssid->psk, 16);
187 keylen = 16;
188 alg = WPA_ALG_CCMP;
189 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700190 case WPA_CIPHER_GCMP:
191 os_memcpy(key, ssid->psk, 16);
192 keylen = 16;
193 alg = WPA_ALG_GCMP;
194 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700195 case WPA_CIPHER_TKIP:
196 /* WPA-None uses the same Michael MIC key for both TX and RX */
197 os_memcpy(key, ssid->psk, 16 + 8);
198 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
199 keylen = 32;
200 alg = WPA_ALG_TKIP;
201 break;
202 default:
203 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
204 "WPA-None", wpa_s->group_cipher);
205 return -1;
206 }
207
208 /* TODO: should actually remember the previously used seq#, both for TX
209 * and RX from each STA.. */
210
Sunil Ravi77d572f2023-01-17 23:58:31 +0000211 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700212 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800213 os_memset(key, 0, sizeof(key));
214 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700215}
216
217
218static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
219{
220 struct wpa_supplicant *wpa_s = eloop_ctx;
221 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700222 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
223 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
224 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225 bssid = wpa_s->pending_bssid;
226 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
227 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800228 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700229 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800231 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 wpa_s->reassociate = 1;
233
234 /*
235 * If we timed out, the AP or the local radio may be busy.
236 * So, wait a second until scanning again.
237 */
238 wpa_supplicant_req_scan(wpa_s, 1, 0);
239}
240
241
242/**
243 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
244 * @wpa_s: Pointer to wpa_supplicant data
245 * @sec: Number of seconds after which to time out authentication
246 * @usec: Number of microseconds after which to time out authentication
247 *
248 * This function is used to schedule a timeout for the current authentication
249 * attempt.
250 */
251void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
252 int sec, int usec)
253{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700254 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
256 return;
257
258 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
259 "%d usec", sec, usec);
260 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700261 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
263}
264
265
Roshan Pius3a1667e2018-07-03 15:17:14 -0700266/*
267 * wpas_auth_timeout_restart - Restart and change timeout for authentication
268 * @wpa_s: Pointer to wpa_supplicant data
269 * @sec_diff: difference in seconds applied to original timeout value
270 */
271void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
272{
273 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
274
275 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
276 wpa_dbg(wpa_s, MSG_DEBUG,
277 "Authentication timeout restart: %d sec", new_sec);
278 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
279 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
280 wpa_s, NULL);
281 }
282}
283
284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285/**
286 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
287 * @wpa_s: Pointer to wpa_supplicant data
288 *
289 * This function is used to cancel authentication timeout scheduled with
290 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
291 * been completed.
292 */
293void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
294{
295 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
296 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800297 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700298 os_free(wpa_s->last_con_fail_realm);
299 wpa_s->last_con_fail_realm = NULL;
300 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700301}
302
303
304/**
305 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
306 * @wpa_s: Pointer to wpa_supplicant data
307 *
308 * This function is used to configure EAPOL state machine based on the selected
309 * authentication mode.
310 */
311void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
312{
313#ifdef IEEE8021X_EAPOL
314 struct eapol_config eapol_conf;
315 struct wpa_ssid *ssid = wpa_s->current_ssid;
316
317#ifdef CONFIG_IBSS_RSN
318 if (ssid->mode == WPAS_MODE_IBSS &&
319 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
320 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
321 /*
322 * RSN IBSS authentication is per-STA and we can disable the
323 * per-BSSID EAPOL authentication.
324 */
325 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700326 eapol_sm_notify_eap_success(wpa_s->eapol, true);
327 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328 return;
329 }
330#endif /* CONFIG_IBSS_RSN */
331
Hai Shalome21d4e82020-04-29 16:34:06 -0700332 eapol_sm_notify_eap_success(wpa_s->eapol, false);
333 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700334
335 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
336 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
337 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
338 else
339 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
340
341 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
342 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
343 eapol_conf.accept_802_1x_keys = 1;
344 eapol_conf.required_keys = 0;
345 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
346 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
347 }
348 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
349 eapol_conf.required_keys |=
350 EAPOL_REQUIRE_KEY_BROADCAST;
351 }
352
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700353 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 eapol_conf.required_keys = 0;
355 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700356 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700357 eapol_conf.workaround = ssid->eap_workaround;
358 eapol_conf.eap_disabled =
359 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
360 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
361 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700362 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800363
364#ifdef CONFIG_WPS
365 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
366 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
367 if (wpa_s->current_bss) {
368 struct wpabuf *ie;
369 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
370 WPS_IE_VENDOR_TYPE);
371 if (ie) {
372 if (wps_is_20(ie))
373 eapol_conf.wps |=
374 EAPOL_PEER_IS_WPS20_AP;
375 wpabuf_free(ie);
376 }
377 }
378 }
379#endif /* CONFIG_WPS */
380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700381 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700382
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800383#ifdef CONFIG_MACSEC
384 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
385 ieee802_1x_create_preshared_mka(wpa_s, ssid);
386 else
387 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
388#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800389#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700390}
391
392
393/**
394 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
395 * @wpa_s: Pointer to wpa_supplicant data
396 * @ssid: Configuration data for the network
397 *
398 * This function is used to configure WPA state machine and related parameters
399 * to a mode where WPA is not enabled. This is called as part of the
400 * authentication configuration when the selected network does not use WPA.
401 */
402void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
403 struct wpa_ssid *ssid)
404{
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700407#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000408 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700409
410 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
411 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
412 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
413 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
414 else
415 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
416 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
417 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700418 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700420 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
421 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
423 wpa_s->group_cipher = WPA_CIPHER_NONE;
424 wpa_s->mgmt_group_cipher = 0;
425
Hai Shalomfdcde762020-04-02 11:19:20 -0700426#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 for (i = 0; i < NUM_WEP_KEYS; i++) {
428 if (ssid->wep_key_len[i] > 5) {
429 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
430 wpa_s->group_cipher = WPA_CIPHER_WEP104;
431 break;
432 } else if (ssid->wep_key_len[i] > 0) {
433 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
434 wpa_s->group_cipher = WPA_CIPHER_WEP40;
435 break;
436 }
437 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700438#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
443 wpa_s->pairwise_cipher);
444 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
446 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447
448 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000449 os_memset(&mlo, 0, sizeof(mlo));
450 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451}
452
453
Dmitry Shmidt04949592012-07-19 12:16:46 -0700454void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800455{
456 int i;
457 if (wpa_s->hw.modes == NULL)
458 return;
459
460 for (i = 0; i < wpa_s->hw.num_modes; i++) {
461 os_free(wpa_s->hw.modes[i].channels);
462 os_free(wpa_s->hw.modes[i].rates);
463 }
464
465 os_free(wpa_s->hw.modes);
466 wpa_s->hw.modes = NULL;
467}
468
469
Hai Shalomc1a21442022-02-04 13:43:00 -0800470static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
471 struct wpa_bss_tmp_disallowed *bss)
472{
473 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
474 dl_list_del(&bss->list);
475 os_free(bss);
476}
477
478
Hai Shalom74f70d42019-02-11 14:42:39 -0800479void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800480{
481 struct wpa_bss_tmp_disallowed *bss, *prev;
482
483 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800484 struct wpa_bss_tmp_disallowed, list)
485 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800486}
487
488
Paul Stewart092955c2017-02-06 09:13:09 -0800489void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
490{
491 struct fils_hlp_req *req;
492
493 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
494 list)) != NULL) {
495 dl_list_del(&req->list);
496 wpabuf_free(req->pkt);
497 os_free(req);
498 }
499}
500
501
Hai Shalomfdcde762020-04-02 11:19:20 -0700502void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
503{
504 struct wpa_supplicant *wpa_s = eloop_ctx;
505
506 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
507 return;
508 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
509 wpa_bss_flush(wpa_s);
510}
511
512
513#ifdef CONFIG_TESTING_OPTIONS
514void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
515{
516 struct driver_signal_override *dso;
517
518 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
519 struct driver_signal_override, list))) {
520 dl_list_del(&dso->list);
521 os_free(dso);
522 }
523}
524#endif /* CONFIG_TESTING_OPTIONS */
525
526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
528{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700529 int i;
530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700532 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533 scard_deinit(wpa_s->scard);
534 wpa_s->scard = NULL;
535 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
536 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
537 l2_packet_deinit(wpa_s->l2);
538 wpa_s->l2 = NULL;
539 if (wpa_s->l2_br) {
540 l2_packet_deinit(wpa_s->l2_br);
541 wpa_s->l2_br = NULL;
542 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800543#ifdef CONFIG_TESTING_OPTIONS
544 l2_packet_deinit(wpa_s->l2_test);
545 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800546 os_free(wpa_s->get_pref_freq_list_override);
547 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700548 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
549 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800550 os_free(wpa_s->extra_sae_rejected_groups);
551 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700552 wpabuf_free(wpa_s->rsne_override_eapol);
553 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800554 wpabuf_free(wpa_s->rsnxe_override_assoc);
555 wpa_s->rsnxe_override_assoc = NULL;
556 wpabuf_free(wpa_s->rsnxe_override_eapol);
557 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700558 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800559#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 if (wpa_s->conf != NULL) {
562 struct wpa_ssid *ssid;
563 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
564 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 }
566
567 os_free(wpa_s->confname);
568 wpa_s->confname = NULL;
569
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700570 os_free(wpa_s->confanother);
571 wpa_s->confanother = NULL;
572
Hai Shalomce48b4a2018-09-05 11:41:35 -0700573 os_free(wpa_s->last_con_fail_realm);
574 wpa_s->last_con_fail_realm = NULL;
575 wpa_s->last_con_fail_realm_len = 0;
576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 wpa_sm_set_eapol(wpa_s->wpa, NULL);
578 eapol_sm_deinit(wpa_s->eapol);
579 wpa_s->eapol = NULL;
580
581 rsn_preauth_deinit(wpa_s->wpa);
582
583#ifdef CONFIG_TDLS
584 wpa_tdls_deinit(wpa_s->wpa);
585#endif /* CONFIG_TDLS */
586
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800587 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800589 ptksa_cache_deinit(wpa_s->ptksa);
590 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_sm_deinit(wpa_s->wpa);
592 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800593 wpa_bssid_ignore_clear(wpa_s);
594
595#ifdef CONFIG_PASN
596 wpas_pasn_auth_stop(wpa_s);
597#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
599 wpa_bss_deinit(wpa_s);
600
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700601 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpa_supplicant_cancel_scan(wpa_s);
603 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800604 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
605#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
606 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
607 wpa_s, NULL);
608#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700610 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700611 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 wpas_wps_deinit(wpa_s);
614
615 wpabuf_free(wpa_s->pending_eapol_rx);
616 wpa_s->pending_eapol_rx = NULL;
617
618#ifdef CONFIG_IBSS_RSN
619 ibss_rsn_deinit(wpa_s->ibss_rsn);
620 wpa_s->ibss_rsn = NULL;
621#endif /* CONFIG_IBSS_RSN */
622
623 sme_deinit(wpa_s);
624
625#ifdef CONFIG_AP
626 wpa_supplicant_ap_deinit(wpa_s);
627#endif /* CONFIG_AP */
628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800631#ifdef CONFIG_OFFCHANNEL
632 offchannel_deinit(wpa_s);
633#endif /* CONFIG_OFFCHANNEL */
634
635 wpa_supplicant_cancel_sched_scan(wpa_s);
636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 os_free(wpa_s->next_scan_freqs);
638 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800639
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800640 os_free(wpa_s->manual_scan_freqs);
641 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700642 os_free(wpa_s->select_network_scan_freqs);
643 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800644
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700645 os_free(wpa_s->manual_sched_scan_freqs);
646 wpa_s->manual_sched_scan_freqs = NULL;
647
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800648 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
649
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700650 /*
651 * Need to remove any pending gas-query radio work before the
652 * gas_query_deinit() call because gas_query::work has not yet been set
653 * for works that have not been started. gas_query_free() will be unable
654 * to cancel such pending radio works and once the pending gas-query
655 * radio work eventually gets removed, the deinit notification call to
656 * gas_query_start_cb() would result in dereferencing freed memory.
657 */
658 if (wpa_s->radio)
659 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660 gas_query_deinit(wpa_s->gas);
661 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700662 gas_server_deinit(wpa_s->gas_server);
663 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800664
665 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700666
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700667 ieee802_1x_dealloc_kay_sm(wpa_s);
668
Dmitry Shmidt04949592012-07-19 12:16:46 -0700669 os_free(wpa_s->bssid_filter);
670 wpa_s->bssid_filter = NULL;
671
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800672 os_free(wpa_s->disallow_aps_bssid);
673 wpa_s->disallow_aps_bssid = NULL;
674 os_free(wpa_s->disallow_aps_ssid);
675 wpa_s->disallow_aps_ssid = NULL;
676
Dmitry Shmidt04949592012-07-19 12:16:46 -0700677 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700678#ifdef CONFIG_WNM
679 wnm_deallocate_memory(wpa_s);
680#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700681
682 ext_password_deinit(wpa_s->ext_pw);
683 wpa_s->ext_pw = NULL;
684
685 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800686 wpa_s->last_gas_resp = NULL;
687 wpabuf_free(wpa_s->prev_gas_resp);
688 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700689
690 os_free(wpa_s->last_scan_res);
691 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800692
693#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700694 if (wpa_s->drv_priv)
695 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700696 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800697#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700698
699 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
700 wpabuf_free(wpa_s->vendor_elem[i]);
701 wpa_s->vendor_elem[i] = NULL;
702 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800703
704 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800705
706 wpa_s->sched_scan_plans_num = 0;
707 os_free(wpa_s->sched_scan_plans);
708 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800709
710#ifdef CONFIG_MBO
711 wpa_s->non_pref_chan_num = 0;
712 os_free(wpa_s->non_pref_chan);
713 wpa_s->non_pref_chan = NULL;
714#endif /* CONFIG_MBO */
715
716 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700717
718 wpabuf_free(wpa_s->lci);
719 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800720 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800721
722#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
723#ifdef CONFIG_MESH
724 {
725 struct external_pmksa_cache *entry;
726
727 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
728 struct external_pmksa_cache,
729 list)) != NULL) {
730 dl_list_del(&entry->list);
731 os_free(entry->pmksa_cache);
732 os_free(entry);
733 }
734 }
735#endif /* CONFIG_MESH */
736#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
737
738 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800739
740 wpabuf_free(wpa_s->ric_ies);
741 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700742
743#ifdef CONFIG_DPP
744 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700745 dpp_global_deinit(wpa_s->dpp);
746 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700747#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800748
749#ifdef CONFIG_PASN
750 wpas_pasn_auth_stop(wpa_s);
751#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800752 wpas_scs_deinit(wpa_s);
753 wpas_dscp_deinit(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000754
755#ifdef CONFIG_OWE
756 os_free(wpa_s->owe_trans_scan_freq);
757 wpa_s->owe_trans_scan_freq = NULL;
758#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759}
760
761
762/**
763 * wpa_clear_keys - Clear keys configured for the driver
764 * @wpa_s: Pointer to wpa_supplicant data
765 * @addr: Previously used BSSID or %NULL if not available
766 *
767 * This function clears the encryption keys that has been previously configured
768 * for the driver.
769 */
770void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
771{
Hai Shalomc3565922019-10-28 11:58:20 -0700772 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773
774 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800775 for (i = 0; i < max; i++) {
776 if (wpa_s->keys_cleared & BIT(i))
777 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000778 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700779 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800780 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700781 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
782 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800783 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700784 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000785 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
786 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700787 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000788 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
789 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 /* MLME-SETPROTECTION.request(None) */
791 wpa_drv_mlme_setprotection(
792 wpa_s, addr,
793 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
794 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
795 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800796 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797}
798
799
800/**
801 * wpa_supplicant_state_txt - Get the connection state name as a text string
802 * @state: State (wpa_state; WPA_*)
803 * Returns: The state name as a printable text string
804 */
805const char * wpa_supplicant_state_txt(enum wpa_states state)
806{
807 switch (state) {
808 case WPA_DISCONNECTED:
809 return "DISCONNECTED";
810 case WPA_INACTIVE:
811 return "INACTIVE";
812 case WPA_INTERFACE_DISABLED:
813 return "INTERFACE_DISABLED";
814 case WPA_SCANNING:
815 return "SCANNING";
816 case WPA_AUTHENTICATING:
817 return "AUTHENTICATING";
818 case WPA_ASSOCIATING:
819 return "ASSOCIATING";
820 case WPA_ASSOCIATED:
821 return "ASSOCIATED";
822 case WPA_4WAY_HANDSHAKE:
823 return "4WAY_HANDSHAKE";
824 case WPA_GROUP_HANDSHAKE:
825 return "GROUP_HANDSHAKE";
826 case WPA_COMPLETED:
827 return "COMPLETED";
828 default:
829 return "UNKNOWN";
830 }
831}
832
833
834#ifdef CONFIG_BGSCAN
835
Hai Shalom899fcc72020-10-19 14:38:18 -0700836static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
837{
838 if (wpa_s->bgscan_ssid) {
839 bgscan_deinit(wpa_s);
840 wpa_s->bgscan_ssid = NULL;
841 }
842}
843
844
845/**
846 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
847 * @wpa_s: Pointer to the wpa_supplicant data
848 *
849 * Stop, start, or reconfigure the scan parameters depending on the method.
850 */
851void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800853 const char *name;
854
855 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
856 name = wpa_s->current_ssid->bgscan;
857 else
858 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700859 if (!name || name[0] == '\0') {
860 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800861 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700862 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800863 if (wpas_driver_bss_selection(wpa_s))
864 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800865#ifdef CONFIG_P2P
866 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
867 return;
868#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869
870 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800871 if (wpa_s->current_ssid) {
872 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
874 "bgscan");
875 /*
876 * Live without bgscan; it is only used as a roaming
877 * optimization, so the initial connection is not
878 * affected.
879 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700880 } else {
881 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700883 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
884 0);
885 if (scan_res) {
886 bgscan_notify_scan(wpa_s, scan_res);
887 wpa_scan_results_free(scan_res);
888 }
889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 } else
891 wpa_s->bgscan_ssid = NULL;
892}
893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700894#endif /* CONFIG_BGSCAN */
895
896
Dmitry Shmidt04949592012-07-19 12:16:46 -0700897static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
898{
899 if (autoscan_init(wpa_s, 0))
900 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
901}
902
903
904static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
905{
906 autoscan_deinit(wpa_s);
907}
908
909
910void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
911{
912 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
913 wpa_s->wpa_state == WPA_SCANNING) {
914 autoscan_deinit(wpa_s);
915 wpa_supplicant_start_autoscan(wpa_s);
916 }
917}
918
919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920/**
921 * wpa_supplicant_set_state - Set current connection state
922 * @wpa_s: Pointer to wpa_supplicant data
923 * @state: The new connection state
924 *
925 * This function is called whenever the connection state changes, e.g.,
926 * association is completed for WPA/WPA2 4-Way Handshake is started.
927 */
928void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
929 enum wpa_states state)
930{
931 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700932#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700933 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700934#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935
936 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
937 wpa_supplicant_state_txt(wpa_s->wpa_state),
938 wpa_supplicant_state_txt(state));
939
Hai Shalom74f70d42019-02-11 14:42:39 -0800940 if (state == WPA_COMPLETED &&
941 os_reltime_initialized(&wpa_s->roam_start)) {
942 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
943 wpa_s->roam_start.sec = 0;
944 wpa_s->roam_start.usec = 0;
945 wpas_notify_auth_changed(wpa_s);
946 wpas_notify_roam_time(wpa_s);
947 wpas_notify_roam_complete(wpa_s);
948 } else if (state == WPA_DISCONNECTED &&
949 os_reltime_initialized(&wpa_s->roam_start)) {
950 wpa_s->roam_start.sec = 0;
951 wpa_s->roam_start.usec = 0;
952 wpa_s->roam_time.sec = 0;
953 wpa_s->roam_time.usec = 0;
954 wpas_notify_roam_complete(wpa_s);
955 }
956
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800957 if (state == WPA_INTERFACE_DISABLED) {
958 /* Assure normal scan when interface is restored */
959 wpa_s->normal_scans = 0;
960 }
961
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700962 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800963 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700964 /* Reinitialize normal_scan counter */
965 wpa_s->normal_scans = 0;
966 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800967
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700968#ifdef CONFIG_P2P
969 /*
970 * P2PS client has to reply to Probe Request frames received on the
971 * group operating channel. Enable Probe Request frame reporting for
972 * P2P connected client in case p2p_cli_probe configuration property is
973 * set to 1.
974 */
975 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
976 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
977 wpa_s->current_ssid->p2p_group) {
978 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
979 wpa_dbg(wpa_s, MSG_DEBUG,
980 "P2P: Enable CLI Probe Request RX reporting");
981 wpa_s->p2p_cli_probe =
982 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
983 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
984 wpa_dbg(wpa_s, MSG_DEBUG,
985 "P2P: Disable CLI Probe Request RX reporting");
986 wpa_s->p2p_cli_probe = 0;
987 wpa_drv_probe_req_report(wpa_s, 0);
988 }
989 }
990#endif /* CONFIG_P2P */
991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700992 if (state != WPA_SCANNING)
993 wpa_supplicant_notify_scanning(wpa_s, 0);
994
995 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700997 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -0700998 char mld_addr[50];
999
1000 mld_addr[0] = '\0';
1001 if (wpa_s->valid_links)
1002 os_snprintf(mld_addr, sizeof(mld_addr),
1003 " ap_mld_addr=" MACSTR,
1004 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001005
1006#ifdef CONFIG_SME
1007 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1008 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1009 fils_hlp_sent = 1;
1010#endif /* CONFIG_SME */
1011 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1012 wpa_auth_alg_fils(wpa_s->auth_alg))
1013 fils_hlp_sent = 1;
1014
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001015#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001017 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001018 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001020 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001021 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001023 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001024 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 wpa_drv_set_operstate(wpa_s, 1);
1027#ifndef IEEE8021X_EAPOL
1028 wpa_drv_set_supp_port(wpa_s, 1);
1029#endif /* IEEE8021X_EAPOL */
1030 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001031 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001033
1034 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001035
1036#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1037 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001038 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001039#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001040#ifdef CONFIG_OWE
1041 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1042 wpas_update_owe_connect_params(wpa_s);
1043#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001044#ifdef CONFIG_HS20
1045 hs20_configure_frame_filters(wpa_s);
1046#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1048 state == WPA_ASSOCIATED) {
1049 wpa_s->new_connection = 1;
1050 wpa_drv_set_operstate(wpa_s, 0);
1051#ifndef IEEE8021X_EAPOL
1052 wpa_drv_set_supp_port(wpa_s, 0);
1053#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001054 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055 }
1056 wpa_s->wpa_state = state;
1057
1058#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001059 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1060 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001061 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 wpa_supplicant_stop_bgscan(wpa_s);
1063#endif /* CONFIG_BGSCAN */
1064
Hai Shalom5f92bc92019-04-18 11:54:11 -07001065 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001066 wpa_supplicant_stop_autoscan(wpa_s);
1067
1068 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1069 wpa_supplicant_start_autoscan(wpa_s);
1070
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001071 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1072 wmm_ac_notify_disassoc(wpa_s);
1073
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 if (wpa_s->wpa_state != old_state) {
1075 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1076
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001077 /*
1078 * Notify the P2P Device interface about a state change in one
1079 * of the interfaces.
1080 */
1081 wpas_p2p_indicate_state_change(wpa_s);
1082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083 if (wpa_s->wpa_state == WPA_COMPLETED ||
1084 old_state == WPA_COMPLETED)
1085 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001086#ifdef CONFIG_DPP2
1087 if (wpa_s->wpa_state == WPA_COMPLETED)
1088 wpas_dpp_connected(wpa_s);
1089#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 }
Hai Shalomc3565922019-10-28 11:58:20 -07001091#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1092 if (update_fils_connect_params)
1093 wpas_update_fils_connect_params(wpa_s);
1094#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095}
1096
1097
1098void wpa_supplicant_terminate_proc(struct wpa_global *global)
1099{
1100 int pending = 0;
1101#ifdef CONFIG_WPS
1102 struct wpa_supplicant *wpa_s = global->ifaces;
1103 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001104 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001105 if (wpas_wps_terminate_pending(wpa_s) == 1)
1106 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001107#ifdef CONFIG_P2P
1108 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1109 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1110 wpas_p2p_disconnect(wpa_s);
1111#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001112 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113 }
1114#endif /* CONFIG_WPS */
1115 if (pending)
1116 return;
1117 eloop_terminate();
1118}
1119
1120
1121static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1122{
1123 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001124 wpa_supplicant_terminate_proc(global);
1125}
1126
1127
1128void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1129{
1130 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001131 enum wpa_states new_state;
1132
1133 if (old_state == WPA_SCANNING)
1134 new_state = WPA_SCANNING;
1135 else
1136 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137
1138 wpa_s->pairwise_cipher = 0;
1139 wpa_s->group_cipher = 0;
1140 wpa_s->mgmt_group_cipher = 0;
1141 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001142 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001144 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145
1146 if (wpa_s->wpa_state != old_state)
1147 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1148}
1149
1150
1151/**
1152 * wpa_supplicant_reload_configuration - Reload configuration data
1153 * @wpa_s: Pointer to wpa_supplicant data
1154 * Returns: 0 on success or -1 if configuration parsing failed
1155 *
1156 * This function can be used to request that the configuration data is reloaded
1157 * (e.g., after configuration file change). This function is reloading
1158 * configuration only for one interface, so this may need to be called multiple
1159 * times if %wpa_supplicant is controlling multiple interfaces and all
1160 * interfaces need reconfiguration.
1161 */
1162int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1163{
1164 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 int reconf_ctrl;
1166 int old_ap_scan;
1167
1168 if (wpa_s->confname == NULL)
1169 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001170 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171 if (conf == NULL) {
1172 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1173 "file '%s' - exiting", wpa_s->confname);
1174 return -1;
1175 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001176 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001177 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001178 wpa_msg(wpa_s, MSG_ERROR,
1179 "Failed to parse the configuration file '%s' - exiting",
1180 wpa_s->confanother);
1181 return -1;
1182 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 conf->changed_parameters = (unsigned int) -1;
1185
1186 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1187 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1188 os_strcmp(conf->ctrl_interface,
1189 wpa_s->conf->ctrl_interface) != 0);
1190
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001191 if (reconf_ctrl) {
1192 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 wpa_s->ctrl_iface = NULL;
1194 }
1195
1196 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001197 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001198 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1199 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001200 wpa_supplicant_deauthenticate(wpa_s,
1201 WLAN_REASON_DEAUTH_LEAVING);
1202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203
1204 /*
1205 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001206 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001208 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1209 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1210 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 /*
1212 * Clear forced success to clear EAP state for next
1213 * authentication.
1214 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001215 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 }
1217 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1218 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001219 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1221 rsn_preauth_deinit(wpa_s->wpa);
1222
1223 old_ap_scan = wpa_s->conf->ap_scan;
1224 wpa_config_free(wpa_s->conf);
1225 wpa_s->conf = conf;
1226 if (old_ap_scan != wpa_s->conf->ap_scan)
1227 wpas_notify_ap_scan_changed(wpa_s);
1228
1229 if (reconf_ctrl)
1230 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1231
1232 wpa_supplicant_update_config(wpa_s);
1233
1234 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001235 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 wpa_s->reassociate = 1;
1237 wpa_supplicant_req_scan(wpa_s, 0, 0);
1238 }
Hai Shalom60840252021-02-19 19:02:11 -08001239 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1241 return 0;
1242}
1243
1244
1245static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1246{
1247 struct wpa_global *global = signal_ctx;
1248 struct wpa_supplicant *wpa_s;
1249 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1250 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1251 sig);
1252 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1253 wpa_supplicant_terminate_proc(global);
1254 }
1255 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001256
1257 if (wpa_debug_reopen_file() < 0) {
1258 /* Ignore errors since we cannot really do much to fix this */
1259 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261}
1262
1263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001264static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1265 struct wpa_ssid *ssid,
1266 struct wpa_ie_data *ie)
1267{
1268 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1269 if (ret) {
1270 if (ret == -2) {
1271 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1272 "from association info");
1273 }
1274 return -1;
1275 }
1276
1277 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1278 "cipher suites");
1279 if (!(ie->group_cipher & ssid->group_cipher)) {
1280 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1281 "cipher 0x%x (mask 0x%x) - reject",
1282 ie->group_cipher, ssid->group_cipher);
1283 return -1;
1284 }
1285 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1286 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1287 "cipher 0x%x (mask 0x%x) - reject",
1288 ie->pairwise_cipher, ssid->pairwise_cipher);
1289 return -1;
1290 }
1291 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1292 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1293 "management 0x%x (mask 0x%x) - reject",
1294 ie->key_mgmt, ssid->key_mgmt);
1295 return -1;
1296 }
1297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001299 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1301 "that does not support management frame protection - "
1302 "reject");
1303 return -1;
1304 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305
1306 return 0;
1307}
1308
1309
Hai Shalom021b0b52019-04-10 11:17:58 -07001310static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1311 int freq)
1312{
1313 if (!ie->has_group)
1314 ie->group_cipher = wpa_default_rsn_cipher(freq);
1315 if (!ie->has_pairwise)
1316 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1317 return (ie->group_cipher & ssid->group_cipher) &&
1318 (ie->pairwise_cipher & ssid->pairwise_cipher);
1319}
1320
1321
Hai Shalomc1a21442022-02-04 13:43:00 -08001322void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1323 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1324{
1325 int sel;
1326
1327 sel = ie->mgmt_group_cipher;
1328 if (ssid->group_mgmt_cipher)
1329 sel &= ssid->group_mgmt_cipher;
1330 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1331 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1332 sel = 0;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1335 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1336 if (sel & WPA_CIPHER_AES_128_CMAC) {
1337 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1338 wpa_dbg(wpa_s, MSG_DEBUG,
1339 "WPA: using MGMT group cipher AES-128-CMAC");
1340 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1341 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1342 wpa_dbg(wpa_s, MSG_DEBUG,
1343 "WPA: using MGMT group cipher BIP-GMAC-128");
1344 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1345 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1346 wpa_dbg(wpa_s, MSG_DEBUG,
1347 "WPA: using MGMT group cipher BIP-GMAC-256");
1348 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1349 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1350 wpa_dbg(wpa_s, MSG_DEBUG,
1351 "WPA: using MGMT group cipher BIP-CMAC-256");
1352 } else {
1353 wpa_s->mgmt_group_cipher = 0;
1354 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1355 }
1356 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1357 wpa_s->mgmt_group_cipher);
1358 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1359 wpas_get_ssid_pmf(wpa_s, ssid));
1360}
1361
Sunil Ravi77d572f2023-01-17 23:58:31 +00001362/**
1363 * wpa_supplicant_get_psk - Get PSK from config or external database
1364 * @wpa_s: Pointer to wpa_supplicant data
1365 * @bss: Scan results for the selected BSS, or %NULL if not available
1366 * @ssid: Configuration data for the selected network
1367 * @psk: Buffer for the PSK
1368 * Returns: 0 on success or -1 if configuration parsing failed
1369 *
1370 * This function obtains the PSK for a network, either included inline in the
1371 * config or retrieved from an external database.
1372 */
1373static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1374 struct wpa_bss *bss, struct wpa_ssid *ssid,
1375 u8 *psk)
1376{
1377 if (ssid->psk_set) {
1378 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1379 ssid->psk, PMK_LEN);
1380 os_memcpy(psk, ssid->psk, PMK_LEN);
1381 return 0;
1382 }
1383
1384#ifndef CONFIG_NO_PBKDF2
1385 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1386 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1387 4096, psk, PMK_LEN) != 0) {
1388 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1389 return -1;
1390 }
1391 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1392 psk, PMK_LEN);
1393 return 0;
1394 }
1395#endif /* CONFIG_NO_PBKDF2 */
1396
1397#ifdef CONFIG_EXT_PASSWORD
1398 if (ssid->ext_psk) {
1399 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1400 ssid->ext_psk);
1401 char pw_str[64 + 1];
1402
1403 if (!pw) {
1404 wpa_msg(wpa_s, MSG_INFO,
1405 "EXT PW: No PSK found from external storage");
1406 return -1;
1407 }
1408
1409 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1410 wpa_msg(wpa_s, MSG_INFO,
1411 "EXT PW: Unexpected PSK length %d in external storage",
1412 (int) wpabuf_len(pw));
1413 ext_password_free(pw);
1414 return -1;
1415 }
1416
1417 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1418 pw_str[wpabuf_len(pw)] = '\0';
1419
1420#ifndef CONFIG_NO_PBKDF2
1421 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1422 {
1423 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1424 4096, psk, PMK_LEN) != 0) {
1425 wpa_msg(wpa_s, MSG_WARNING,
1426 "Error in pbkdf2_sha1()");
1427 forced_memzero(pw_str, sizeof(pw_str));
1428 ext_password_free(pw);
1429 return -1;
1430 }
1431 wpa_hexdump_key(MSG_MSGDUMP,
1432 "PSK (from external passphrase)",
1433 psk, PMK_LEN);
1434 } else
1435#endif /* CONFIG_NO_PBKDF2 */
1436 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1437 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1438 wpa_msg(wpa_s, MSG_INFO,
1439 "EXT PW: Invalid PSK hex string");
1440 forced_memzero(pw_str, sizeof(pw_str));
1441 ext_password_free(pw);
1442 return -1;
1443 }
1444 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1445 psk, PMK_LEN);
1446 } else {
1447 wpa_msg(wpa_s, MSG_INFO,
1448 "EXT PW: No suitable PSK available");
1449 forced_memzero(pw_str, sizeof(pw_str));
1450 ext_password_free(pw);
1451 return -1;
1452 }
1453
1454 forced_memzero(pw_str, sizeof(pw_str));
1455 ext_password_free(pw);
1456
1457 return 0;
1458 }
1459#endif /* CONFIG_EXT_PASSWORD */
1460
1461 return -1;
1462}
1463
Hai Shalomc1a21442022-02-04 13:43:00 -08001464
Sunil Ravi89eba102022-09-13 21:04:37 -07001465static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1466 struct wpa_ssid *ssid)
1467{
1468 int akm_count = wpa_s->max_num_akms;
1469 u8 capab = 0;
1470
1471 if (akm_count < 2)
1472 return;
1473
1474 akm_count--;
1475 wpa_s->allowed_key_mgmts = 0;
1476 switch (wpa_s->key_mgmt) {
1477 case WPA_KEY_MGMT_PSK:
1478 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1479 akm_count--;
1480 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1481 }
1482 if (!akm_count)
1483 break;
1484 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1485 akm_count--;
1486 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1487 }
1488 if (!akm_count)
1489 break;
1490 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1491 wpa_s->allowed_key_mgmts |=
1492 WPA_KEY_MGMT_PSK_SHA256;
1493 break;
1494 case WPA_KEY_MGMT_PSK_SHA256:
1495 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1496 akm_count--;
1497 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1498 }
1499 if (!akm_count)
1500 break;
1501 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1502 akm_count--;
1503 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1504 }
1505 if (!akm_count)
1506 break;
1507 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1508 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1509 break;
1510 case WPA_KEY_MGMT_SAE:
1511 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1512 akm_count--;
1513 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1514 }
1515 if (!akm_count)
1516 break;
1517 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1518 akm_count--;
1519 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1520 }
1521 if (!akm_count)
1522 break;
1523 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1524 wpa_s->allowed_key_mgmts |=
1525 WPA_KEY_MGMT_PSK_SHA256;
1526 break;
1527 case WPA_KEY_MGMT_SAE_EXT_KEY:
1528 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1529 akm_count--;
1530 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1531 }
1532 if (!akm_count)
1533 break;
1534 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1535 akm_count--;
1536 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1537 }
1538 if (!akm_count)
1539 break;
1540 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1541 wpa_s->allowed_key_mgmts |=
1542 WPA_KEY_MGMT_PSK_SHA256;
1543 break;
1544 default:
1545 return;
1546 }
1547
Sunil Ravi77d572f2023-01-17 23:58:31 +00001548 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1549 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001550 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1551#ifdef CONFIG_SAE_PK
1552 if (ssid->sae_pk)
1553 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1554#endif /* CONFIG_SAE_PK */
1555
1556 if (!((wpa_s->allowed_key_mgmts &
1557 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1558 return;
1559
1560 if (!wpa_s->rsnxe_len) {
1561 wpa_s->rsnxe_len = 3;
1562 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1563 wpa_s->rsnxe[1] = 1;
1564 wpa_s->rsnxe[2] = 0;
1565 }
1566
1567 wpa_s->rsnxe[2] |= capab;
1568}
1569
1570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001571/**
1572 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1573 * @wpa_s: Pointer to wpa_supplicant data
1574 * @bss: Scan results for the selected BSS, or %NULL if not available
1575 * @ssid: Configuration data for the selected network
1576 * @wpa_ie: Buffer for the WPA/RSN IE
1577 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1578 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001579 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 * Returns: 0 on success or -1 on failure
1581 *
1582 * This function is used to configure authentication and encryption parameters
1583 * based on the network configuration and scan result for the selected BSS (if
1584 * available).
1585 */
1586int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1587 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001588 u8 *wpa_ie, size_t *wpa_ie_len,
1589 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590{
1591 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001592 int sel, proto;
1593 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001594 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Sunil Ravi640215c2023-06-28 23:08:09 +00001595 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001596
1597 if (bss) {
1598 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1599 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001600 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001601 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001602 } else {
1603 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1604 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605
1606 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1607 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001608 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 (ie.key_mgmt & ssid->key_mgmt)) {
1610 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1611 proto = WPA_PROTO_RSN;
1612 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001613 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614 (ie.group_cipher & ssid->group_cipher) &&
1615 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1616 (ie.key_mgmt & ssid->key_mgmt)) {
1617 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1618 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001619#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001620 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1621 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1622 (ie.group_cipher & ssid->group_cipher) &&
1623 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1624 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001625 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001626 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001627 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1628 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1629 (ie.group_cipher & ssid->group_cipher) &&
1630 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1631 (ie.key_mgmt & ssid->key_mgmt)) {
1632 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1633 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001634#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 } else if (bss) {
1636 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001637 wpa_dbg(wpa_s, MSG_DEBUG,
1638 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1639 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1640 ssid->key_mgmt);
1641 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1642 MAC2STR(bss->bssid),
1643 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1644 bss_wpa ? " WPA" : "",
1645 bss_rsn ? " RSN" : "",
1646 bss_osen ? " OSEN" : "");
1647 if (bss_rsn) {
1648 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1649 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1650 wpa_dbg(wpa_s, MSG_DEBUG,
1651 "Could not parse RSN element");
1652 } else {
1653 wpa_dbg(wpa_s, MSG_DEBUG,
1654 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1655 ie.pairwise_cipher, ie.group_cipher,
1656 ie.key_mgmt);
1657 }
1658 }
1659 if (bss_wpa) {
1660 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1661 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1662 wpa_dbg(wpa_s, MSG_DEBUG,
1663 "Could not parse WPA element");
1664 } else {
1665 wpa_dbg(wpa_s, MSG_DEBUG,
1666 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1667 ie.pairwise_cipher, ie.group_cipher,
1668 ie.key_mgmt);
1669 }
1670 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671 return -1;
1672 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001673 if (ssid->proto & WPA_PROTO_OSEN)
1674 proto = WPA_PROTO_OSEN;
1675 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001676 proto = WPA_PROTO_RSN;
1677 else
1678 proto = WPA_PROTO_WPA;
1679 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1680 os_memset(&ie, 0, sizeof(ie));
1681 ie.group_cipher = ssid->group_cipher;
1682 ie.pairwise_cipher = ssid->pairwise_cipher;
1683 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001684 ie.mgmt_group_cipher = 0;
1685 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1686 if (ssid->group_mgmt_cipher &
1687 WPA_CIPHER_BIP_GMAC_256)
1688 ie.mgmt_group_cipher =
1689 WPA_CIPHER_BIP_GMAC_256;
1690 else if (ssid->group_mgmt_cipher &
1691 WPA_CIPHER_BIP_CMAC_256)
1692 ie.mgmt_group_cipher =
1693 WPA_CIPHER_BIP_CMAC_256;
1694 else if (ssid->group_mgmt_cipher &
1695 WPA_CIPHER_BIP_GMAC_128)
1696 ie.mgmt_group_cipher =
1697 WPA_CIPHER_BIP_GMAC_128;
1698 else
1699 ie.mgmt_group_cipher =
1700 WPA_CIPHER_AES_128_CMAC;
1701 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001702#ifdef CONFIG_OWE
1703 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1704 !ssid->owe_only &&
1705 !bss_wpa && !bss_rsn && !bss_osen) {
1706 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1707 wpa_s->wpa_proto = 0;
1708 *wpa_ie_len = 0;
1709 return 0;
1710 }
1711#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001712 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1713 "based on configuration");
1714 } else
1715 proto = ie.proto;
1716 }
1717
1718 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1719 "pairwise %d key_mgmt %d proto %d",
1720 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 if (ssid->ieee80211w) {
1722 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1723 ie.mgmt_group_cipher);
1724 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001726 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1728 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001729 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730
1731 if (bss || !wpa_s->ap_ies_from_associnfo) {
1732 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1733 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1734 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001735 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1736 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1737 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001738 return -1;
1739 }
1740
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001741#ifdef CONFIG_NO_WPA
1742 wpa_s->group_cipher = WPA_CIPHER_NONE;
1743 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1744#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001746 wpa_dbg(wpa_s, MSG_DEBUG,
1747 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1748 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001749 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1750 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1752 "cipher");
1753 return -1;
1754 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001755 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1756 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757
1758 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001759 wpa_dbg(wpa_s, MSG_DEBUG,
1760 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1761 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001762 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1763 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1765 "cipher");
1766 return -1;
1767 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001768 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1769 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001770#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001771
1772 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001773#ifdef CONFIG_SAE
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001774 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) &&
1775 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001776 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001777 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1778 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001779#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001780#ifdef CONFIG_IEEE80211R
1781 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1782 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1783 sel &= ~WPA_KEY_MGMT_FT;
1784#endif /* CONFIG_IEEE80211R */
1785 wpa_dbg(wpa_s, MSG_DEBUG,
1786 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1787 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001789#ifdef CONFIG_IEEE80211R
1790#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001791 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1792 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001793 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1794 wpa_dbg(wpa_s, MSG_DEBUG,
1795 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001796 if (!ssid->ft_eap_pmksa_caching &&
1797 pmksa_cache_get_current(wpa_s->wpa)) {
1798 /* PMKSA caching with FT may have interoperability
1799 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001800 wpa_dbg(wpa_s, MSG_DEBUG,
1801 "WPA: Disable PMKSA caching for FT/802.1X connection");
1802 pmksa_cache_clear_current(wpa_s->wpa);
1803 }
1804#endif /* CONFIG_SHA384 */
1805#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001806#ifdef CONFIG_SUITEB192
1807 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1808 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1809 wpa_dbg(wpa_s, MSG_DEBUG,
1810 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1811#endif /* CONFIG_SUITEB192 */
1812#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001813 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1814 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1815 wpa_dbg(wpa_s, MSG_DEBUG,
1816 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001817#endif /* CONFIG_SUITEB */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001818#ifdef CONFIG_SHA384
1819 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) {
1820 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384;
1821 wpa_dbg(wpa_s, MSG_DEBUG,
1822 "WPA: using KEY_MGMT 802.1X with SHA384");
1823#endif /* CONFIG_SHA384 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001824#ifdef CONFIG_FILS
1825#ifdef CONFIG_IEEE80211R
1826 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1827 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1828 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001829#endif /* CONFIG_IEEE80211R */
1830 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1831 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1832 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001833#ifdef CONFIG_IEEE80211R
1834 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1835 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1836 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1837#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001838 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1839 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1840 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1841#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001843 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1844 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1846 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001847 if (!ssid->ft_eap_pmksa_caching &&
1848 pmksa_cache_get_current(wpa_s->wpa)) {
1849 /* PMKSA caching with FT may have interoperability
1850 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001851 wpa_dbg(wpa_s, MSG_DEBUG,
1852 "WPA: Disable PMKSA caching for FT/802.1X connection");
1853 pmksa_cache_clear_current(wpa_s->wpa);
1854 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001855#endif /* CONFIG_IEEE80211R */
1856#ifdef CONFIG_DPP
1857 } else if (sel & WPA_KEY_MGMT_DPP) {
1858 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1859 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1860#endif /* CONFIG_DPP */
1861#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001862 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1863 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1864 wpa_dbg(wpa_s, MSG_DEBUG,
1865 "RSN: using KEY_MGMT FT/SAE (ext key)");
1866 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1867 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1868 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001869 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1870 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1871 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1872 } else if (sel & WPA_KEY_MGMT_SAE) {
1873 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1874 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1875#endif /* CONFIG_SAE */
1876#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1878 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1879 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1880#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1882 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1883 wpa_dbg(wpa_s, MSG_DEBUG,
1884 "WPA: using KEY_MGMT 802.1X with SHA256");
1885 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1886 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1887 wpa_dbg(wpa_s, MSG_DEBUG,
1888 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1890 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1891 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1892 } else if (sel & WPA_KEY_MGMT_PSK) {
1893 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1894 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1895 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1896 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1897 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001898#ifdef CONFIG_HS20
1899 } else if (sel & WPA_KEY_MGMT_OSEN) {
1900 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1901 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1902#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001903#ifdef CONFIG_OWE
1904 } else if (sel & WPA_KEY_MGMT_OWE) {
1905 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1906 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1907#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001908 } else {
1909 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1910 "authenticated key management type");
1911 return -1;
1912 }
1913
1914 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1915 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1916 wpa_s->pairwise_cipher);
1917 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1918
Hai Shalomc3565922019-10-28 11:58:20 -07001919 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001920 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1921 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001922 wpa_msg(wpa_s, MSG_INFO,
1923 "RSN: Management frame protection required but the selected AP does not enable it");
1924 return -1;
1925 }
1926
Hai Shalomc1a21442022-02-04 13:43:00 -08001927 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001928#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001929 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1930 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1931 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001932#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001933 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001934 if ((ssid->sae_password_id ||
1935 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001936 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1937 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1938 if (bss && is_6ghz_freq(bss->freq) &&
1939 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1940 wpa_dbg(wpa_s, MSG_DEBUG,
1941 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1942 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001943 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001944 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001945#ifdef CONFIG_SAE_PK
1946 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1947 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1948 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1949 ((ssid->sae_password &&
1950 sae_pk_valid_password(ssid->sae_password)) ||
1951 (!ssid->sae_password && ssid->passphrase &&
1952 sae_pk_valid_password(ssid->passphrase))));
1953#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001954 if (bss && is_6ghz_freq(bss->freq) &&
1955 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1956 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1957 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1958 MGMT_FRAME_PROTECTION_REQUIRED);
1959 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001960#ifdef CONFIG_TESTING_OPTIONS
1961 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1962 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001963 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1964 wpa_s->oci_freq_override_eapol);
1965 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1966 wpa_s->oci_freq_override_eapol_g2);
1967 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1968 wpa_s->oci_freq_override_ft_assoc);
1969 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1970 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001971 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1972 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001973#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001974
1975 /* Extended Key ID is only supported in infrastructure BSS so far */
1976 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1977 (ssid->proto & WPA_PROTO_RSN) &&
1978 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1979 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1980 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1981 int use_ext_key_id = 0;
1982
1983 wpa_msg(wpa_s, MSG_DEBUG,
1984 "WPA: Enable Extended Key ID support");
1985 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1986 wpa_s->conf->extended_key_id);
1987 if (bss_rsn &&
1988 wpa_s->conf->extended_key_id &&
1989 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1990 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1991 use_ext_key_id = 1;
1992 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1993 use_ext_key_id);
1994 } else {
1995 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1996 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1997 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998
Sunil Ravi640215c2023-06-28 23:08:09 +00001999 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
2000 * appropriate advertisement of the supported number of PTKSA receive
2001 * counters. In theory, this could be based on a driver capability, but
2002 * in practice all cases using WMM support at least eight replay
2003 * counters, so use a hardcoded value for now since there is no explicit
2004 * driver capability indication for this.
2005 *
2006 * In addition, claim WMM to be enabled if the AP supports it since it
2007 * is far more likely for any current device to support WMM. */
2008 wmm = wpa_s->connection_set &&
2009 (wpa_s->connection_ht || wpa_s->connection_vht ||
2010 wpa_s->connection_he || wpa_s->connection_eht);
2011 if (!wmm && bss)
2012 wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
2013 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2014
Sunil Ravi77d572f2023-01-17 23:58:31 +00002015 if (!skip_default_rsne) {
2016 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2017 wpa_ie_len)) {
2018 wpa_msg(wpa_s, MSG_WARNING,
2019 "RSN: Failed to generate RSNE/WPA IE");
2020 return -1;
2021 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022
Sunil Ravi77d572f2023-01-17 23:58:31 +00002023 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2024 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2025 &wpa_s->rsnxe_len)) {
2026 wpa_msg(wpa_s, MSG_WARNING,
2027 "RSN: Failed to generate RSNXE");
2028 return -1;
2029 }
Hai Shalomc3565922019-10-28 11:58:20 -07002030 }
2031
Hai Shalom021b0b52019-04-10 11:17:58 -07002032 if (0) {
2033#ifdef CONFIG_DPP
2034 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2035 /* Use PMK from DPP network introduction (PMKSA entry) */
2036 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002037#ifdef CONFIG_DPP2
2038 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2039#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002040#endif /* CONFIG_DPP */
2041 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002042 int psk_set = 0;
2043
Sunil Ravi77d572f2023-01-17 23:58:31 +00002044 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2045 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002046
Sunil Ravi77d572f2023-01-17 23:58:31 +00002047 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2048 psk) == 0) {
2049 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2050 NULL);
2051 psk_set = 1;
2052 }
2053 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002054 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002055
Roshan Pius3a1667e2018-07-03 15:17:14 -07002056 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002057 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002058 psk_set = 1;
2059
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002060 if (!psk_set) {
2061 wpa_msg(wpa_s, MSG_INFO,
2062 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002063 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002064 return -1;
2065 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002066#ifdef CONFIG_OWE
2067 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2068 /* OWE Diffie-Hellman exchange in (Re)Association
2069 * Request/Response frames set the PMK, so do not override it
2070 * here. */
2071#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002072 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2074
Hai Shalomfdcde762020-04-02 11:19:20 -07002075 if (ssid->mode != WPAS_MODE_IBSS &&
2076 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2077 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2078 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2079 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2080 wpa_msg(wpa_s, MSG_INFO,
2081 "Disable PTK0 rekey support - replaced with reconnect");
2082 wpa_s->deny_ptk0_rekey = 1;
2083 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2084 } else {
2085 wpa_s->deny_ptk0_rekey = 0;
2086 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2087 }
2088
Winnie Chen4138eec2022-11-10 16:32:53 +08002089#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302090 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002091 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2092 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002093 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2094 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302095 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2096 wpa_dbg(wpa_s, MSG_INFO,
2097 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2098 }
Sunil Ravif42be322022-11-04 03:31:21 +00002099#else
2100 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2101 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2102 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002103#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302104
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002105 return 0;
2106}
2107
2108
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002109static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
2110 struct wpa_bss *bss)
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002111{
Hai Shalomc1a21442022-02-04 13:43:00 -08002112 bool scs = true, mscs = true;
2113
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002114 *pos = 0x00;
2115
2116 switch (idx) {
2117 case 0: /* Bits 0-7 */
2118 break;
2119 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002120 if (wpa_s->conf->coloc_intf_reporting) {
2121 /* Bit 13 - Collocated Interference Reporting */
2122 *pos |= 0x20;
2123 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002124 break;
2125 case 2: /* Bits 16-23 */
2126#ifdef CONFIG_WNM
2127 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002128 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002129 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002130#endif /* CONFIG_WNM */
2131 break;
2132 case 3: /* Bits 24-31 */
2133#ifdef CONFIG_WNM
2134 *pos |= 0x02; /* Bit 25 - SSID List */
2135#endif /* CONFIG_WNM */
2136#ifdef CONFIG_INTERWORKING
2137 if (wpa_s->conf->interworking)
2138 *pos |= 0x80; /* Bit 31 - Interworking */
2139#endif /* CONFIG_INTERWORKING */
2140 break;
2141 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002142#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002143 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002144 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002145#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002146 break;
2147 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002148#ifdef CONFIG_HS20
2149 if (wpa_s->conf->hs20)
2150 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2151#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002152#ifdef CONFIG_MBO
2153 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2154#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002155 break;
2156 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002157#ifdef CONFIG_TESTING_OPTIONS
2158 if (wpa_s->disable_scs_support)
2159 scs = false;
2160#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002161 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
2162 /* Drop own SCS capability indication since the AP does
2163 * not support it. This is needed to avoid
2164 * interoperability issues with APs that get confused
2165 * with Extended Capabilities element. */
2166 scs = false;
2167 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002168 if (scs)
2169 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002170 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002171 case 7: /* Bits 56-63 */
2172 break;
2173 case 8: /* Bits 64-71 */
2174 if (wpa_s->conf->ftm_responder)
2175 *pos |= 0x40; /* Bit 70 - FTM responder */
2176 if (wpa_s->conf->ftm_initiator)
2177 *pos |= 0x80; /* Bit 71 - FTM initiator */
2178 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002179 case 9: /* Bits 72-79 */
2180#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002181 if (!wpa_s->disable_fils)
2182 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002183#endif /* CONFIG_FILS */
2184 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002185 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002186#ifdef CONFIG_TESTING_OPTIONS
2187 if (wpa_s->disable_mscs_support)
2188 mscs = false;
2189#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002190 if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
2191 /* Drop own MSCS capability indication since the AP does
2192 * not support it. This is needed to avoid
2193 * interoperability issues with APs that get confused
2194 * with Extended Capabilities element. */
2195 mscs = false;
2196 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002197 if (mscs)
2198 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002199 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002200 }
2201}
2202
2203
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002204int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
2205 size_t buflen, struct wpa_bss *bss)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002206{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002207 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002208 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002209
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002210 if (len < wpa_s->extended_capa_len)
2211 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002212 if (buflen < (size_t) len + 2) {
2213 wpa_printf(MSG_INFO,
2214 "Not enough room for building extended capabilities element");
2215 return -1;
2216 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002217
2218 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002219 *pos++ = len;
2220 for (i = 0; i < len; i++, pos++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002221 wpas_ext_capab_byte(wpa_s, pos, i, bss);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002222
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002223 if (i < wpa_s->extended_capa_len) {
2224 *pos &= ~wpa_s->extended_capa_mask[i];
2225 *pos |= wpa_s->extended_capa[i];
2226 }
2227 }
2228
2229 while (len > 0 && buf[1 + len] == 0) {
2230 len--;
2231 buf[1] = len;
2232 }
2233 if (len == 0)
2234 return 0;
2235
2236 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002237}
2238
2239
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002240static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2241 struct wpa_bss *test_bss)
2242{
2243 struct wpa_bss *bss;
2244
2245 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2246 if (bss == test_bss)
2247 return 1;
2248 }
2249
2250 return 0;
2251}
2252
2253
2254static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2255 struct wpa_ssid *test_ssid)
2256{
2257 struct wpa_ssid *ssid;
2258
2259 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2260 if (ssid == test_ssid)
2261 return 1;
2262 }
2263
2264 return 0;
2265}
2266
2267
2268int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2269 struct wpa_ssid *test_ssid)
2270{
2271 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2272 return 0;
2273
2274 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2275}
2276
2277
2278void wpas_connect_work_free(struct wpa_connect_work *cwork)
2279{
2280 if (cwork == NULL)
2281 return;
2282 os_free(cwork);
2283}
2284
2285
2286void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2287{
2288 struct wpa_connect_work *cwork;
2289 struct wpa_radio_work *work = wpa_s->connect_work;
2290
2291 if (!work)
2292 return;
2293
2294 wpa_s->connect_work = NULL;
2295 cwork = work->ctx;
2296 work->ctx = NULL;
2297 wpas_connect_work_free(cwork);
2298 radio_work_done(work);
2299}
2300
2301
Sunil Ravi77d572f2023-01-17 23:58:31 +00002302int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2303 enum wpas_mac_addr_style style,
2304 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002305{
2306 struct os_reltime now;
2307 u8 addr[ETH_ALEN];
2308
2309 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002310 /* Random addresses are valid within a given ESS so check
2311 * expiration/value only when continuing to use the same ESS. */
2312 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2313 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2314 /* Pregenerated addresses do not expire but their value
2315 * might have changed, so let's check that. */
2316 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2317 ETH_ALEN) == 0)
2318 return 0;
2319 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2320 wpa_s->last_mac_addr_change.usec != 0) &&
2321 !os_reltime_expired(
2322 &now,
2323 &wpa_s->last_mac_addr_change,
2324 wpa_s->conf->rand_addr_lifetime)) {
2325 wpa_msg(wpa_s, MSG_DEBUG,
2326 "Previously selected random MAC address has not yet expired");
2327 return 0;
2328 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002329 }
2330
2331 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002332 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002333 if (random_mac_addr(addr) < 0)
2334 return -1;
2335 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002336 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002337 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2338 if (random_mac_addr_keep_oui(addr) < 0)
2339 return -1;
2340 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002341 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2342 if (!ssid) {
2343 wpa_msg(wpa_s, MSG_INFO,
2344 "Invalid 'ssid' for address policy 3");
2345 return -1;
2346 }
2347 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2348 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002349 default:
2350 return -1;
2351 }
2352
2353 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2354 wpa_msg(wpa_s, MSG_INFO,
2355 "Failed to set random MAC address");
2356 return -1;
2357 }
2358
2359 os_get_reltime(&wpa_s->last_mac_addr_change);
2360 wpa_s->mac_addr_changed = 1;
2361 wpa_s->last_mac_addr_style = style;
2362
2363 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2364 wpa_msg(wpa_s, MSG_INFO,
2365 "Could not update MAC address information");
2366 return -1;
2367 }
2368
2369 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2370 MAC2STR(addr));
2371
Sunil Ravi77d572f2023-01-17 23:58:31 +00002372 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002373}
2374
2375
2376int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2377{
2378 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2379 !wpa_s->conf->preassoc_mac_addr)
2380 return 0;
2381
Sunil Ravi77d572f2023-01-17 23:58:31 +00002382 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2383 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002384}
2385
2386
Sunil Ravi036cec52023-03-29 11:35:17 -07002387void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2388 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002389{
2390#ifdef CONFIG_SAE
2391 int *groups = conf->sae_groups;
2392 int default_groups[] = { 19, 20, 21, 0 };
2393 const char *password;
2394
2395 if (!groups || groups[0] <= 0)
2396 groups = default_groups;
2397
2398 password = ssid->sae_password;
2399 if (!password)
2400 password = ssid->passphrase;
2401
Hai Shalom899fcc72020-10-19 14:38:18 -07002402 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002403 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002404 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002405 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002406 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002407 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002408 /* PT derivation not needed */
2409 sae_deinit_pt(ssid->pt);
2410 ssid->pt = NULL;
2411 return;
2412 }
2413
2414 if (ssid->pt)
2415 return; /* PT already derived */
2416 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2417 (const u8 *) password, os_strlen(password),
2418 ssid->sae_password_id);
2419#endif /* CONFIG_SAE */
2420}
2421
2422
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002423static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2424{
2425#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2426 os_free(wpa_s->sme.sae_rejected_groups);
2427 wpa_s->sme.sae_rejected_groups = NULL;
2428#ifdef CONFIG_TESTING_OPTIONS
2429 if (wpa_s->extra_sae_rejected_groups) {
2430 int i, *groups = wpa_s->extra_sae_rejected_groups;
2431
2432 for (i = 0; groups[i]; i++) {
2433 wpa_printf(MSG_DEBUG,
2434 "TESTING: Indicate rejection of an extra SAE group %d",
2435 groups[i]);
2436 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2437 groups[i]);
2438 }
2439 }
2440#endif /* CONFIG_TESTING_OPTIONS */
2441#endif /* CONFIG_SAE && CONFIG_SME */
2442}
2443
2444
Hai Shalom60840252021-02-19 19:02:11 -08002445int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2446{
2447 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2448 wpa_msg(wpa_s, MSG_INFO,
2449 "Could not restore permanent MAC address");
2450 return -1;
2451 }
2452 wpa_s->mac_addr_changed = 0;
2453 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2454 wpa_msg(wpa_s, MSG_INFO,
2455 "Could not update MAC address information");
2456 return -1;
2457 }
2458 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2459 return 0;
2460}
2461
2462
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002463static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2464
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465/**
2466 * wpa_supplicant_associate - Request association
2467 * @wpa_s: Pointer to wpa_supplicant data
2468 * @bss: Scan results for the selected BSS, or %NULL if not available
2469 * @ssid: Configuration data for the selected network
2470 *
2471 * This function is used to request %wpa_supplicant to associate with a BSS.
2472 */
2473void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2474 struct wpa_bss *bss, struct wpa_ssid *ssid)
2475{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002476 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002477 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002478
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002479 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002480 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002481
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002482 /*
2483 * If we are starting a new connection, any previously pending EAPOL
2484 * RX cannot be valid anymore.
2485 */
2486 wpabuf_free(wpa_s->pending_eapol_rx);
2487 wpa_s->pending_eapol_rx = NULL;
2488
Sunil Ravi77d572f2023-01-17 23:58:31 +00002489 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002490 rand_style = wpa_s->conf->mac_addr;
2491 else
2492 rand_style = ssid->mac_addr;
2493
Sunil Ravia04bd252022-05-02 22:54:18 -07002494 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002495 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002496 wmm_ac_clear_saved_tspecs(wpa_s);
2497 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002498 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002499#ifdef CONFIG_TESTING_OPTIONS
2500 wpa_s->testing_resend_assoc = 0;
2501#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002502
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002503 if (wpa_s->last_ssid == ssid) {
2504 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002505 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002506 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2507 wmm_ac_save_tspecs(wpa_s);
2508 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002509 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2510 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002511 }
Hai Shalomc3565922019-10-28 11:58:20 -07002512 } else {
2513#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002514 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002515#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002516 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002517#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002518 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002519#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002520
Sunil Ravi77d572f2023-01-17 23:58:31 +00002521 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2522 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2523
2524 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002525 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002526 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2527 status > 0) /* MAC changed */
2528 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2529 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2530 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002531 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002532 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002533 }
2534 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535
2536#ifdef CONFIG_IBSS_RSN
2537 ibss_rsn_deinit(wpa_s->ibss_rsn);
2538 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002539#else /* CONFIG_IBSS_RSN */
2540 if (ssid->mode == WPAS_MODE_IBSS &&
2541 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2542 wpa_msg(wpa_s, MSG_INFO,
2543 "IBSS RSN not supported in the build");
2544 return;
2545 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546#endif /* CONFIG_IBSS_RSN */
2547
2548 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2549 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2550#ifdef CONFIG_AP
2551 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2552 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2553 "mode");
2554 return;
2555 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002556 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2557 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002558 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2559 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002560 return;
2561 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002562 wpa_s->current_bss = bss;
2563#else /* CONFIG_AP */
2564 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2565 "the build");
2566#endif /* CONFIG_AP */
2567 return;
2568 }
2569
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002570 if (ssid->mode == WPAS_MODE_MESH) {
2571#ifdef CONFIG_MESH
2572 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2573 wpa_msg(wpa_s, MSG_INFO,
2574 "Driver does not support mesh mode");
2575 return;
2576 }
2577 if (bss)
2578 ssid->frequency = bss->freq;
2579 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002580 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002581 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2582 return;
2583 }
2584 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002585#else /* CONFIG_MESH */
2586 wpa_msg(wpa_s, MSG_ERROR,
2587 "mesh mode support not included in the build");
2588#endif /* CONFIG_MESH */
2589 return;
2590 }
2591
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002592 /*
2593 * Set WPA state machine configuration to match the selected network now
2594 * so that the information is available before wpas_start_assoc_cb()
2595 * gets called. This is needed at least for RSN pre-authentication where
2596 * candidate APs are added to a list based on scan result processing
2597 * before completion of the first association.
2598 */
2599 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2600
2601#ifdef CONFIG_DPP
2602 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2603 return;
2604#endif /* CONFIG_DPP */
2605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606#ifdef CONFIG_TDLS
2607 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002608 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609#endif /* CONFIG_TDLS */
2610
Hai Shalomc3565922019-10-28 11:58:20 -07002611#ifdef CONFIG_MBO
2612 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2613#endif /* CONFIG_MBO */
2614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002616 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 sme_authenticate(wpa_s, bss, ssid);
2618 return;
2619 }
2620
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002621 if (wpa_s->connect_work) {
2622 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2623 return;
2624 }
2625
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002626 if (radio_work_pending(wpa_s, "connect")) {
2627 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2628 return;
2629 }
2630
Dmitry Shmidt29333592017-01-09 12:27:11 -08002631#ifdef CONFIG_SME
2632 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2633 /* Clear possibly set auth_alg, if any, from last attempt. */
2634 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2635 }
2636#endif /* CONFIG_SME */
2637
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002638 wpas_abort_ongoing_scan(wpa_s);
2639
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002640 cwork = os_zalloc(sizeof(*cwork));
2641 if (cwork == NULL)
2642 return;
2643
2644 cwork->bss = bss;
2645 cwork->ssid = ssid;
2646
2647 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2648 wpas_start_assoc_cb, cwork) < 0) {
2649 os_free(cwork);
2650 }
2651}
2652
2653
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002654static int bss_is_ibss(struct wpa_bss *bss)
2655{
2656 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2657 IEEE80211_CAP_IBSS;
2658}
2659
2660
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002661static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2662 const struct wpa_ssid *ssid)
2663{
2664 enum hostapd_hw_mode hw_mode;
2665 struct hostapd_hw_modes *mode = NULL;
2666 u8 channel;
2667 int i;
2668
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002669 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2670 if (hw_mode == NUM_HOSTAPD_MODES)
2671 return 0;
2672 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2673 if (wpa_s->hw.modes[i].mode == hw_mode) {
2674 mode = &wpa_s->hw.modes[i];
2675 break;
2676 }
2677 }
2678
2679 if (!mode)
2680 return 0;
2681
2682 return mode->vht_capab != 0;
2683}
2684
2685
Hai Shalomc1a21442022-02-04 13:43:00 -08002686static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2687{
2688 int i;
2689
2690 for (i = channel; i < channel + 16; i += 4) {
2691 struct hostapd_channel_data *chan;
2692
2693 chan = hw_get_channel_chan(mode, i, NULL);
2694 if (!chan ||
2695 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2696 return false;
2697 }
2698
2699 return true;
2700}
2701
2702
Sunil Ravi036cec52023-03-29 11:35:17 -07002703static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2704 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002705{
Sunil Ravi036cec52023-03-29 11:35:17 -07002706 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002707
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002708 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2709 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2710
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002711 if (!bss_is_ibss(bss))
2712 continue;
2713
2714 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002715 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2716 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002717 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002718 return NULL;
2719}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002720
Sunil Ravi036cec52023-03-29 11:35:17 -07002721
2722static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2723 const struct wpa_ssid *ssid,
2724 struct hostapd_hw_modes *mode)
2725{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002726 /* For IBSS check HT_IBSS flag */
2727 if (ssid->mode == WPAS_MODE_IBSS &&
2728 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002729 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002730
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002731 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2732 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2733 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2734 wpa_printf(MSG_DEBUG,
2735 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002736 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002737 }
2738
Sunil Ravi036cec52023-03-29 11:35:17 -07002739 if (!ht_supported(mode))
2740 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002741
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002742#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002743 if (ssid->disable_ht)
2744 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002745#endif /* CONFIG_HT_OVERRIDES */
2746
Sunil Ravi036cec52023-03-29 11:35:17 -07002747 return true;
2748}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002749
Sunil Ravi036cec52023-03-29 11:35:17 -07002750
2751static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2752 const struct wpa_ssid *ssid,
2753 struct hostapd_hw_modes *mode)
2754{
2755 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2756 return false;
2757
2758 if (!drv_supports_vht(wpa_s, ssid))
2759 return false;
2760
2761 /* For IBSS check VHT_IBSS flag */
2762 if (ssid->mode == WPAS_MODE_IBSS &&
2763 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2764 return false;
2765
2766 if (!vht_supported(mode))
2767 return false;
2768
2769#ifdef CONFIG_VHT_OVERRIDES
2770 if (ssid->disable_vht)
2771 return false;
2772#endif /* CONFIG_VHT_OVERRIDES */
2773
2774 return true;
2775}
2776
2777
2778static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2779 const struct wpa_ssid *ssid,
2780 const struct hostapd_hw_modes *mode,
2781 int ieee80211_mode)
2782{
Hai Shalomfdcde762020-04-02 11:19:20 -07002783#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002784 if (ssid->disable_he)
2785 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002786#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002787
Sunil Ravi036cec52023-03-29 11:35:17 -07002788 switch (mode->mode) {
2789 case HOSTAPD_MODE_IEEE80211G:
2790 case HOSTAPD_MODE_IEEE80211B:
2791 case HOSTAPD_MODE_IEEE80211A:
2792 return mode->he_capab[ieee80211_mode].he_supported;
2793 default:
2794 return false;
2795 }
2796}
2797
2798
2799static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2800 const struct wpa_ssid *ssid,
2801 const struct hostapd_hw_modes *mode,
2802 int ieee80211_mode)
2803{
2804 if (ssid->disable_eht)
2805 return false;
2806
2807 switch(mode->mode) {
2808 case HOSTAPD_MODE_IEEE80211G:
2809 case HOSTAPD_MODE_IEEE80211B:
2810 case HOSTAPD_MODE_IEEE80211A:
2811 return mode->eht_capab[ieee80211_mode].eht_supported;
2812 default:
2813 return false;
2814 }
2815}
2816
2817
2818static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2819 const struct wpa_ssid *ssid,
2820 struct hostapd_hw_modes *mode,
2821 struct hostapd_freq_params *freq,
2822 int obss_scan) {
2823 int chan_idx;
2824 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2825 int i, res;
2826 unsigned int j;
2827 static const int ht40plus[] = {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002828 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
2829 149, 157, 165, 173, 184, 192
Sunil Ravi036cec52023-03-29 11:35:17 -07002830 };
2831 int ht40 = -1;
2832
2833 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002834 return;
2835
2836 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2837 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002838 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002839 break;
2840 pri_chan = NULL;
2841 }
2842 if (!pri_chan)
2843 return;
2844
2845 /* Check primary channel flags */
2846 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2847 return;
2848
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002849#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002850 if (ssid->disable_ht40)
2851 return;
2852#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002853
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002854 /* Check/setup HT40+/HT40- */
2855 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002856 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002857 ht40 = 1;
2858 break;
2859 }
2860 }
2861
2862 /* Find secondary channel */
2863 for (i = 0; i < mode->num_channels; i++) {
2864 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002865 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002866 break;
2867 sec_chan = NULL;
2868 }
2869 if (!sec_chan)
2870 return;
2871
2872 /* Check secondary channel flags */
2873 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2874 return;
2875
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002876 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002877 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2878 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002879 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002880 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2881 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002882 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002883 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002884
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002885 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002886 struct wpa_scan_results *scan_res;
2887
2888 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2889 if (scan_res == NULL) {
2890 /* Back to HT20 */
2891 freq->sec_channel_offset = 0;
2892 return;
2893 }
2894
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002895 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002896 switch (res) {
2897 case 0:
2898 /* Back to HT20 */
2899 freq->sec_channel_offset = 0;
2900 break;
2901 case 1:
2902 /* Configuration allowed */
2903 break;
2904 case 2:
2905 /* Switch pri/sec channels */
2906 freq->freq = hw_get_freq(mode, sec_chan->chan);
2907 freq->sec_channel_offset = -freq->sec_channel_offset;
2908 freq->channel = sec_chan->chan;
2909 break;
2910 default:
2911 freq->sec_channel_offset = 0;
2912 break;
2913 }
2914
2915 wpa_scan_results_free(scan_res);
2916 }
2917
2918 wpa_printf(MSG_DEBUG,
2919 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2920 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002921}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002922
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002923
Sunil Ravi036cec52023-03-29 11:35:17 -07002924static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2925 const struct wpa_ssid *ssid,
2926 struct hostapd_hw_modes *mode,
2927 struct hostapd_freq_params *freq,
2928 int ieee80211_mode, bool is_6ghz) {
2929 static const int bw80[] = {
2930 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2931 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2932 6515, 6595, 6675, 6755, 6835, 6915, 6995
2933 };
2934 static const int bw160[] = {
2935 5955, 6115, 6275, 6435, 6595, 6755, 6915
2936 };
2937 struct hostapd_freq_params vht_freq;
2938 int i;
2939 unsigned int j, k;
2940 int chwidth, seg0, seg1;
2941 u32 vht_caps = 0;
2942 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002943
Sunil Ravi036cec52023-03-29 11:35:17 -07002944 if (!freq->vht_enabled && !freq->he_enabled)
2945 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002946
Hai Shalomc1a21442022-02-04 13:43:00 -08002947 vht_freq = *freq;
2948
Sunil Ravi036cec52023-03-29 11:35:17 -07002949 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2950 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2951 seg1 = 0;
2952 if (freq->sec_channel_offset == 0) {
2953 seg0 = 0;
2954 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2955 if (freq->ht_enabled && !is_6ghz)
2956 goto skip_80mhz;
2957 }
2958 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2959 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002960
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002961 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002962 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2963 if (freq->freq >= bw80[j] &&
2964 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002965 break;
2966 }
2967
Hai Shalomc1a21442022-02-04 13:43:00 -08002968 if (j == ARRAY_SIZE(bw80) ||
2969 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002970 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002971
Sunil Ravi036cec52023-03-29 11:35:17 -07002972 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002973 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002974 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002975
Sunil8cd6f4d2022-06-28 18:40:46 +00002976 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002977 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002978 seg1 = 0;
2979
Sunil Ravi036cec52023-03-29 11:35:17 -07002980 /* In 160 MHz, the initial four 20 MHz channels were validated
2981 * above. If 160 MHz is supported, check the remaining four 20 MHz
2982 * channels for the total of 160 MHz bandwidth for 6 GHz.
2983 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002984 if ((mode->he_capab[ieee80211_mode].phy_cap[
2985 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002986 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2987 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002988 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2989 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002990 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002991 seg0 = channel + 14;
2992 break;
2993 }
2994 }
2995 }
2996
Sunil8cd6f4d2022-06-28 18:40:46 +00002997 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002998 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002999 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003000 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08003001 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003002 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08003003
3004 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
3005 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07003006 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08003007
3008 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003009 struct hostapd_channel_data *chan;
3010
3011 chan = hw_get_channel_chan(mode, i, NULL);
3012 if (!chan)
3013 continue;
3014
3015 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3016 HOSTAPD_CHAN_NO_IR |
3017 HOSTAPD_CHAN_RADAR))
3018 continue;
3019
3020 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00003021 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08003022 if (!is_6ghz)
3023 vht_caps |=
3024 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
3025 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003026 }
3027
Sunil8cd6f4d2022-06-28 18:40:46 +00003028 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003029 break;
3030 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003031 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003032 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003033 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003034 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3035 seg0 = 50;
3036 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003037 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003038 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3039 seg0 = 114;
3040 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003041 }
3042
Sunil Ravi036cec52023-03-29 11:35:17 -07003043skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003044 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003045 freq->channel, ssid->enable_edmg,
3046 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003047 freq->vht_enabled, freq->he_enabled,
3048 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003049 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003050 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003051 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003052 &mode->eht_capab[ieee80211_mode]) != 0)
3053 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003054
3055 *freq = vht_freq;
3056
3057 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3058 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003059 return true;
3060}
3061
3062
3063void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3064 const struct wpa_ssid *ssid,
3065 struct hostapd_freq_params *freq)
3066{
3067 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3068 enum hostapd_hw_mode hw_mode;
3069 struct hostapd_hw_modes *mode = NULL;
3070 int i, obss_scan = 1;
3071 u8 channel;
3072 bool is_6ghz;
3073
3074 freq->freq = ssid->frequency;
3075
3076 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3077 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3078
3079 if (bss) {
3080 wpa_printf(MSG_DEBUG,
3081 "IBSS already found in scan results, adjust control freq: %d",
3082 bss->freq);
3083 freq->freq = bss->freq;
3084 obss_scan = 0;
3085 }
3086 }
3087
3088 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3089 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3090 if (wpa_s->hw.modes[i].mode == hw_mode &&
3091 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3092 NULL) != NULL) {
3093 mode = &wpa_s->hw.modes[i];
3094 break;
3095 }
3096 }
3097
3098 if (!mode)
3099 return;
3100
3101 is_6ghz = is_6ghz_freq(freq->freq);
3102
3103 freq->ht_enabled = 0;
3104 freq->vht_enabled = 0;
3105 freq->he_enabled = 0;
3106 freq->eht_enabled = 0;
3107
3108 if (!is_6ghz)
3109 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3110 if (freq->ht_enabled)
3111 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3112 if (freq->vht_enabled || is_6ghz)
3113 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3114 ieee80211_mode);
3115 freq->channel = channel;
3116 /* Setup higher BW only for 5 GHz */
3117 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3118 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3119 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3120 ieee80211_mode, is_6ghz))
3121 freq->he_enabled = freq->vht_enabled = false;
3122 }
3123
3124 if (freq->he_enabled)
3125 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3126 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003127}
3128
3129
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003130#ifdef CONFIG_FILS
3131static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3132 size_t ie_buf_len)
3133{
3134 struct fils_hlp_req *req;
3135 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3136 const u8 *pos;
3137 u8 *buf = ie_buf;
3138
3139 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3140 list) {
3141 rem_len = ie_buf_len - ie_len;
3142 pos = wpabuf_head(req->pkt);
3143 hdr_len = 1 + 2 * ETH_ALEN + 6;
3144 hlp_len = wpabuf_len(req->pkt);
3145
3146 if (rem_len < 2 + hdr_len + hlp_len) {
3147 wpa_printf(MSG_ERROR,
3148 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3149 (unsigned long) rem_len,
3150 (unsigned long) (2 + hdr_len + hlp_len));
3151 break;
3152 }
3153
3154 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3155 /* Element ID */
3156 *buf++ = WLAN_EID_EXTENSION;
3157 /* Length */
3158 *buf++ = len;
3159 /* Element ID Extension */
3160 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3161 /* Destination MAC address */
3162 os_memcpy(buf, req->dst, ETH_ALEN);
3163 buf += ETH_ALEN;
3164 /* Source MAC address */
3165 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3166 buf += ETH_ALEN;
3167 /* LLC/SNAP Header */
3168 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3169 buf += 6;
3170 /* HLP Packet */
3171 os_memcpy(buf, pos, len - hdr_len);
3172 buf += len - hdr_len;
3173 pos += len - hdr_len;
3174
3175 hlp_len -= len - hdr_len;
3176 ie_len += 2 + len;
3177 rem_len -= 2 + len;
3178
3179 while (hlp_len) {
3180 len = (hlp_len > 255) ? 255 : hlp_len;
3181 if (rem_len < 2 + len)
3182 break;
3183 *buf++ = WLAN_EID_FRAGMENT;
3184 *buf++ = len;
3185 os_memcpy(buf, pos, len);
3186 buf += len;
3187 pos += len;
3188
3189 hlp_len -= len;
3190 ie_len += 2 + len;
3191 rem_len -= 2 + len;
3192 }
3193 }
3194
3195 return ie_len;
3196}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003197
3198
3199int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3200{
3201 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3202 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3203 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3204 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3205}
3206
3207
3208int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3209{
3210#ifdef CONFIG_FILS_SK_PFS
3211 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3212 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3213#else /* CONFIG_FILS_SK_PFS */
3214 return 0;
3215#endif /* CONFIG_FILS_SK_PFS */
3216}
3217
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003218#endif /* CONFIG_FILS */
3219
3220
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003221bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss)
3222{
3223 const u8 *wfa_capa;
3224
3225 if (!bss)
3226 return false;
3227
3228 /* Get WFA capability from Beacon or Probe Response frame elements */
3229 wfa_capa = wpa_bss_get_vendor_ie(bss, WFA_CAPA_IE_VENDOR_TYPE);
3230 if (!wfa_capa)
3231 wfa_capa = wpa_bss_get_vendor_ie_beacon(
3232 bss, WFA_CAPA_IE_VENDOR_TYPE);
3233
3234 if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
3235 !(wfa_capa[7] & WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC)) {
3236 /* AP does not enable QM non EHT traffic description policy */
3237 return false;
3238 }
3239
3240 return true;
3241}
3242
3243
Hai Shalomc1a21442022-02-04 13:43:00 -08003244static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3245 struct wpa_bss *bss,
3246 u8 *wpa_ie, size_t wpa_ie_len,
3247 size_t max_wpa_ie_len)
3248{
3249 struct wpabuf *wfa_ie = NULL;
3250 u8 wfa_capa[1];
3251 size_t wfa_ie_len, buf_len;
3252
3253 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3254 if (wpa_s->enable_dscp_policy_capa)
3255 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3256
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003257 if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
3258 wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
3259
Hai Shalomc1a21442022-02-04 13:43:00 -08003260 if (!wfa_capa[0])
3261 return wpa_ie_len;
3262
3263 /* Wi-Fi Alliance element */
3264 buf_len = 1 + /* Element ID */
3265 1 + /* Length */
3266 3 + /* OUI */
3267 1 + /* OUI Type */
3268 1 + /* Capabilities Length */
3269 sizeof(wfa_capa); /* Capabilities */
3270 wfa_ie = wpabuf_alloc(buf_len);
3271 if (!wfa_ie)
3272 return wpa_ie_len;
3273
3274 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3275 wpabuf_put_u8(wfa_ie, buf_len - 2);
3276 wpabuf_put_be24(wfa_ie, OUI_WFA);
3277 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3278 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3279 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3280
3281 wfa_ie_len = wpabuf_len(wfa_ie);
3282 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3283 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3284 wfa_ie);
3285 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3286 wfa_ie_len);
3287 wpa_ie_len += wfa_ie_len;
3288 }
3289
3290 wpabuf_free(wfa_ie);
3291 return wpa_ie_len;
3292}
3293
3294
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003295static u8 * wpas_populate_assoc_ies(
3296 struct wpa_supplicant *wpa_s,
3297 struct wpa_bss *bss, struct wpa_ssid *ssid,
3298 struct wpa_driver_associate_params *params,
3299 enum wpa_drv_update_connect_params_mask *mask)
3300{
3301 u8 *wpa_ie;
3302 size_t max_wpa_ie_len = 500;
3303 size_t wpa_ie_len;
3304 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003305#ifdef CONFIG_MBO
3306 const u8 *mbo_ie;
3307#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303308#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3309 int pmksa_cached = 0;
3310#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003311#ifdef CONFIG_FILS
3312 const u8 *realm, *username, *rrk;
3313 size_t realm_len, username_len, rrk_len;
3314 u16 next_seq_num;
3315 struct fils_hlp_req *req;
3316
3317 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3318 list) {
3319 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3320 2 + 2 * wpabuf_len(req->pkt) / 255;
3321 }
3322#endif /* CONFIG_FILS */
3323
3324 wpa_ie = os_malloc(max_wpa_ie_len);
3325 if (!wpa_ie) {
3326 wpa_printf(MSG_ERROR,
3327 "Failed to allocate connect IE buffer for %lu bytes",
3328 (unsigned long) max_wpa_ie_len);
3329 return NULL;
3330 }
3331
3332 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3333 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3334 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3335 int try_opportunistic;
3336 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003337 const u8 *addr = bss->bssid;
3338
Sunil Ravi036cec52023-03-29 11:35:17 -07003339 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3340 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3341 !is_zero_ether_addr(bss->mld_addr))
3342 addr = bss->mld_addr;
3343
3344 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3345 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003346 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003347
3348 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3349 wpa_s->conf->okc :
3350 ssid->proactive_key_caching) &&
3351 (ssid->proto & WPA_PROTO_RSN);
3352#ifdef CONFIG_FILS
3353 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3354 cache_id = wpa_bss_get_fils_cache_id(bss);
3355#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003356 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003357 ssid, try_opportunistic,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003358 cache_id, 0, false) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003359 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303360#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3361 pmksa_cached = 1;
3362#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003363 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003364 wpa_ie_len = max_wpa_ie_len;
3365 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003366 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003367 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3368 "key management and encryption suites");
3369 os_free(wpa_ie);
3370 return NULL;
3371 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003372#ifdef CONFIG_HS20
3373 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3374 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3375 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3376 wpa_ie_len = max_wpa_ie_len;
3377 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003378 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003379 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3380 "key management and encryption suites");
3381 os_free(wpa_ie);
3382 return NULL;
3383 }
3384#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003385 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3386 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3387 /*
3388 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3389 * use non-WPA since the scan results did not indicate that the
3390 * AP is using WPA or WPA2.
3391 */
3392 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3393 wpa_ie_len = 0;
3394 wpa_s->wpa_proto = 0;
3395 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3396 wpa_ie_len = max_wpa_ie_len;
3397 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003398 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003399 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3400 "key management and encryption suites (no "
3401 "scan results)");
3402 os_free(wpa_ie);
3403 return NULL;
3404 }
3405#ifdef CONFIG_WPS
3406 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3407 struct wpabuf *wps_ie;
3408 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3409 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3410 wpa_ie_len = wpabuf_len(wps_ie);
3411 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3412 } else
3413 wpa_ie_len = 0;
3414 wpabuf_free(wps_ie);
3415 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3416 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3417 params->wps = WPS_MODE_PRIVACY;
3418 else
3419 params->wps = WPS_MODE_OPEN;
3420 wpa_s->wpa_proto = 0;
3421#endif /* CONFIG_WPS */
3422 } else {
3423 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3424 wpa_ie_len = 0;
3425 wpa_s->wpa_proto = 0;
3426 }
3427
3428#ifdef IEEE8021X_EAPOL
3429 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3430 if (ssid->leap) {
3431 if (ssid->non_leap == 0)
3432 algs = WPA_AUTH_ALG_LEAP;
3433 else
3434 algs |= WPA_AUTH_ALG_LEAP;
3435 }
3436 }
3437
3438#ifdef CONFIG_FILS
3439 /* Clear FILS association */
3440 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3441
3442 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3443 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3444 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3445 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003446 &next_seq_num, &rrk, &rrk_len) == 0 &&
3447 (!wpa_s->last_con_fail_realm ||
3448 wpa_s->last_con_fail_realm_len != realm_len ||
3449 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 algs = WPA_AUTH_ALG_FILS;
3451 params->fils_erp_username = username;
3452 params->fils_erp_username_len = username_len;
3453 params->fils_erp_realm = realm;
3454 params->fils_erp_realm_len = realm_len;
3455 params->fils_erp_next_seq_num = next_seq_num;
3456 params->fils_erp_rrk = rrk;
3457 params->fils_erp_rrk_len = rrk_len;
3458
3459 if (mask)
3460 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303461 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3462 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3463 pmksa_cached) {
3464 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003465 }
3466#endif /* CONFIG_FILS */
3467#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003468#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003469 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003470 algs = WPA_AUTH_ALG_SAE;
3471#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003472
3473 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3474 if (ssid->auth_alg) {
3475 algs = ssid->auth_alg;
3476 wpa_dbg(wpa_s, MSG_DEBUG,
3477 "Overriding auth_alg selection: 0x%x", algs);
3478 }
3479
Hai Shalom5f92bc92019-04-18 11:54:11 -07003480#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303481 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003482 wpa_dbg(wpa_s, MSG_DEBUG,
3483 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3484 algs = WPA_AUTH_ALG_OPEN;
3485 }
3486#endif /* CONFIG_SAE */
3487
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003488#ifdef CONFIG_P2P
3489 if (wpa_s->global->p2p) {
3490 u8 *pos;
3491 size_t len;
3492 int res;
3493 pos = wpa_ie + wpa_ie_len;
3494 len = max_wpa_ie_len - wpa_ie_len;
3495 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3496 ssid->p2p_group);
3497 if (res >= 0)
3498 wpa_ie_len += res;
3499 }
3500
3501 wpa_s->cross_connect_disallowed = 0;
3502 if (bss) {
3503 struct wpabuf *p2p;
3504 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3505 if (p2p) {
3506 wpa_s->cross_connect_disallowed =
3507 p2p_get_cross_connect_disallowed(p2p);
3508 wpabuf_free(p2p);
3509 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3510 "connection",
3511 wpa_s->cross_connect_disallowed ?
3512 "disallows" : "allows");
3513 }
3514 }
3515
3516 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3517#endif /* CONFIG_P2P */
3518
3519 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003520 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003521 wpa_ie + wpa_ie_len,
3522 max_wpa_ie_len -
3523 wpa_ie_len);
3524 }
3525
3526 /*
3527 * Workaround: Add Extended Capabilities element only if the AP
3528 * included this element in Beacon/Probe Response frames. Some older
3529 * APs seem to have interoperability issues if this element is
3530 * included, so while the standard may require us to include the
3531 * element in all cases, it is justifiable to skip it to avoid
3532 * interoperability issues.
3533 */
3534 if (ssid->p2p_group)
3535 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3536 else
3537 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3538
3539 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3540 u8 ext_capab[18];
3541 int ext_capab_len;
3542 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003543 sizeof(ext_capab), bss);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003544 if (ext_capab_len > 0 &&
3545 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3546 u8 *pos = wpa_ie;
3547 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3548 pos += 2 + pos[1];
3549 os_memmove(pos + ext_capab_len, pos,
3550 wpa_ie_len - (pos - wpa_ie));
3551 wpa_ie_len += ext_capab_len;
3552 os_memcpy(pos, ext_capab, ext_capab_len);
3553 }
3554 }
3555
3556#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003557 if (is_hs20_network(wpa_s, ssid, bss)
3558#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3559 && is_hs20_config(wpa_s)
3560#endif /* ANDROID */
3561 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003562 struct wpabuf *hs20;
3563
Roshan Pius3a1667e2018-07-03 15:17:14 -07003564 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003565 if (hs20) {
3566 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3567 size_t len;
3568
Hai Shalom74f70d42019-02-11 14:42:39 -08003569 wpas_hs20_add_indication(hs20, pps_mo_id,
3570 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003571 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003572 len = max_wpa_ie_len - wpa_ie_len;
3573 if (wpabuf_len(hs20) <= len) {
3574 os_memcpy(wpa_ie + wpa_ie_len,
3575 wpabuf_head(hs20), wpabuf_len(hs20));
3576 wpa_ie_len += wpabuf_len(hs20);
3577 }
3578 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003579 }
3580 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003581 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003582#endif /* CONFIG_HS20 */
3583
3584 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3585 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3586 size_t len;
3587
3588 len = max_wpa_ie_len - wpa_ie_len;
3589 if (wpabuf_len(buf) <= len) {
3590 os_memcpy(wpa_ie + wpa_ie_len,
3591 wpabuf_head(buf), wpabuf_len(buf));
3592 wpa_ie_len += wpabuf_len(buf);
3593 }
3594 }
3595
3596#ifdef CONFIG_FST
3597 if (wpa_s->fst_ies) {
3598 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3599
3600 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3601 os_memcpy(wpa_ie + wpa_ie_len,
3602 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3603 wpa_ie_len += fst_ies_len;
3604 }
3605 }
3606#endif /* CONFIG_FST */
3607
3608#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003609 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003610 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003611 int len;
3612
3613 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003614 max_wpa_ie_len - wpa_ie_len,
3615 !!mbo_attr_from_mbo_ie(mbo_ie,
3616 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003617 if (len >= 0)
3618 wpa_ie_len += len;
3619 }
3620#endif /* CONFIG_MBO */
3621
3622#ifdef CONFIG_FILS
3623 if (algs == WPA_AUTH_ALG_FILS) {
3624 size_t len;
3625
3626 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3627 max_wpa_ie_len - wpa_ie_len);
3628 wpa_ie_len += len;
3629 }
3630#endif /* CONFIG_FILS */
3631
3632#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003633#ifdef CONFIG_TESTING_OPTIONS
3634 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3635 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3636 } else
3637#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003638 if (algs == WPA_AUTH_ALG_OPEN &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003639 ssid->key_mgmt == WPA_KEY_MGMT_OWE &&
3640 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003641 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003642 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003643
Roshan Pius3a1667e2018-07-03 15:17:14 -07003644 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003645 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003646 } else if (wpa_s->assoc_status_code ==
3647 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003648 if (wpa_s->last_owe_group == 19)
3649 group = 20;
3650 else if (wpa_s->last_owe_group == 20)
3651 group = 21;
3652 else
3653 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003654 } else {
3655 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003656 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003657
Roshan Pius3a1667e2018-07-03 15:17:14 -07003658 wpa_s->last_owe_group = group;
3659 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003660 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3661 if (owe_ie &&
3662 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3663 os_memcpy(wpa_ie + wpa_ie_len,
3664 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3665 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003666 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003667 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003668 }
3669#endif /* CONFIG_OWE */
3670
Hai Shalom021b0b52019-04-10 11:17:58 -07003671#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003672 if (DPP_VERSION > 1 &&
3673 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003674 ssid->dpp_netaccesskey &&
3675 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003676 struct rsn_pmksa_cache_entry *pmksa;
3677
3678 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3679 if (!pmksa || !pmksa->dpp_pfs)
3680 goto pfs_fail;
3681
Hai Shalom021b0b52019-04-10 11:17:58 -07003682 dpp_pfs_free(wpa_s->dpp_pfs);
3683 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3684 ssid->dpp_netaccesskey_len);
3685 if (!wpa_s->dpp_pfs) {
3686 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3687 /* Try to continue without PFS */
3688 goto pfs_fail;
3689 }
3690 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3691 max_wpa_ie_len - wpa_ie_len) {
3692 os_memcpy(wpa_ie + wpa_ie_len,
3693 wpabuf_head(wpa_s->dpp_pfs->ie),
3694 wpabuf_len(wpa_s->dpp_pfs->ie));
3695 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3696 }
3697 }
3698pfs_fail:
3699#endif /* CONFIG_DPP2 */
3700
Roshan Pius3a1667e2018-07-03 15:17:14 -07003701#ifdef CONFIG_IEEE80211R
3702 /*
3703 * Add MDIE under these conditions: the network profile allows FT,
3704 * the AP supports FT, and the mobility domain ID matches.
3705 */
3706 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3707 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3708
3709 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3710 size_t len = 0;
3711 const u8 *md = mdie + 2;
3712 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3713
3714 if (os_memcmp(md, wpa_md,
3715 MOBILITY_DOMAIN_ID_LEN) == 0) {
3716 /* Add mobility domain IE */
3717 len = wpa_ft_add_mdie(
3718 wpa_s->wpa, wpa_ie + wpa_ie_len,
3719 max_wpa_ie_len - wpa_ie_len, mdie);
3720 wpa_ie_len += len;
3721 }
3722#ifdef CONFIG_SME
3723 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003724 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003725 wpa_dbg(wpa_s, MSG_DEBUG,
3726 "SME: Trying to use FT over-the-air");
3727 algs |= WPA_AUTH_ALG_FT;
3728 }
3729#endif /* CONFIG_SME */
3730 }
3731 }
3732#endif /* CONFIG_IEEE80211R */
3733
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003734#ifdef CONFIG_TESTING_OPTIONS
3735 if (wpa_s->rsnxe_override_assoc &&
3736 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3737 max_wpa_ie_len - wpa_ie_len) {
3738 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3739 os_memcpy(wpa_ie + wpa_ie_len,
3740 wpabuf_head(wpa_s->rsnxe_override_assoc),
3741 wpabuf_len(wpa_s->rsnxe_override_assoc));
3742 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3743 } else
3744#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003745 if (wpa_s->rsnxe_len > 0 &&
3746 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3747 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3748 wpa_ie_len += wpa_s->rsnxe_len;
3749 }
3750
Hai Shalomc1a21442022-02-04 13:43:00 -08003751#ifdef CONFIG_TESTING_OPTIONS
3752 if (wpa_s->disable_mscs_support)
3753 goto mscs_end;
3754#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003755 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3756 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003757 struct wpabuf *mscs_ie;
3758 size_t mscs_ie_len, buf_len;
3759
Hai Shalom899fcc72020-10-19 14:38:18 -07003760 buf_len = 3 + /* MSCS descriptor IE header */
3761 1 + /* Request type */
3762 2 + /* User priority control */
3763 4 + /* Stream timeout */
3764 3 + /* TCLAS Mask IE header */
3765 wpa_s->robust_av.frame_classifier_len;
3766 mscs_ie = wpabuf_alloc(buf_len);
3767 if (!mscs_ie) {
3768 wpa_printf(MSG_INFO,
3769 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003770 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003771 }
3772
3773 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3774 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3775 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3776 mscs_ie_len = wpabuf_len(mscs_ie);
3777 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3778 mscs_ie_len);
3779 wpa_ie_len += mscs_ie_len;
3780 }
3781
3782 wpabuf_free(mscs_ie);
3783 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003784mscs_end:
3785
3786 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3787 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003788
Hai Shalom74f70d42019-02-11 14:42:39 -08003789 if (ssid->multi_ap_backhaul_sta) {
3790 size_t multi_ap_ie_len;
3791
3792 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3793 max_wpa_ie_len - wpa_ie_len,
3794 MULTI_AP_BACKHAUL_STA);
3795 if (multi_ap_ie_len == 0) {
3796 wpa_printf(MSG_ERROR,
3797 "Multi-AP: Failed to build Multi-AP IE");
3798 os_free(wpa_ie);
3799 return NULL;
3800 }
3801 wpa_ie_len += multi_ap_ie_len;
3802 }
3803
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003804 params->wpa_ie = wpa_ie;
3805 params->wpa_ie_len = wpa_ie_len;
3806 params->auth_alg = algs;
3807 if (mask)
3808 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3809
3810 return wpa_ie;
3811}
3812
3813
Hai Shalomc3565922019-10-28 11:58:20 -07003814#ifdef CONFIG_OWE
3815static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3816{
3817 struct wpa_driver_associate_params params;
3818 u8 *wpa_ie;
3819
3820 os_memset(&params, 0, sizeof(params));
3821 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3822 wpa_s->current_ssid, &params, NULL);
3823 if (!wpa_ie)
3824 return;
3825
3826 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3827 os_free(wpa_ie);
3828}
3829#endif /* CONFIG_OWE */
3830
3831
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003832#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3833static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3834{
3835 struct wpa_driver_associate_params params;
3836 enum wpa_drv_update_connect_params_mask mask = 0;
3837 u8 *wpa_ie;
3838
3839 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3840 return; /* nothing to do */
3841
3842 os_memset(&params, 0, sizeof(params));
3843 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3844 wpa_s->current_ssid, &params, &mask);
3845 if (!wpa_ie)
3846 return;
3847
Hai Shalomc1a21442022-02-04 13:43:00 -08003848 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3849 wpa_s->auth_alg = params.auth_alg;
3850 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003851 }
3852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003853 os_free(wpa_ie);
3854}
3855#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3856
3857
Hai Shalomc3565922019-10-28 11:58:20 -07003858static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3859{
3860 if (!edmg_ie || edmg_ie[1] < 6)
3861 return 0;
3862 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3863}
3864
3865
3866static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3867{
3868 if (!edmg_ie || edmg_ie[1] < 6)
3869 return 0;
3870 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3871}
3872
3873
3874/* Returns the intersection of two EDMG configurations.
3875 * Note: The current implementation is limited to CB2 only (CB1 included),
3876 * i.e., the implementation supports up to 2 contiguous channels.
3877 * For supporting non-contiguous (aggregated) channels and for supporting
3878 * CB3 and above, this function will need to be extended.
3879 */
3880static struct ieee80211_edmg_config
3881get_edmg_intersection(struct ieee80211_edmg_config a,
3882 struct ieee80211_edmg_config b,
3883 u8 primary_channel)
3884{
3885 struct ieee80211_edmg_config result;
3886 int i, contiguous = 0;
3887 int max_contiguous = 0;
3888
3889 result.channels = b.channels & a.channels;
3890 if (!result.channels) {
3891 wpa_printf(MSG_DEBUG,
3892 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3893 a.channels, b.channels);
3894 goto fail;
3895 }
3896
3897 if (!(result.channels & BIT(primary_channel - 1))) {
3898 wpa_printf(MSG_DEBUG,
3899 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3900 primary_channel, result.channels);
3901 goto fail;
3902 }
3903
3904 /* Find max contiguous channels */
3905 for (i = 0; i < 6; i++) {
3906 if (result.channels & BIT(i))
3907 contiguous++;
3908 else
3909 contiguous = 0;
3910
3911 if (contiguous > max_contiguous)
3912 max_contiguous = contiguous;
3913 }
3914
3915 /* Assuming AP and STA supports ONLY contiguous channels,
3916 * bw configuration can have value between 4-7.
3917 */
3918 if ((b.bw_config < a.bw_config))
3919 result.bw_config = b.bw_config;
3920 else
3921 result.bw_config = a.bw_config;
3922
3923 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3924 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3925 wpa_printf(MSG_DEBUG,
3926 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3927 max_contiguous);
3928 goto fail;
3929 }
3930
3931 return result;
3932
3933fail:
3934 result.channels = 0;
3935 result.bw_config = 0;
3936 return result;
3937}
3938
3939
3940static struct ieee80211_edmg_config
3941get_supported_edmg(struct wpa_supplicant *wpa_s,
3942 struct hostapd_freq_params *freq,
3943 struct ieee80211_edmg_config request_edmg)
3944{
3945 enum hostapd_hw_mode hw_mode;
3946 struct hostapd_hw_modes *mode = NULL;
3947 u8 primary_channel;
3948
3949 if (!wpa_s->hw.modes)
3950 goto fail;
3951
3952 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3953 if (hw_mode == NUM_HOSTAPD_MODES)
3954 goto fail;
3955
Hai Shalom60840252021-02-19 19:02:11 -08003956 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003957 if (!mode)
3958 goto fail;
3959
3960 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3961
3962fail:
3963 request_edmg.channels = 0;
3964 request_edmg.bw_config = 0;
3965 return request_edmg;
3966}
3967
3968
Hai Shalom021b0b52019-04-10 11:17:58 -07003969#ifdef CONFIG_MBO
3970void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3971{
3972 struct wpa_driver_associate_params params;
3973 u8 *wpa_ie;
3974
3975 /*
3976 * Update MBO connect params only in case of change of MBO attributes
3977 * when connected, if the AP support MBO.
3978 */
3979
3980 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3981 !wpa_s->current_bss ||
3982 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3983 return;
3984
3985 os_memset(&params, 0, sizeof(params));
3986 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3987 wpa_s->current_ssid, &params, NULL);
3988 if (!wpa_ie)
3989 return;
3990
3991 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3992 os_free(wpa_ie);
3993}
3994#endif /* CONFIG_MBO */
3995
3996
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003997static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3998{
3999 struct wpa_connect_work *cwork = work->ctx;
4000 struct wpa_bss *bss = cwork->bss;
4001 struct wpa_ssid *ssid = cwork->ssid;
4002 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004003 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07004004 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07004005 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004006 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004007 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004008 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07004009#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004010 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004011#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004012 int assoc_failed = 0;
4013 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07004014 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004015#ifdef CONFIG_HT_OVERRIDES
4016 struct ieee80211_ht_capabilities htcaps;
4017 struct ieee80211_ht_capabilities htcaps_mask;
4018#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004019#ifdef CONFIG_VHT_OVERRIDES
4020 struct ieee80211_vht_capabilities vhtcaps;
4021 struct ieee80211_vht_capabilities vhtcaps_mask;
4022#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004023
Hai Shalomc1a21442022-02-04 13:43:00 -08004024 wpa_s->roam_in_progress = false;
4025#ifdef CONFIG_WNM
4026 wpa_s->bss_trans_mgmt_in_progress = false;
4027#endif /* CONFIG_WNM */
4028
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004029 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004030 if (work->started) {
4031 wpa_s->connect_work = NULL;
4032
4033 /* cancel possible auth. timeout */
4034 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
4035 NULL);
4036 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004037 wpas_connect_work_free(cwork);
4038 return;
4039 }
4040
4041 wpa_s->connect_work = work;
4042
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004043 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
4044 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004045 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
4046 wpas_connect_work_done(wpa_s);
4047 return;
4048 }
4049
Sunil Ravi640215c2023-06-28 23:08:09 +00004050 /*
4051 * Set the current AP's BSSID (for non-MLO connection) or MLD address
4052 * (for MLO connection) as the previous BSSID for reassociation requests
4053 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
4054 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4055 * will be zero.
4056 */
4057 os_memcpy(prev_bssid,
4058 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4059 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 os_memset(&params, 0, sizeof(params));
4061 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004062 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004063
4064 /* Starting new association, so clear the possibly used WPA IE from the
4065 * previous association. */
4066 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4067 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4068 wpa_s->rsnxe_len = 0;
4069 wpa_s->mscs_setup_done = false;
4070
4071 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4072 if (!wpa_ie) {
4073 wpas_connect_work_done(wpa_s);
4074 return;
4075 }
4076
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004077 if (bss &&
4078 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004079#ifdef CONFIG_IEEE80211R
4080 const u8 *ie, *md = NULL;
4081#endif /* CONFIG_IEEE80211R */
4082 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4083 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4084 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4085 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4086 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4087 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4088 if (bssid_changed)
4089 wpas_notify_bssid_changed(wpa_s);
4090#ifdef CONFIG_IEEE80211R
4091 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4092 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4093 md = ie + 2;
4094 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4095 if (md) {
4096 /* Prepare for the next transition */
4097 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4098 }
4099#endif /* CONFIG_IEEE80211R */
4100#ifdef CONFIG_WPS
4101 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4102 wpa_s->conf->ap_scan == 2 &&
4103 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4104 /* Use ap_scan==1 style network selection to find the network
4105 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004106 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004107 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004108 wpa_s->reassociate = 1;
4109 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004110 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111 return;
4112#endif /* CONFIG_WPS */
4113 } else {
4114 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4115 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004116 if (bss)
4117 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4118 else
4119 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004121 if (!wpa_s->pno)
4122 wpa_supplicant_cancel_sched_scan(wpa_s);
4123
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 wpa_supplicant_cancel_scan(wpa_s);
4125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4127 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004128 cipher_pairwise = wpa_s->pairwise_cipher;
4129 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004130 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4132 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4133 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4134 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004135#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004136 if (wpa_set_wep_keys(wpa_s, ssid)) {
4137 use_crypt = 1;
4138 wep_keys_set = 1;
4139 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004140#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 }
4142 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4143 use_crypt = 0;
4144
4145#ifdef IEEE8021X_EAPOL
4146 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4147 if ((ssid->eapol_flags &
4148 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4149 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4150 !wep_keys_set) {
4151 use_crypt = 0;
4152 } else {
4153 /* Assume that dynamic WEP-104 keys will be used and
4154 * set cipher suites in order for drivers to expect
4155 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004156 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004157 }
4158 }
4159#endif /* IEEE8021X_EAPOL */
4160
4161 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4162 /* Set the key before (and later after) association */
4163 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4164 }
4165
Sunil8cd6f4d2022-06-28 18:40:46 +00004166 /* Set current_ssid before changing state to ASSOCIATING, so that the
4167 * selected SSID is available to wpas_notify_state_changed(). */
4168 old_ssid = wpa_s->current_ssid;
4169 wpa_s->current_ssid = ssid;
4170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4172 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173 params.ssid = bss->ssid;
4174 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004175 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4176 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004177 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4178 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004179 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004180 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004181 ssid->bssid_set,
4182 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004183 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004184 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004185 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004186 params.bssid_hint = bss->bssid;
4187 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004188 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004190 if (ssid->bssid_hint_set)
4191 params.bssid_hint = ssid->bssid_hint;
4192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004193 params.ssid = ssid->ssid;
4194 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004195 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004197
4198 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4199 wpa_s->conf->ap_scan == 2) {
4200 params.bssid = ssid->bssid;
4201 params.fixed_bssid = 1;
4202 }
4203
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004204 /* Initial frequency for IBSS/mesh */
4205 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004206 ssid->frequency > 0 && params.freq.freq == 0)
4207 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004208
4209 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004210 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004211 if (ssid->beacon_int)
4212 params.beacon_int = ssid->beacon_int;
4213 else
4214 params.beacon_int = wpa_s->conf->beacon_int;
4215 }
4216
Hai Shalomc3565922019-10-28 11:58:20 -07004217 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004218 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4219 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004220 else
4221 edmg_ie_oper = NULL;
4222
4223 if (edmg_ie_oper) {
4224 params.freq.edmg.channels =
4225 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4226 params.freq.edmg.bw_config =
4227 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4228 wpa_printf(MSG_DEBUG,
4229 "AP supports EDMG channels 0x%x, bw_config %d",
4230 params.freq.edmg.channels,
4231 params.freq.edmg.bw_config);
4232
4233 /* User may ask for specific EDMG channel for EDMG connection
4234 * (must be supported by AP)
4235 */
4236 if (ssid->edmg_channel) {
4237 struct ieee80211_edmg_config configured_edmg;
4238 enum hostapd_hw_mode hw_mode;
4239 u8 primary_channel;
4240
4241 hw_mode = ieee80211_freq_to_chan(bss->freq,
4242 &primary_channel);
4243 if (hw_mode == NUM_HOSTAPD_MODES)
4244 goto edmg_fail;
4245
4246 hostapd_encode_edmg_chan(ssid->enable_edmg,
4247 ssid->edmg_channel,
4248 primary_channel,
4249 &configured_edmg);
4250
4251 if (ieee802_edmg_is_allowed(params.freq.edmg,
4252 configured_edmg)) {
4253 params.freq.edmg = configured_edmg;
4254 wpa_printf(MSG_DEBUG,
4255 "Use EDMG channel %d for connection",
4256 ssid->edmg_channel);
4257 } else {
4258 edmg_fail:
4259 params.freq.edmg.channels = 0;
4260 params.freq.edmg.bw_config = 0;
4261 wpa_printf(MSG_WARNING,
4262 "EDMG channel %d not supported by AP, fallback to DMG",
4263 ssid->edmg_channel);
4264 }
4265 }
4266
4267 if (params.freq.edmg.channels) {
4268 wpa_printf(MSG_DEBUG,
4269 "EDMG before: channels 0x%x, bw_config %d",
4270 params.freq.edmg.channels,
4271 params.freq.edmg.bw_config);
4272 params.freq.edmg = get_supported_edmg(wpa_s,
4273 &params.freq,
4274 params.freq.edmg);
4275 wpa_printf(MSG_DEBUG,
4276 "EDMG after: channels 0x%x, bw_config %d",
4277 params.freq.edmg.channels,
4278 params.freq.edmg.bw_config);
4279 }
4280 }
4281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282 params.pairwise_suite = cipher_pairwise;
4283 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004284 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004285 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004286 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004287 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004288 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004289 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004290 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004291#ifdef CONFIG_WEP
4292 {
4293 int i;
4294
4295 for (i = 0; i < NUM_WEP_KEYS; i++) {
4296 if (ssid->wep_key_len[i])
4297 params.wep_key[i] = ssid->wep_key[i];
4298 params.wep_key_len[i] = ssid->wep_key_len[i];
4299 }
4300 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004301 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004302#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303
Hai Shalom74f70d42019-02-11 14:42:39 -08004304 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004305#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004306 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4307 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304308#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004309 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4310 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4311 (params.allowed_key_mgmts &
4312 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004313#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004315 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4316 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317 }
4318
Hai Shalom74f70d42019-02-11 14:42:39 -08004319 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4320 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4321 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4322 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004323 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4324 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384))
Hai Shalomc3565922019-10-28 11:58:20 -07004325 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004326
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004327 if (wpa_s->conf->key_mgmt_offload) {
4328 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4329 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004330 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004331 params.key_mgmt_suite ==
4332 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
4333 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004334 params.req_key_mgmt_offload =
4335 ssid->proactive_key_caching < 0 ?
4336 wpa_s->conf->okc : ssid->proactive_key_caching;
4337 else
4338 params.req_key_mgmt_offload = 1;
4339
Winnie Chen4138eec2022-11-10 16:32:53 +08004340#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004341 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004342 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4343 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004344#else
4345 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4346 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004347#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004348 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4349 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004350 }
4351
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004352 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA) &&
4353 wpa_key_mgmt_sae(params.key_mgmt_suite)) {
4354 params.auth_alg = WPA_AUTH_ALG_SAE;
4355 if (ssid->sae_password) {
4356 params.sae_password = ssid->sae_password;
4357 params.sae_password_id = ssid->sae_password_id;
4358 } else if (ssid->passphrase) {
4359 params.passphrase = ssid->passphrase;
4360 }
4361 }
4362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 params.drop_unencrypted = use_crypt;
4364
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004365 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004366 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4368 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004369 if (!wpas_driver_bss_selection(wpa_s) && rsn &&
4370 wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004371 ie.capabilities &
4372 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4373 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4374 "MFP: require MFP");
4375 params.mgmt_frame_protection =
4376 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004377#ifdef CONFIG_OWE
4378 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4379 !ssid->owe_only) {
4380 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4381#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004382 }
4383 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004384
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004385 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004387 if (wpa_s->p2pdev->set_sta_uapsd)
4388 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004389 else
4390 params.uapsd = -1;
4391
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004392#ifdef CONFIG_HT_OVERRIDES
4393 os_memset(&htcaps, 0, sizeof(htcaps));
4394 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4395 params.htcaps = (u8 *) &htcaps;
4396 params.htcaps_mask = (u8 *) &htcaps_mask;
4397 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4398#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004399#ifdef CONFIG_VHT_OVERRIDES
4400 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4401 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4402 params.vhtcaps = &vhtcaps;
4403 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004404 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004405#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004406#ifdef CONFIG_HE_OVERRIDES
4407 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4408#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004409 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004410
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004411#ifdef CONFIG_P2P
4412 /*
4413 * If multi-channel concurrency is not supported, check for any
4414 * frequency conflict. In case of any frequency conflict, remove the
4415 * least prioritized connection.
4416 */
4417 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004418 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004419 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004420 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004421 wpa_printf(MSG_DEBUG,
4422 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004423 freq, params.freq.freq);
4424 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004425 wpa_s, params.freq.freq, ssid) < 0) {
4426 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004427 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004428 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004429 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004430 }
4431 }
4432#endif /* CONFIG_P2P */
4433
Dmitry Shmidte4663042016-04-04 10:07:49 -07004434 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004435 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004436 params.prev_bssid = prev_bssid;
4437
Hai Shalom60840252021-02-19 19:02:11 -08004438#ifdef CONFIG_SAE
4439 params.sae_pwe = wpa_s->conf->sae_pwe;
4440#endif /* CONFIG_SAE */
4441
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004442 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004443 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004444 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004445 if (ret < 0) {
4446 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4447 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004448 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004449 /*
4450 * The driver is known to mean what is saying, so we
4451 * can stop right here; the association will not
4452 * succeed.
4453 */
4454 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004455 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004456 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004457 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004458 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4459 return;
4460 }
4461 /* try to continue anyway; new association will be tried again
4462 * after timeout */
4463 assoc_failed = 1;
4464 }
4465
4466 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4467 /* Set the key after the association just in case association
4468 * cleared the previously configured key. */
4469 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4470 /* No need to timeout authentication since there is no key
4471 * management. */
4472 wpa_supplicant_cancel_auth_timeout(wpa_s);
4473 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4474#ifdef CONFIG_IBSS_RSN
4475 } else if (ssid->mode == WPAS_MODE_IBSS &&
4476 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4477 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4478 /*
4479 * RSN IBSS authentication is per-STA and we can disable the
4480 * per-BSSID authentication.
4481 */
4482 wpa_supplicant_cancel_auth_timeout(wpa_s);
4483#endif /* CONFIG_IBSS_RSN */
4484 } else {
4485 /* Timeout for IEEE 802.11 authentication and association */
4486 int timeout = 60;
4487
4488 if (assoc_failed) {
4489 /* give IBSS a bit more time */
4490 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4491 } else if (wpa_s->conf->ap_scan == 1) {
4492 /* give IBSS a bit more time */
4493 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4494 }
4495 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4496 }
4497
Hai Shalomfdcde762020-04-02 11:19:20 -07004498#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004499 if (wep_keys_set &&
4500 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004501 /* Set static WEP keys again */
4502 wpa_set_wep_keys(wpa_s, ssid);
4503 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004504#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004505
Sunil8cd6f4d2022-06-28 18:40:46 +00004506 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507 /*
4508 * Do not allow EAP session resumption between different
4509 * network configurations.
4510 */
4511 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4512 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004513
mtk30479d7f89782024-01-24 11:51:43 +08004514 if (!wpas_driver_bss_selection(wpa_s) ||
4515#ifdef CONFIG_P2P
4516 wpa_s->p2p_in_invitation ||
4517#endif /* CONFIG_P2P */
4518 ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004519 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004520#ifdef CONFIG_HS20
4521 hs20_configure_frame_filters(wpa_s);
4522#endif /* CONFIG_HS20 */
4523 }
4524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004525 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4526 wpa_supplicant_initiate_eapol(wpa_s);
4527 if (old_ssid != wpa_s->current_ssid)
4528 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004529 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4530 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004531}
4532
4533
4534static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4535 const u8 *addr)
4536{
4537 struct wpa_ssid *old_ssid;
4538
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004539 wpa_s->ml_connect_probe_ssid = NULL;
4540 wpa_s->ml_connect_probe_bss = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004541 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004542 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004543 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004544 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004545 wpa_sm_set_config(wpa_s->wpa, NULL);
4546 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4547 if (old_ssid != wpa_s->current_ssid)
4548 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004549
4550 wpas_scs_deinit(wpa_s);
4551 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4553}
4554
4555
4556/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4558 * @wpa_s: Pointer to wpa_supplicant data
4559 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4560 *
4561 * This function is used to request %wpa_supplicant to deauthenticate from the
4562 * current AP.
4563 */
4564void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004565 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004566{
4567 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004568 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004569 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004570
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004571 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004572 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004573 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004574 reason_code, reason2str(reason_code),
4575 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004576
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004577 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4578 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4579 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004580 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004581 else if (!is_zero_ether_addr(wpa_s->bssid))
4582 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004583 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4584 /*
4585 * When using driver-based BSS selection, we may not know the
4586 * BSSID with which we are currently trying to associate. We
4587 * need to notify the driver of this disconnection even in such
4588 * a case, so use the all zeros address here.
4589 */
4590 addr = wpa_s->bssid;
4591 zero_addr = 1;
4592 }
4593
Hai Shalom74f70d42019-02-11 14:42:39 -08004594 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4595 wpa_s->enabled_4addr_mode = 0;
4596
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004597#ifdef CONFIG_TDLS
4598 wpa_tdls_teardown_peers(wpa_s->wpa);
4599#endif /* CONFIG_TDLS */
4600
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004601#ifdef CONFIG_MESH
4602 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004603 struct mesh_conf *mconf;
4604
4605 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004606 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4607 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004608 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4609 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004610 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004611 }
4612#endif /* CONFIG_MESH */
4613
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004614 if (addr) {
4615 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004616 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004617 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004618 event.deauth_info.locally_generated = 1;
4619 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004620 if (zero_addr)
4621 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004622 }
4623
4624 wpa_supplicant_clear_connection(wpa_s, addr);
4625}
4626
Hai Shalomfdcde762020-04-02 11:19:20 -07004627
4628void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4629{
4630 wpa_s->own_reconnect_req = 1;
4631 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4632
4633}
4634
4635
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004636static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4637 struct wpa_ssid *ssid)
4638{
4639 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4640 return;
4641
4642 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004643 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004644 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4645 wpas_notify_network_enabled_changed(wpa_s, ssid);
4646
4647 /*
4648 * Try to reassociate since there is no current configuration and a new
4649 * network was made available.
4650 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004651 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004652 wpa_s->reassociate = 1;
4653}
4654
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004655
Roshan Pius950bec92016-07-19 09:49:24 -07004656/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004657 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004658 * @wpa_s: wpa_supplicant structure for a network interface
4659 * Returns: The new network configuration or %NULL if operation failed
4660 *
4661 * This function performs the following operations:
4662 * 1. Adds a new network.
4663 * 2. Send network addition notification.
4664 * 3. Marks the network disabled.
4665 * 4. Set network default parameters.
4666 */
4667struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4668{
4669 struct wpa_ssid *ssid;
4670
4671 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004672 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004673 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004674 wpas_notify_network_added(wpa_s, ssid);
4675 ssid->disabled = 1;
4676 wpa_config_set_network_defaults(ssid);
4677
4678 return ssid;
4679}
4680
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004681
Roshan Pius950bec92016-07-19 09:49:24 -07004682/**
4683 * wpa_supplicant_remove_network - Remove a configured network based on id
4684 * @wpa_s: wpa_supplicant structure for a network interface
4685 * @id: Unique network id to search for
4686 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4687 * could not be removed
4688 *
4689 * This function performs the following operations:
4690 * 1. Removes the network.
4691 * 2. Send network removal notification.
4692 * 3. Update internal state machines.
4693 * 4. Stop any running sched scans.
4694 */
4695int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4696{
Sunil Ravia04bd252022-05-02 22:54:18 -07004697 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004698 int was_disabled;
4699
4700 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004701 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004702 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004703 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004704
Sunil Ravia04bd252022-05-02 22:54:18 -07004705 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004706#ifdef CONFIG_SME
4707 wpa_s->sme.prev_bssid_set = 0;
4708#endif /* CONFIG_SME */
4709 /*
4710 * Invalidate the EAP session cache if the current or
4711 * previously used network is removed.
4712 */
4713 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4714 }
4715
Sunil Ravia04bd252022-05-02 22:54:18 -07004716 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004717 wpa_sm_set_config(wpa_s->wpa, NULL);
4718 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4719
4720 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4721 wpa_s->own_disconnect_req = 1;
4722 wpa_supplicant_deauthenticate(wpa_s,
4723 WLAN_REASON_DEAUTH_LEAVING);
4724 }
4725
4726 was_disabled = ssid->disabled;
4727
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004728 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004729 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004730
4731 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004732 wpa_printf(MSG_DEBUG,
4733 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004734 wpa_supplicant_cancel_sched_scan(wpa_s);
4735 wpa_supplicant_req_scan(wpa_s, 0, 0);
4736 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004737
Roshan Pius950bec92016-07-19 09:49:24 -07004738 return 0;
4739}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004740
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004741
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004742/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004743 * wpa_supplicant_remove_all_networks - Remove all configured networks
4744 * @wpa_s: wpa_supplicant structure for a network interface
4745 * Returns: 0 on success (errors are currently ignored)
4746 *
4747 * This function performs the following operations:
4748 * 1. Remove all networks.
4749 * 2. Send network removal notifications.
4750 * 3. Update internal state machines.
4751 * 4. Stop any running sched scans.
4752 */
4753int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4754{
4755 struct wpa_ssid *ssid;
4756
Vinayak Yadawad4222acc2023-12-15 17:39:27 +05304757 if (wpa_s->drv_flags2 &
4758 (WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA |
4759 WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA))
4760 wpa_drv_flush_pmkid(wpa_s);
4761
Hai Shalom899fcc72020-10-19 14:38:18 -07004762 if (wpa_s->sched_scanning)
4763 wpa_supplicant_cancel_sched_scan(wpa_s);
4764
4765 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4766 if (wpa_s->current_ssid) {
4767#ifdef CONFIG_SME
4768 wpa_s->sme.prev_bssid_set = 0;
4769#endif /* CONFIG_SME */
4770 wpa_sm_set_config(wpa_s->wpa, NULL);
4771 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4772 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4773 wpa_s->own_disconnect_req = 1;
4774 wpa_supplicant_deauthenticate(
4775 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4776 }
4777 ssid = wpa_s->conf->ssid;
4778 while (ssid) {
4779 struct wpa_ssid *remove_ssid = ssid;
4780 int id;
4781
4782 id = ssid->id;
4783 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004784 wpas_notify_network_removed(wpa_s, remove_ssid);
4785 wpa_config_remove_network(wpa_s->conf, id);
4786 }
4787 return 0;
4788}
4789
4790
4791/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004792 * wpa_supplicant_enable_network - Mark a configured network as enabled
4793 * @wpa_s: wpa_supplicant structure for a network interface
4794 * @ssid: wpa_ssid structure for a configured network or %NULL
4795 *
4796 * Enables the specified network or all networks if no network specified.
4797 */
4798void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4799 struct wpa_ssid *ssid)
4800{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004802 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4803 wpa_supplicant_enable_one_network(wpa_s, ssid);
4804 } else
4805 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004807 if (wpa_s->reassociate && !wpa_s->disconnected &&
4808 (!wpa_s->current_ssid ||
4809 wpa_s->wpa_state == WPA_DISCONNECTED ||
4810 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004811 if (wpa_s->sched_scanning) {
4812 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4813 "new network to scan filters");
4814 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815 }
4816
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004817 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4818 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004819 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821 }
4822}
4823
4824
4825/**
4826 * wpa_supplicant_disable_network - Mark a configured network as disabled
4827 * @wpa_s: wpa_supplicant structure for a network interface
4828 * @ssid: wpa_ssid structure for a configured network or %NULL
4829 *
4830 * Disables the specified network or all networks if no network specified.
4831 */
4832void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4833 struct wpa_ssid *ssid)
4834{
4835 struct wpa_ssid *other_ssid;
4836 int was_disabled;
4837
4838 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004839 if (wpa_s->sched_scanning)
4840 wpa_supplicant_cancel_sched_scan(wpa_s);
4841
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004842 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4843 other_ssid = other_ssid->next) {
4844 was_disabled = other_ssid->disabled;
4845 if (was_disabled == 2)
4846 continue; /* do not change persistent P2P group
4847 * data */
4848
4849 other_ssid->disabled = 1;
4850
4851 if (was_disabled != other_ssid->disabled)
4852 wpas_notify_network_enabled_changed(
4853 wpa_s, other_ssid);
4854 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004855 if (wpa_s->current_ssid) {
4856 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4857 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004858 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004860 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004861 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004862 if (ssid == wpa_s->current_ssid) {
4863 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4864 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004865 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004866 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004867 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004868
4869 was_disabled = ssid->disabled;
4870
4871 ssid->disabled = 1;
4872
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004873 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004875 if (wpa_s->sched_scanning) {
4876 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4877 "to remove network from filters");
4878 wpa_supplicant_cancel_sched_scan(wpa_s);
4879 wpa_supplicant_req_scan(wpa_s, 0, 0);
4880 }
4881 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004882 }
4883}
4884
4885
4886/**
4887 * wpa_supplicant_select_network - Attempt association with a network
4888 * @wpa_s: wpa_supplicant structure for a network interface
4889 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4890 */
4891void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4892 struct wpa_ssid *ssid)
4893{
4894
4895 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004896 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004898 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004899 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4900 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004901 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004903 disconnected = 1;
4904 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004906 if (ssid)
4907 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909 /*
4910 * Mark all other networks disabled or mark all networks enabled if no
4911 * network specified.
4912 */
4913 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4914 other_ssid = other_ssid->next) {
4915 int was_disabled = other_ssid->disabled;
4916 if (was_disabled == 2)
4917 continue; /* do not change persistent P2P group data */
4918
4919 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004920 if (was_disabled && !other_ssid->disabled)
4921 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922
4923 if (was_disabled != other_ssid->disabled)
4924 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4925 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004926
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004927 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4928 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004929 /* We are already associated with the selected network */
4930 wpa_printf(MSG_DEBUG, "Already associated with the "
4931 "selected network - do nothing");
4932 return;
4933 }
4934
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004935 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004936 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004937 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004938 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004939 (ssid->mode == WPAS_MODE_MESH ||
4940 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004941
4942 /*
4943 * Don't optimize next scan freqs since a new ESS has been
4944 * selected.
4945 */
4946 os_free(wpa_s->next_scan_freqs);
4947 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004948 } else {
4949 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004950 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004952 wpa_s->disconnected = 0;
4953 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004954 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004955 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004956 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004957 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004958 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004959 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004960
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004961 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004962 wpa_supplicant_fast_associate(wpa_s) != 1) {
4963 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004964 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004965 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004966 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967
4968 if (ssid)
4969 wpas_notify_network_selected(wpa_s, ssid);
4970}
4971
4972
4973/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004974 * wpas_remove_cred - Remove the specified credential and all the network
4975 * entries created based on the removed credential
4976 * @wpa_s: wpa_supplicant structure for a network interface
4977 * @cred: The credential to remove
4978 * Returns: 0 on success, -1 on failure
4979 */
4980int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4981{
4982 struct wpa_ssid *ssid, *next;
4983 int id;
4984
4985 if (!cred) {
4986 wpa_printf(MSG_DEBUG, "Could not find cred");
4987 return -1;
4988 }
4989
4990 id = cred->id;
4991 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4992 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4993 return -1;
4994 }
4995
4996 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4997
4998 /* Remove any network entry created based on the removed credential */
4999 ssid = wpa_s->conf->ssid;
5000 while (ssid) {
5001 next = ssid->next;
5002
5003 if (ssid->parent_cred == cred) {
5004 wpa_printf(MSG_DEBUG,
5005 "Remove network id %d since it used the removed credential",
5006 ssid->id);
5007 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
5008 -1) {
5009 wpa_printf(MSG_DEBUG,
5010 "Could not find network id=%d",
5011 ssid->id);
5012 }
5013 }
5014
5015 ssid = next;
5016 }
5017
5018 return 0;
5019}
5020
5021
5022/**
5023 * wpas_remove_cred - Remove all the Interworking credentials
5024 * @wpa_s: wpa_supplicant structure for a network interface
5025 * Returns: 0 on success, -1 on failure
5026 */
5027int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
5028{
5029 int res, ret = 0;
5030 struct wpa_cred *cred, *prev;
5031
5032 cred = wpa_s->conf->cred;
5033 while (cred) {
5034 prev = cred;
5035 cred = cred->next;
5036 res = wpas_remove_cred(wpa_s, prev);
5037 if (res < 0) {
5038 wpa_printf(MSG_DEBUG,
5039 "Removal of all credentials failed - failed to remove credential id=%d",
5040 prev->id);
5041 ret = -1;
5042 }
5043 }
5044
5045 return ret;
5046}
5047
5048
5049/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005050 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
5051 * @wpa_s: wpa_supplicant structure for a network interface
5052 * @pkcs11_engine_path: PKCS #11 engine path or NULL
5053 * @pkcs11_module_path: PKCS #11 module path or NULL
5054 * Returns: 0 on success; -1 on failure
5055 *
5056 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
5057 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
5058 * module path fails the paths will be reset to the default value (NULL).
5059 */
5060int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
5061 const char *pkcs11_engine_path,
5062 const char *pkcs11_module_path)
5063{
5064 char *pkcs11_engine_path_copy = NULL;
5065 char *pkcs11_module_path_copy = NULL;
5066
5067 if (pkcs11_engine_path != NULL) {
5068 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
5069 if (pkcs11_engine_path_copy == NULL)
5070 return -1;
5071 }
5072 if (pkcs11_module_path != NULL) {
5073 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005074 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005075 os_free(pkcs11_engine_path_copy);
5076 return -1;
5077 }
5078 }
5079
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005080#ifndef CONFIG_PKCS11_ENGINE_PATH
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005081 os_free(wpa_s->conf->pkcs11_engine_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005082 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005083#endif /* CONFIG_PKCS11_ENGINE_PATH */
5084#ifndef CONFIG_PKCS11_MODULE_PATH
5085 os_free(wpa_s->conf->pkcs11_module_path);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005086 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005087#endif /* CONFIG_PKCS11_MODULE_PATH */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005088
5089 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5090 eapol_sm_deinit(wpa_s->eapol);
5091 wpa_s->eapol = NULL;
5092 if (wpa_supplicant_init_eapol(wpa_s)) {
5093 /* Error -> Reset paths to the default value (NULL) once. */
5094 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5095 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5096 NULL);
5097
5098 return -1;
5099 }
5100 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5101
5102 return 0;
5103}
5104
5105
5106/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5108 * @wpa_s: wpa_supplicant structure for a network interface
5109 * @ap_scan: AP scan mode
5110 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5111 *
5112 */
5113int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5114{
5115
5116 int old_ap_scan;
5117
5118 if (ap_scan < 0 || ap_scan > 2)
5119 return -1;
5120
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005121 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5122 wpa_printf(MSG_INFO,
5123 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5124 }
5125
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005126#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005127 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5128 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5129 wpa_s->wpa_state < WPA_COMPLETED) {
5130 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5131 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005132 return 0;
5133 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005134#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005136 old_ap_scan = wpa_s->conf->ap_scan;
5137 wpa_s->conf->ap_scan = ap_scan;
5138
5139 if (old_ap_scan != wpa_s->conf->ap_scan)
5140 wpas_notify_ap_scan_changed(wpa_s);
5141
5142 return 0;
5143}
5144
5145
5146/**
5147 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5148 * @wpa_s: wpa_supplicant structure for a network interface
5149 * @expire_age: Expiration age in seconds
5150 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5151 *
5152 */
5153int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5154 unsigned int bss_expire_age)
5155{
5156 if (bss_expire_age < 10) {
5157 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5158 bss_expire_age);
5159 return -1;
5160 }
5161 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5162 bss_expire_age);
5163 wpa_s->conf->bss_expiration_age = bss_expire_age;
5164
5165 return 0;
5166}
5167
5168
5169/**
5170 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5171 * @wpa_s: wpa_supplicant structure for a network interface
5172 * @expire_count: number of scans after which an unseen BSS is reclaimed
5173 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5174 *
5175 */
5176int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5177 unsigned int bss_expire_count)
5178{
5179 if (bss_expire_count < 1) {
5180 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5181 bss_expire_count);
5182 return -1;
5183 }
5184 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5185 bss_expire_count);
5186 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5187
5188 return 0;
5189}
5190
5191
5192/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005193 * wpa_supplicant_set_scan_interval - Set scan interval
5194 * @wpa_s: wpa_supplicant structure for a network interface
5195 * @scan_interval: scan interval in seconds
5196 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5197 *
5198 */
5199int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5200 int scan_interval)
5201{
5202 if (scan_interval < 0) {
5203 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5204 scan_interval);
5205 return -1;
5206 }
5207 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5208 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005209 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005210
5211 return 0;
5212}
5213
5214
5215/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005216 * wpa_supplicant_set_debug_params - Set global debug params
5217 * @global: wpa_global structure
5218 * @debug_level: debug level
5219 * @debug_timestamp: determines if show timestamp in debug data
5220 * @debug_show_keys: determines if show keys in debug data
5221 * Returns: 0 if succeed or -1 if debug_level has wrong value
5222 */
5223int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5224 int debug_timestamp, int debug_show_keys)
5225{
5226
5227 int old_level, old_timestamp, old_show_keys;
5228
5229 /* check for allowed debuglevels */
5230 if (debug_level != MSG_EXCESSIVE &&
5231 debug_level != MSG_MSGDUMP &&
5232 debug_level != MSG_DEBUG &&
5233 debug_level != MSG_INFO &&
5234 debug_level != MSG_WARNING &&
5235 debug_level != MSG_ERROR)
5236 return -1;
5237
5238 old_level = wpa_debug_level;
5239 old_timestamp = wpa_debug_timestamp;
5240 old_show_keys = wpa_debug_show_keys;
5241
5242 wpa_debug_level = debug_level;
5243 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5244 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5245
5246 if (wpa_debug_level != old_level)
5247 wpas_notify_debug_level_changed(global);
5248 if (wpa_debug_timestamp != old_timestamp)
5249 wpas_notify_debug_timestamp_changed(global);
5250 if (wpa_debug_show_keys != old_show_keys)
5251 wpas_notify_debug_show_keys_changed(global);
5252
5253 return 0;
5254}
5255
5256
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005257#ifdef CONFIG_OWE
5258static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5259 const u8 *entry_ssid, size_t entry_ssid_len)
5260{
5261 const u8 *owe, *pos, *end;
5262 u8 ssid_len;
5263 struct wpa_bss *bss;
5264
5265 /* Check network profile SSID aganst the SSID in the
5266 * OWE Transition Mode element. */
5267
5268 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5269 if (!bss)
5270 return 0;
5271
5272 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5273 if (!owe)
5274 return 0;
5275
5276 pos = owe + 6;
5277 end = owe + 2 + owe[1];
5278
5279 if (end - pos < ETH_ALEN + 1)
5280 return 0;
5281 pos += ETH_ALEN;
5282 ssid_len = *pos++;
5283 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5284 return 0;
5285
5286 return entry_ssid_len == ssid_len &&
5287 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5288}
5289#endif /* CONFIG_OWE */
5290
5291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005292/**
5293 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5294 * @wpa_s: Pointer to wpa_supplicant data
5295 * Returns: A pointer to the current network structure or %NULL on failure
5296 */
5297struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5298{
5299 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005300 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005301 int res;
5302 size_t ssid_len;
5303 u8 bssid[ETH_ALEN];
5304 int wired;
5305
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005306 res = wpa_drv_get_ssid(wpa_s, ssid);
5307 if (res < 0) {
5308 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5309 "driver");
5310 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005311 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005312 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005313
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005314 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005315 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5316 "driver");
5317 return NULL;
5318 }
5319
5320 wired = wpa_s->conf->ap_scan == 0 &&
5321 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5322
5323 entry = wpa_s->conf->ssid;
5324 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005325 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005326 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005327 (!entry->ssid ||
5328 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5329 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005330 (!entry->bssid_set ||
5331 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5332 return entry;
5333#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005334 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005335 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5336 (entry->ssid == NULL || entry->ssid_len == 0) &&
5337 (!entry->bssid_set ||
5338 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5339 return entry;
5340#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005341
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005342#ifdef CONFIG_OWE
5343 if (!wpas_network_disabled(wpa_s, entry) &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005344 (entry->ssid &&
5345 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5346 entry->ssid_len)) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005347 (!entry->bssid_set ||
5348 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5349 return entry;
5350#endif /* CONFIG_OWE */
5351
Dmitry Shmidt04949592012-07-19 12:16:46 -07005352 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005353 entry->ssid_len == 0 &&
5354 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5355 return entry;
5356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005357 entry = entry->next;
5358 }
5359
5360 return NULL;
5361}
5362
5363
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005364static int select_driver(struct wpa_supplicant *wpa_s, int i)
5365{
5366 struct wpa_global *global = wpa_s->global;
5367
5368 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005369 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005370 if (global->drv_priv[i] == NULL) {
5371 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5372 "'%s'", wpa_drivers[i]->name);
5373 return -1;
5374 }
5375 }
5376
5377 wpa_s->driver = wpa_drivers[i];
5378 wpa_s->global_drv_priv = global->drv_priv[i];
5379
5380 return 0;
5381}
5382
5383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005384static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5385 const char *name)
5386{
5387 int i;
5388 size_t len;
5389 const char *pos, *driver = name;
5390
5391 if (wpa_s == NULL)
5392 return -1;
5393
5394 if (wpa_drivers[0] == NULL) {
5395 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5396 "wpa_supplicant");
5397 return -1;
5398 }
5399
5400 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005401 /* Default to first successful driver in the list */
5402 for (i = 0; wpa_drivers[i]; i++) {
5403 if (select_driver(wpa_s, i) == 0)
5404 return 0;
5405 }
5406 /* Drivers have each reported failure, so no wpa_msg() here. */
5407 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005408 }
5409
5410 do {
5411 pos = os_strchr(driver, ',');
5412 if (pos)
5413 len = pos - driver;
5414 else
5415 len = os_strlen(driver);
5416
5417 for (i = 0; wpa_drivers[i]; i++) {
5418 if (os_strlen(wpa_drivers[i]->name) == len &&
5419 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005420 0) {
5421 /* First driver that succeeds wins */
5422 if (select_driver(wpa_s, i) == 0)
5423 return 0;
5424 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005425 }
5426
5427 driver = pos + 1;
5428 } while (pos);
5429
5430 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5431 return -1;
5432}
5433
5434
5435/**
5436 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5437 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5438 * with struct wpa_driver_ops::init()
5439 * @src_addr: Source address of the EAPOL frame
5440 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5441 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005442 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005443 *
5444 * This function is called for each received EAPOL frame. Most driver
5445 * interfaces rely on more generic OS mechanism for receiving frames through
5446 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5447 * take care of received EAPOL frames and deliver them to the core supplicant
5448 * code by calling this function.
5449 */
5450void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005451 const u8 *buf, size_t len,
5452 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005453{
5454 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005455 const u8 *connected_addr = wpa_s->valid_links ?
5456 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005457
Sunil8cd6f4d2022-06-28 18:40:46 +00005458 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5459 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005460 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5461
Hai Shalomc1a21442022-02-04 13:43:00 -08005462 if (wpa_s->own_disconnect_req) {
5463 wpa_printf(MSG_DEBUG,
5464 "Drop received EAPOL frame as we are disconnecting");
5465 return;
5466 }
5467
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005468#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005469 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5470 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005471 if (wpa_s->ignore_auth_resp) {
5472 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5473 return;
5474 }
5475#endif /* CONFIG_TESTING_OPTIONS */
5476
Jouni Malinena05074c2012-12-21 21:35:35 +02005477 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5478 (wpa_s->last_eapol_matches_bssid &&
5479#ifdef CONFIG_AP
5480 !wpa_s->ap_iface &&
5481#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005482 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005483 /*
5484 * There is possible race condition between receiving the
5485 * association event and the EAPOL frame since they are coming
5486 * through different paths from the driver. In order to avoid
5487 * issues in trying to process the EAPOL frame before receiving
5488 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005489 * the association event is received. This may also be needed in
5490 * driver-based roaming case, so also use src_addr != BSSID as a
5491 * trigger if we have previously confirmed that the
5492 * Authenticator uses BSSID as the src_addr (which is not the
5493 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005494 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005495 wpa_dbg(wpa_s, MSG_DEBUG,
5496 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5497 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005498 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005499 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005500 wpabuf_free(wpa_s->pending_eapol_rx);
5501 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5502 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005503 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005504 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5505 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005506 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507 }
5508 return;
5509 }
5510
Jouni Malinena05074c2012-12-21 21:35:35 +02005511 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005512 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005513
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005514#ifdef CONFIG_AP
5515 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005516 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5517 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005518 return;
5519 }
5520#endif /* CONFIG_AP */
5521
5522 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5523 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5524 "no key management is configured");
5525 return;
5526 }
5527
5528 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005529 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005530 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5531 wpa_s->wpa_state != WPA_COMPLETED) &&
5532 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005533 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005534 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005535 int timeout = 10;
5536
5537 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5538 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5539 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5540 /* Use longer timeout for IEEE 802.1X/EAP */
5541 timeout = 70;
5542 }
5543
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005544#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005545 if (wpa_s->current_ssid && wpa_s->current_bss &&
5546 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5547 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5548 /*
5549 * Use shorter timeout if going through WPS AP iteration
5550 * for PIN config method with an AP that does not
5551 * advertise Selected Registrar.
5552 */
5553 struct wpabuf *wps_ie;
5554
5555 wps_ie = wpa_bss_get_vendor_ie_multi(
5556 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5557 if (wps_ie &&
5558 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5559 timeout = 10;
5560 wpabuf_free(wps_ie);
5561 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005562#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005563
5564 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005565 }
5566 wpa_s->eapol_received++;
5567
5568 if (wpa_s->countermeasures) {
5569 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5570 "EAPOL packet");
5571 return;
5572 }
5573
5574#ifdef CONFIG_IBSS_RSN
5575 if (wpa_s->current_ssid &&
5576 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005577 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5578 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 return;
5580 }
5581#endif /* CONFIG_IBSS_RSN */
5582
5583 /* Source address of the incoming EAPOL frame could be compared to the
5584 * current BSSID. However, it is possible that a centralized
5585 * Authenticator could be using another MAC address than the BSSID of
5586 * an AP, so just allow any address to be used for now. The replies are
5587 * still sent to the current BSSID (if available), though. */
5588
5589 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5590 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005591 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5592 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005593 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5594 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005595 return;
5596 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005597 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005598 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005599 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5600 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005601 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005602 * handshake processing which would normally set portValid. We
5603 * need this to allow the EAPOL state machines to be completed
5604 * without going through EAPOL-Key handshake.
5605 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005606 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005607 }
5608}
5609
5610
Sunil8cd6f4d2022-06-28 18:40:46 +00005611static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5612 const u8 *buf, size_t len)
5613{
5614 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5615 FRAME_ENCRYPTION_UNKNOWN);
5616}
5617
5618
Hai Shalomb755a2a2020-04-23 21:49:02 -07005619static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5620{
5621 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5622 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5623}
5624
5625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005626int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005627{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005628 u8 prev_mac_addr[ETH_ALEN];
5629
5630 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5631
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005632 if ((!wpa_s->p2p_mgmt ||
5633 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5634 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005635 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005636 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5637 wpa_drv_get_mac_addr(wpa_s),
5638 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005639 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005640 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005641 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005642 if (wpa_s->l2 == NULL)
5643 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005644
5645 if (l2_packet_set_packet_filter(wpa_s->l2,
5646 L2_PACKET_FILTER_PKTTYPE))
5647 wpa_dbg(wpa_s, MSG_DEBUG,
5648 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005649
5650 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5651 wpa_msg(wpa_s, MSG_ERROR,
5652 "Failed to get own L2 address");
5653 return -1;
5654 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005655 } else {
5656 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5657 if (addr)
5658 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5659 }
5660
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005661 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005662 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005663
Hai Shalomc3565922019-10-28 11:58:20 -07005664#ifdef CONFIG_FST
5665 if (wpa_s->fst)
5666 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5667#endif /* CONFIG_FST */
5668
Sunil Ravi77d572f2023-01-17 23:58:31 +00005669 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5670 wpas_notify_mac_address_changed(wpa_s);
5671
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005672 return 0;
5673}
5674
5675
Dmitry Shmidt04949592012-07-19 12:16:46 -07005676static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5677 const u8 *buf, size_t len)
5678{
5679 struct wpa_supplicant *wpa_s = ctx;
5680 const struct l2_ethhdr *eth;
5681
5682 if (len < sizeof(*eth))
5683 return;
5684 eth = (const struct l2_ethhdr *) buf;
5685
5686 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5687 !(eth->h_dest[0] & 0x01)) {
5688 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5689 " (bridge - not for this interface - ignore)",
5690 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5691 return;
5692 }
5693
5694 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5695 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5696 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005697 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005698}
5699
5700
Hai Shalom899fcc72020-10-19 14:38:18 -07005701int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5702 const char *bridge_ifname)
5703{
5704 if (wpa_s->wpa_state > WPA_SCANNING)
5705 return -EBUSY;
5706
5707 if (bridge_ifname &&
5708 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5709 return -EINVAL;
5710
5711 if (!bridge_ifname)
5712 bridge_ifname = "";
5713
5714 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5715 return 0;
5716
5717 if (wpa_s->l2_br) {
5718 l2_packet_deinit(wpa_s->l2_br);
5719 wpa_s->l2_br = NULL;
5720 }
5721
5722 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5723 sizeof(wpa_s->bridge_ifname));
5724
5725 if (wpa_s->bridge_ifname[0]) {
5726 wpa_dbg(wpa_s, MSG_DEBUG,
5727 "Receiving packets from bridge interface '%s'",
5728 wpa_s->bridge_ifname);
5729 wpa_s->l2_br = l2_packet_init_bridge(
5730 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5731 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5732 if (!wpa_s->l2_br) {
5733 wpa_msg(wpa_s, MSG_ERROR,
5734 "Failed to open l2_packet connection for the bridge interface '%s'",
5735 wpa_s->bridge_ifname);
5736 goto fail;
5737 }
5738 }
5739
5740#ifdef CONFIG_TDLS
5741 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5742 goto fail;
5743#endif /* CONFIG_TDLS */
5744
5745 return 0;
5746fail:
5747 wpa_s->bridge_ifname[0] = 0;
5748 if (wpa_s->l2_br) {
5749 l2_packet_deinit(wpa_s->l2_br);
5750 wpa_s->l2_br = NULL;
5751 }
5752#ifdef CONFIG_TDLS
5753 if (!wpa_s->p2p_mgmt)
5754 wpa_tdls_init(wpa_s->wpa);
5755#endif /* CONFIG_TDLS */
5756 return -EIO;
5757}
5758
5759
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005760/**
5761 * wpa_supplicant_driver_init - Initialize driver interface parameters
5762 * @wpa_s: Pointer to wpa_supplicant data
5763 * Returns: 0 on success, -1 on failure
5764 *
5765 * This function is called to initialize driver interface parameters.
5766 * wpa_drv_init() must have been called before this function to initialize the
5767 * driver interface.
5768 */
5769int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5770{
5771 static int interface_count = 0;
5772
5773 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5774 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005775
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005776 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5777 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005778 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005779 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5780
Hai Shalomb755a2a2020-04-23 21:49:02 -07005781 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005782 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5783 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005784 wpa_s->l2_br = l2_packet_init_bridge(
5785 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5786 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005787 if (wpa_s->l2_br == NULL) {
5788 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5789 "connection for the bridge interface '%s'",
5790 wpa_s->bridge_ifname);
5791 return -1;
5792 }
5793 }
5794
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005795 if (wpa_s->conf->ap_scan == 2 &&
5796 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5797 wpa_printf(MSG_INFO,
5798 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5799 }
5800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005801 wpa_clear_keys(wpa_s, NULL);
5802
5803 /* Make sure that TKIP countermeasures are not left enabled (could
5804 * happen if wpa_supplicant is killed during countermeasures. */
5805 wpa_drv_set_countermeasures(wpa_s, 0);
5806
5807 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5808 wpa_drv_flush_pmkid(wpa_s);
5809
5810 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005811 wpa_s->prev_scan_wildcard = 0;
5812
Dmitry Shmidt04949592012-07-19 12:16:46 -07005813 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005814 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5815 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5816 interface_count = 0;
5817 }
Keith Mok4389c282022-11-23 21:36:48 +00005818#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005819 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005820 wpa_supplicant_delayed_sched_scan(wpa_s,
5821 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005822 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005823 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005824 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005825#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005826 interface_count++;
5827 } else
5828 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5829
5830 return 0;
5831}
5832
5833
5834static int wpa_supplicant_daemon(const char *pid_file)
5835{
5836 wpa_printf(MSG_DEBUG, "Daemonize..");
5837 return os_daemonize(pid_file);
5838}
5839
5840
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005841static struct wpa_supplicant *
5842wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005843{
5844 struct wpa_supplicant *wpa_s;
5845
5846 wpa_s = os_zalloc(sizeof(*wpa_s));
5847 if (wpa_s == NULL)
5848 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005849 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005850 wpa_s->scan_interval = 5;
5851 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005852 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005853 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005854 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005855 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005857 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005858 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005859#ifdef CONFIG_TESTING_OPTIONS
5860 dl_list_init(&wpa_s->drv_signal_override);
5861#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005862 dl_list_init(&wpa_s->active_scs_ids);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005863 wpa_s->ml_probe_mld_id = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005865 return wpa_s;
5866}
5867
5868
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005869#ifdef CONFIG_HT_OVERRIDES
5870
5871static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5872 struct ieee80211_ht_capabilities *htcaps,
5873 struct ieee80211_ht_capabilities *htcaps_mask,
5874 const char *ht_mcs)
5875{
5876 /* parse ht_mcs into hex array */
5877 int i;
5878 const char *tmp = ht_mcs;
5879 char *end = NULL;
5880
5881 /* If ht_mcs is null, do not set anything */
5882 if (!ht_mcs)
5883 return 0;
5884
5885 /* This is what we are setting in the kernel */
5886 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5887
5888 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5889
5890 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005891 long v;
5892
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005893 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005894 v = strtol(tmp, &end, 16);
5895
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005896 if (errno == 0) {
5897 wpa_msg(wpa_s, MSG_DEBUG,
5898 "htcap value[%i]: %ld end: %p tmp: %p",
5899 i, v, end, tmp);
5900 if (end == tmp)
5901 break;
5902
5903 htcaps->supported_mcs_set[i] = v;
5904 tmp = end;
5905 } else {
5906 wpa_msg(wpa_s, MSG_ERROR,
5907 "Failed to parse ht-mcs: %s, error: %s\n",
5908 ht_mcs, strerror(errno));
5909 return -1;
5910 }
5911 }
5912
5913 /*
5914 * If we were able to parse any values, then set mask for the MCS set.
5915 */
5916 if (i) {
5917 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5918 IEEE80211_HT_MCS_MASK_LEN - 1);
5919 /* skip the 3 reserved bits */
5920 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5921 0x1f;
5922 }
5923
5924 return 0;
5925}
5926
5927
5928static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5929 struct ieee80211_ht_capabilities *htcaps,
5930 struct ieee80211_ht_capabilities *htcaps_mask,
5931 int disabled)
5932{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005933 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005934
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005935 if (disabled == -1)
5936 return 0;
5937
Hai Shalom74f70d42019-02-11 14:42:39 -08005938 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5939
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005940 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5941 htcaps_mask->ht_capabilities_info |= msk;
5942 if (disabled)
5943 htcaps->ht_capabilities_info &= msk;
5944 else
5945 htcaps->ht_capabilities_info |= msk;
5946
5947 return 0;
5948}
5949
5950
5951static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5952 struct ieee80211_ht_capabilities *htcaps,
5953 struct ieee80211_ht_capabilities *htcaps_mask,
5954 int factor)
5955{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005956 if (factor == -1)
5957 return 0;
5958
Hai Shalom74f70d42019-02-11 14:42:39 -08005959 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5960
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005961 if (factor < 0 || factor > 3) {
5962 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5963 "Must be 0-3 or -1", factor);
5964 return -EINVAL;
5965 }
5966
5967 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5968 htcaps->a_mpdu_params &= ~0x3;
5969 htcaps->a_mpdu_params |= factor & 0x3;
5970
5971 return 0;
5972}
5973
5974
5975static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5976 struct ieee80211_ht_capabilities *htcaps,
5977 struct ieee80211_ht_capabilities *htcaps_mask,
5978 int density)
5979{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005980 if (density == -1)
5981 return 0;
5982
Hai Shalom74f70d42019-02-11 14:42:39 -08005983 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5984
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005985 if (density < 0 || density > 7) {
5986 wpa_msg(wpa_s, MSG_ERROR,
5987 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5988 density);
5989 return -EINVAL;
5990 }
5991
5992 htcaps_mask->a_mpdu_params |= 0x1C;
5993 htcaps->a_mpdu_params &= ~(0x1C);
5994 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5995
5996 return 0;
5997}
5998
5999
6000static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
6001 struct ieee80211_ht_capabilities *htcaps,
6002 struct ieee80211_ht_capabilities *htcaps_mask,
6003 int disabled)
6004{
Hai Shalom74f70d42019-02-11 14:42:39 -08006005 if (disabled)
6006 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006007
Paul Stewart092955c2017-02-06 09:13:09 -08006008 set_disable_ht40(htcaps, disabled);
6009 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006010
6011 return 0;
6012}
6013
6014
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006015static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
6016 struct ieee80211_ht_capabilities *htcaps,
6017 struct ieee80211_ht_capabilities *htcaps_mask,
6018 int disabled)
6019{
6020 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006021 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
6022 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006023
Hai Shalom74f70d42019-02-11 14:42:39 -08006024 if (disabled)
6025 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006026
6027 if (disabled)
6028 htcaps->ht_capabilities_info &= ~msk;
6029 else
6030 htcaps->ht_capabilities_info |= msk;
6031
6032 htcaps_mask->ht_capabilities_info |= msk;
6033
6034 return 0;
6035}
6036
6037
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006038static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
6039 struct ieee80211_ht_capabilities *htcaps,
6040 struct ieee80211_ht_capabilities *htcaps_mask,
6041 int disabled)
6042{
6043 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006044 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006045
Hai Shalom74f70d42019-02-11 14:42:39 -08006046 if (disabled)
6047 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006048
6049 if (disabled)
6050 htcaps->ht_capabilities_info &= ~msk;
6051 else
6052 htcaps->ht_capabilities_info |= msk;
6053
6054 htcaps_mask->ht_capabilities_info |= msk;
6055
6056 return 0;
6057}
6058
6059
Hai Shalom74f70d42019-02-11 14:42:39 -08006060static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
6061 struct ieee80211_ht_capabilities *htcaps,
6062 struct ieee80211_ht_capabilities *htcaps_mask,
6063 int tx_stbc)
6064{
6065 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
6066
6067 if (tx_stbc == -1)
6068 return 0;
6069
6070 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
6071
6072 if (tx_stbc < 0 || tx_stbc > 1) {
6073 wpa_msg(wpa_s, MSG_ERROR,
6074 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
6075 return -EINVAL;
6076 }
6077
6078 htcaps_mask->ht_capabilities_info |= msk;
6079 htcaps->ht_capabilities_info &= ~msk;
6080 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
6081
6082 return 0;
6083}
6084
6085
6086static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6087 struct ieee80211_ht_capabilities *htcaps,
6088 struct ieee80211_ht_capabilities *htcaps_mask,
6089 int rx_stbc)
6090{
6091 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6092
6093 if (rx_stbc == -1)
6094 return 0;
6095
6096 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6097
6098 if (rx_stbc < 0 || rx_stbc > 3) {
6099 wpa_msg(wpa_s, MSG_ERROR,
6100 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6101 return -EINVAL;
6102 }
6103
6104 htcaps_mask->ht_capabilities_info |= msk;
6105 htcaps->ht_capabilities_info &= ~msk;
6106 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6107
6108 return 0;
6109}
6110
6111
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006112void wpa_supplicant_apply_ht_overrides(
6113 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6114 struct wpa_driver_associate_params *params)
6115{
6116 struct ieee80211_ht_capabilities *htcaps;
6117 struct ieee80211_ht_capabilities *htcaps_mask;
6118
6119 if (!ssid)
6120 return;
6121
6122 params->disable_ht = ssid->disable_ht;
6123 if (!params->htcaps || !params->htcaps_mask)
6124 return;
6125
6126 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6127 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6128 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6129 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6130 ssid->disable_max_amsdu);
6131 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6132 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6133 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006134 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006135 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006136 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6137 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006138
6139 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006140 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006141 htcaps->ht_capabilities_info |= bit;
6142 htcaps_mask->ht_capabilities_info |= bit;
6143 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006144}
6145
6146#endif /* CONFIG_HT_OVERRIDES */
6147
6148
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006149#ifdef CONFIG_VHT_OVERRIDES
6150void wpa_supplicant_apply_vht_overrides(
6151 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6152 struct wpa_driver_associate_params *params)
6153{
6154 struct ieee80211_vht_capabilities *vhtcaps;
6155 struct ieee80211_vht_capabilities *vhtcaps_mask;
6156
6157 if (!ssid)
6158 return;
6159
6160 params->disable_vht = ssid->disable_vht;
6161
6162 vhtcaps = (void *) params->vhtcaps;
6163 vhtcaps_mask = (void *) params->vhtcaps_mask;
6164
6165 if (!vhtcaps || !vhtcaps_mask)
6166 return;
6167
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006168 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6169 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006170
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006171#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006172 if (ssid->disable_sgi) {
6173 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6174 VHT_CAP_SHORT_GI_160);
6175 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6176 VHT_CAP_SHORT_GI_160);
6177 wpa_msg(wpa_s, MSG_DEBUG,
6178 "disable-sgi override specified, vht-caps: 0x%x",
6179 vhtcaps->vht_capabilities_info);
6180 }
6181
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006182 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006183 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6184 int max_ampdu;
6185
6186 max_ampdu = (ssid->vht_capa &
6187 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6188 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006189
6190 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6191 wpa_set_ampdu_factor(wpa_s,
6192 (void *) params->htcaps,
6193 (void *) params->htcaps_mask,
6194 max_ampdu);
6195 }
6196#endif /* CONFIG_HT_OVERRIDES */
6197
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006198#define OVERRIDE_MCS(i) \
6199 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6200 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006201 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006202 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006203 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6204 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006205 } \
6206 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6207 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006208 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006209 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006210 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6211 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006212 }
6213
6214 OVERRIDE_MCS(1);
6215 OVERRIDE_MCS(2);
6216 OVERRIDE_MCS(3);
6217 OVERRIDE_MCS(4);
6218 OVERRIDE_MCS(5);
6219 OVERRIDE_MCS(6);
6220 OVERRIDE_MCS(7);
6221 OVERRIDE_MCS(8);
6222}
6223#endif /* CONFIG_VHT_OVERRIDES */
6224
6225
Hai Shalomfdcde762020-04-02 11:19:20 -07006226#ifdef CONFIG_HE_OVERRIDES
6227void wpa_supplicant_apply_he_overrides(
6228 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6229 struct wpa_driver_associate_params *params)
6230{
6231 if (!ssid)
6232 return;
6233
6234 params->disable_he = ssid->disable_he;
6235}
6236#endif /* CONFIG_HE_OVERRIDES */
6237
6238
Sunil Ravi77d572f2023-01-17 23:58:31 +00006239void wpa_supplicant_apply_eht_overrides(
6240 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6241 struct wpa_driver_associate_params *params)
6242{
6243 if (!ssid)
6244 return;
6245
6246 params->disable_eht = ssid->disable_eht;
6247}
6248
6249
Dmitry Shmidt04949592012-07-19 12:16:46 -07006250static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6251{
6252#ifdef PCSC_FUNCS
6253 size_t len;
6254
6255 if (!wpa_s->conf->pcsc_reader)
6256 return 0;
6257
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006258 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006259 if (!wpa_s->scard)
6260 return 1;
6261
6262 if (wpa_s->conf->pcsc_pin &&
6263 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6264 scard_deinit(wpa_s->scard);
6265 wpa_s->scard = NULL;
6266 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6267 return -1;
6268 }
6269
6270 len = sizeof(wpa_s->imsi) - 1;
6271 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6272 scard_deinit(wpa_s->scard);
6273 wpa_s->scard = NULL;
6274 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6275 return -1;
6276 }
6277 wpa_s->imsi[len] = '\0';
6278
6279 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6280
6281 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6282 wpa_s->imsi, wpa_s->mnc_len);
6283
6284 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6285 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6286#endif /* PCSC_FUNCS */
6287
6288 return 0;
6289}
6290
6291
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006292int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6293{
6294 char *val, *pos;
6295
6296 ext_password_deinit(wpa_s->ext_pw);
6297 wpa_s->ext_pw = NULL;
6298 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6299
6300 if (!wpa_s->conf->ext_password_backend)
6301 return 0;
6302
6303 val = os_strdup(wpa_s->conf->ext_password_backend);
6304 if (val == NULL)
6305 return -1;
6306 pos = os_strchr(val, ':');
6307 if (pos)
6308 *pos++ = '\0';
6309
6310 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6311
6312 wpa_s->ext_pw = ext_password_init(val, pos);
6313 os_free(val);
6314 if (wpa_s->ext_pw == NULL) {
6315 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6316 return -1;
6317 }
6318 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6319
6320 return 0;
6321}
6322
6323
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006324#ifdef CONFIG_FST
6325
6326static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6327{
6328 struct wpa_supplicant *wpa_s = ctx;
6329
6330 return (is_zero_ether_addr(wpa_s->bssid) ||
6331 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6332}
6333
6334
6335static void wpas_fst_get_channel_info_cb(void *ctx,
6336 enum hostapd_hw_mode *hw_mode,
6337 u8 *channel)
6338{
6339 struct wpa_supplicant *wpa_s = ctx;
6340
6341 if (wpa_s->current_bss) {
6342 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6343 channel);
6344 } else if (wpa_s->hw.num_modes) {
6345 *hw_mode = wpa_s->hw.modes[0].mode;
6346 } else {
6347 WPA_ASSERT(0);
6348 *hw_mode = 0;
6349 }
6350}
6351
6352
6353static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6354{
6355 struct wpa_supplicant *wpa_s = ctx;
6356
6357 *modes = wpa_s->hw.modes;
6358 return wpa_s->hw.num_modes;
6359}
6360
6361
6362static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6363{
6364 struct wpa_supplicant *wpa_s = ctx;
6365
6366 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6367 wpa_s->fst_ies = fst_ies;
6368}
6369
6370
6371static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6372{
6373 struct wpa_supplicant *wpa_s = ctx;
6374
Paul Stewart092955c2017-02-06 09:13:09 -08006375 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6376 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6377 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6378 return -1;
6379 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006380 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006381 wpa_s->own_addr, wpa_s->bssid,
6382 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006383 0);
6384}
6385
6386
6387static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6388{
6389 struct wpa_supplicant *wpa_s = ctx;
6390
6391 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6392 return wpa_s->received_mb_ies;
6393}
6394
6395
6396static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6397 const u8 *buf, size_t size)
6398{
6399 struct wpa_supplicant *wpa_s = ctx;
6400 struct mb_ies_info info;
6401
6402 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6403
6404 if (!mb_ies_info_by_ies(&info, buf, size)) {
6405 wpabuf_free(wpa_s->received_mb_ies);
6406 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6407 }
6408}
6409
6410
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006411static const u8 * wpas_fst_get_peer_first(void *ctx,
6412 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006413 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006414{
6415 struct wpa_supplicant *wpa_s = ctx;
6416
6417 *get_ctx = NULL;
6418 if (!is_zero_ether_addr(wpa_s->bssid))
6419 return (wpa_s->received_mb_ies || !mb_only) ?
6420 wpa_s->bssid : NULL;
6421 return NULL;
6422}
6423
6424
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006425static const u8 * wpas_fst_get_peer_next(void *ctx,
6426 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006427 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006428{
6429 return NULL;
6430}
6431
6432void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6433 struct fst_wpa_obj *iface_obj)
6434{
Sunil8cd6f4d2022-06-28 18:40:46 +00006435 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006436 iface_obj->ctx = wpa_s;
6437 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6438 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6439 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6440 iface_obj->set_ies = wpas_fst_set_ies_cb;
6441 iface_obj->send_action = wpas_fst_send_action_cb;
6442 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6443 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6444 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6445 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6446}
6447#endif /* CONFIG_FST */
6448
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006449static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006450 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006451{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006452 struct wowlan_triggers *triggers;
6453 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006454
6455 if (!wpa_s->conf->wowlan_triggers)
6456 return 0;
6457
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006458 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6459 if (triggers) {
6460 ret = wpa_drv_wowlan(wpa_s, triggers);
6461 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006462 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006463 return ret;
6464}
6465
6466
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006467enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006468{
6469 if (freq < 3000)
6470 return BAND_2_4_GHZ;
6471 if (freq > 50000)
6472 return BAND_60_GHZ;
6473 return BAND_5_GHZ;
6474}
6475
6476
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006477unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006478{
6479 int i;
6480 unsigned int band = 0;
6481
6482 if (freqs) {
6483 /* freqs are specified for the radio work */
6484 for (i = 0; freqs[i]; i++)
6485 band |= wpas_freq_to_band(freqs[i]);
6486 } else {
6487 /*
6488 * freqs are not specified, implies all
6489 * the supported freqs by HW
6490 */
6491 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6492 if (wpa_s->hw.modes[i].num_channels != 0) {
6493 if (wpa_s->hw.modes[i].mode ==
6494 HOSTAPD_MODE_IEEE80211B ||
6495 wpa_s->hw.modes[i].mode ==
6496 HOSTAPD_MODE_IEEE80211G)
6497 band |= BAND_2_4_GHZ;
6498 else if (wpa_s->hw.modes[i].mode ==
6499 HOSTAPD_MODE_IEEE80211A)
6500 band |= BAND_5_GHZ;
6501 else if (wpa_s->hw.modes[i].mode ==
6502 HOSTAPD_MODE_IEEE80211AD)
6503 band |= BAND_60_GHZ;
6504 else if (wpa_s->hw.modes[i].mode ==
6505 HOSTAPD_MODE_IEEE80211ANY)
6506 band = BAND_2_4_GHZ | BAND_5_GHZ |
6507 BAND_60_GHZ;
6508 }
6509 }
6510 }
6511
6512 return band;
6513}
6514
6515
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006516static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6517 const char *rn)
6518{
6519 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6520 struct wpa_radio *radio;
6521
6522 while (rn && iface) {
6523 radio = iface->radio;
6524 if (radio && os_strcmp(rn, radio->name) == 0) {
6525 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6526 wpa_s->ifname, rn);
6527 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6528 return radio;
6529 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006530
6531 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006532 }
6533
6534 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6535 wpa_s->ifname, rn ? rn : "N/A");
6536 radio = os_zalloc(sizeof(*radio));
6537 if (radio == NULL)
6538 return NULL;
6539
6540 if (rn)
6541 os_strlcpy(radio->name, rn, sizeof(radio->name));
6542 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006543 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006544 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6545
6546 return radio;
6547}
6548
6549
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006550static void radio_work_free(struct wpa_radio_work *work)
6551{
6552 if (work->wpa_s->scan_work == work) {
6553 /* This should not really happen. */
6554 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6555 work->type, work, work->started);
6556 work->wpa_s->scan_work = NULL;
6557 }
6558
6559#ifdef CONFIG_P2P
6560 if (work->wpa_s->p2p_scan_work == work) {
6561 /* This should not really happen. */
6562 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6563 work->type, work, work->started);
6564 work->wpa_s->p2p_scan_work = NULL;
6565 }
6566#endif /* CONFIG_P2P */
6567
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006568 if (work->started) {
6569 work->wpa_s->radio->num_active_works--;
6570 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006571 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006572 work->type, work,
6573 work->wpa_s->radio->num_active_works);
6574 }
6575
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006576 dl_list_del(&work->list);
6577 os_free(work);
6578}
6579
6580
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006581static int radio_work_is_connect(struct wpa_radio_work *work)
6582{
6583 return os_strcmp(work->type, "sme-connect") == 0 ||
6584 os_strcmp(work->type, "connect") == 0;
6585}
6586
6587
6588static int radio_work_is_scan(struct wpa_radio_work *work)
6589{
6590 return os_strcmp(work->type, "scan") == 0 ||
6591 os_strcmp(work->type, "p2p-scan") == 0;
6592}
6593
6594
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006595static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6596{
6597 struct wpa_radio_work *active_work = NULL;
6598 struct wpa_radio_work *tmp;
6599
6600 /* Get the active work to know the type and band. */
6601 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6602 if (tmp->started) {
6603 active_work = tmp;
6604 break;
6605 }
6606 }
6607
6608 if (!active_work) {
6609 /* No active work, start one */
6610 radio->num_active_works = 0;
6611 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6612 list) {
6613 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006614 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006615 (((struct wpa_driver_scan_params *)
6616 tmp->ctx)->only_new_results ||
6617 tmp->wpa_s->clear_driver_scan_cache))
6618 continue;
6619 return tmp;
6620 }
6621 return NULL;
6622 }
6623
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006624 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006625 /*
6626 * If the active work is either connect or sme-connect,
6627 * do not parallelize them with other radio works.
6628 */
6629 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6630 "Do not parallelize radio work with %s",
6631 active_work->type);
6632 return NULL;
6633 }
6634
6635 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6636 if (tmp->started)
6637 continue;
6638
6639 /*
6640 * If connect or sme-connect are enqueued, parallelize only
6641 * those operations ahead of them in the queue.
6642 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006643 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006644 break;
6645
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006646 /* Serialize parallel scan and p2p_scan operations on the same
6647 * interface since the driver_nl80211 mechanism for tracking
6648 * scan cookies does not yet have support for this. */
6649 if (active_work->wpa_s == tmp->wpa_s &&
6650 radio_work_is_scan(active_work) &&
6651 radio_work_is_scan(tmp)) {
6652 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6653 "Do not start work '%s' when another work '%s' is already scheduled",
6654 tmp->type, active_work->type);
6655 continue;
6656 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006657 /*
6658 * Check that the radio works are distinct and
6659 * on different bands.
6660 */
6661 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6662 (active_work->bands != tmp->bands)) {
6663 /*
6664 * If a scan has to be scheduled through nl80211 scan
6665 * interface and if an external scan is already running,
6666 * do not schedule the scan since it is likely to get
6667 * rejected by kernel.
6668 */
6669 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006670 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006671 (((struct wpa_driver_scan_params *)
6672 tmp->ctx)->only_new_results ||
6673 tmp->wpa_s->clear_driver_scan_cache))
6674 continue;
6675
6676 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6677 "active_work:%s new_work:%s",
6678 active_work->type, tmp->type);
6679 return tmp;
6680 }
6681 }
6682
6683 /* Did not find a radio work to schedule in parallel. */
6684 return NULL;
6685}
6686
6687
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006688static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6689{
6690 struct wpa_radio *radio = eloop_ctx;
6691 struct wpa_radio_work *work;
6692 struct os_reltime now, diff;
6693 struct wpa_supplicant *wpa_s;
6694
6695 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006696 if (work == NULL) {
6697 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006698 return;
6699 }
6700
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006701 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6702 radio_list);
6703
6704 if (!(wpa_s &&
6705 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6706 if (work->started)
6707 return; /* already started and still in progress */
6708
Hai Shalom60840252021-02-19 19:02:11 -08006709 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006710 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6711 return;
6712 }
6713 } else {
6714 work = NULL;
6715 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6716 /* get the work to schedule next */
6717 work = radio_work_get_next_work(radio);
6718 }
6719 if (!work)
6720 return;
6721 }
6722
6723 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006724 os_get_reltime(&now);
6725 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006726 wpa_dbg(wpa_s, MSG_DEBUG,
6727 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006728 work->type, work, diff.sec, diff.usec);
6729 work->started = 1;
6730 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006731 radio->num_active_works++;
6732
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006733 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006734
6735 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6736 radio->num_active_works < MAX_ACTIVE_WORKS)
6737 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006738}
6739
6740
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006741/*
6742 * This function removes both started and pending radio works running on
6743 * the provided interface's radio.
6744 * Prior to the removal of the radio work, its callback (cb) is called with
6745 * deinit set to be 1. Each work's callback is responsible for clearing its
6746 * internal data and restoring to a correct state.
6747 * @wpa_s: wpa_supplicant data
6748 * @type: type of works to be removed
6749 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6750 * this interface's works.
6751 */
6752void radio_remove_works(struct wpa_supplicant *wpa_s,
6753 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006754{
6755 struct wpa_radio_work *work, *tmp;
6756 struct wpa_radio *radio = wpa_s->radio;
6757
6758 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6759 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006760 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006761 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006762
6763 /* skip other ifaces' works */
6764 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006765 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006766
6767 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6768 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006769 work->cb(work, 1);
6770 radio_work_free(work);
6771 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006772
6773 /* in case we removed the started work */
6774 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006775}
6776
6777
Roshan Pius3a1667e2018-07-03 15:17:14 -07006778void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6779{
6780 struct wpa_radio_work *work;
6781 struct wpa_radio *radio = wpa_s->radio;
6782
6783 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6784 if (work->ctx != ctx)
6785 continue;
6786 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6787 work->type, work, work->started ? " (started)" : "");
6788 radio_work_free(work);
6789 break;
6790 }
6791}
6792
6793
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006794static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6795{
6796 struct wpa_radio *radio = wpa_s->radio;
6797
6798 if (!radio)
6799 return;
6800
6801 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6802 wpa_s->ifname, radio->name);
6803 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006804 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006805 /* If the interface that triggered the external scan was removed, the
6806 * external scan is no longer running. */
6807 if (wpa_s == radio->external_scan_req_interface)
6808 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006809 wpa_s->radio = NULL;
6810 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006811 return; /* Interfaces remain for this radio */
6812
6813 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006814 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006815 os_free(radio);
6816}
6817
6818
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006819void radio_work_check_next(struct wpa_supplicant *wpa_s)
6820{
6821 struct wpa_radio *radio = wpa_s->radio;
6822
6823 if (dl_list_empty(&radio->work))
6824 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006825 if (wpa_s->ext_work_in_progress) {
6826 wpa_printf(MSG_DEBUG,
6827 "External radio work in progress - delay start of pending item");
6828 return;
6829 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006830 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6831 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6832}
6833
6834
6835/**
6836 * radio_add_work - Add a radio work item
6837 * @wpa_s: Pointer to wpa_supplicant data
6838 * @freq: Frequency of the offchannel operation in MHz or 0
6839 * @type: Unique identifier for each type of work
6840 * @next: Force as the next work to be executed
6841 * @cb: Callback function for indicating when radio is available
6842 * @ctx: Context pointer for the work (work->ctx in cb())
6843 * Returns: 0 on success, -1 on failure
6844 *
6845 * This function is used to request time for an operation that requires
6846 * exclusive radio control. Once the radio is available, the registered callback
6847 * function will be called. radio_work_done() must be called once the exclusive
6848 * radio operation has been completed, so that the radio is freed for other
6849 * operations. The special case of deinit=1 is used to free the context data
6850 * during interface removal. That does not allow the callback function to start
6851 * the radio operation, i.e., it must free any resources allocated for the radio
6852 * work and return.
6853 *
6854 * The @freq parameter can be used to indicate a single channel on which the
6855 * offchannel operation will occur. This may allow multiple radio work
6856 * operations to be performed in parallel if they apply for the same channel.
6857 * Setting this to 0 indicates that the work item may use multiple channels or
6858 * requires exclusive control of the radio.
6859 */
6860int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6861 const char *type, int next,
6862 void (*cb)(struct wpa_radio_work *work, int deinit),
6863 void *ctx)
6864{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006865 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006866 struct wpa_radio_work *work;
6867 int was_empty;
6868
6869 work = os_zalloc(sizeof(*work));
6870 if (work == NULL)
6871 return -1;
6872 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6873 os_get_reltime(&work->time);
6874 work->freq = freq;
6875 work->type = type;
6876 work->wpa_s = wpa_s;
6877 work->cb = cb;
6878 work->ctx = ctx;
6879
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006880 if (freq)
6881 work->bands = wpas_freq_to_band(freq);
6882 else if (os_strcmp(type, "scan") == 0 ||
6883 os_strcmp(type, "p2p-scan") == 0)
6884 work->bands = wpas_get_bands(wpa_s,
6885 ((struct wpa_driver_scan_params *)
6886 ctx)->freqs);
6887 else
6888 work->bands = wpas_get_bands(wpa_s, NULL);
6889
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006890 was_empty = dl_list_empty(&wpa_s->radio->work);
6891 if (next)
6892 dl_list_add(&wpa_s->radio->work, &work->list);
6893 else
6894 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6895 if (was_empty) {
6896 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6897 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006898 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6899 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6900 wpa_dbg(wpa_s, MSG_DEBUG,
6901 "Try to schedule a radio work (num_active_works=%u)",
6902 radio->num_active_works);
6903 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006904 }
6905
6906 return 0;
6907}
6908
6909
6910/**
6911 * radio_work_done - Indicate that a radio work item has been completed
6912 * @work: Completed work
6913 *
6914 * This function is called once the callback function registered with
6915 * radio_add_work() has completed its work.
6916 */
6917void radio_work_done(struct wpa_radio_work *work)
6918{
6919 struct wpa_supplicant *wpa_s = work->wpa_s;
6920 struct os_reltime now, diff;
6921 unsigned int started = work->started;
6922
6923 os_get_reltime(&now);
6924 os_reltime_sub(&now, &work->time, &diff);
6925 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6926 work->type, work, started ? "done" : "canceled",
6927 diff.sec, diff.usec);
6928 radio_work_free(work);
6929 if (started)
6930 radio_work_check_next(wpa_s);
6931}
6932
6933
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006934struct wpa_radio_work *
6935radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006936{
6937 struct wpa_radio_work *work;
6938 struct wpa_radio *radio = wpa_s->radio;
6939
6940 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6941 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006942 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006943 }
6944
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006945 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006946}
6947
6948
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006949static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006950 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006951{
6952 const char *ifname, *driver, *rn;
6953
6954 driver = iface->driver;
6955next_driver:
6956 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6957 return -1;
6958
6959 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6960 if (wpa_s->drv_priv == NULL) {
6961 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006962 int level = MSG_ERROR;
6963
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006964 pos = driver ? os_strchr(driver, ',') : NULL;
6965 if (pos) {
6966 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6967 "driver interface - try next driver wrapper");
6968 driver = pos + 1;
6969 goto next_driver;
6970 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006971
6972#ifdef CONFIG_MATCH_IFACE
6973 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6974 level = MSG_DEBUG;
6975#endif /* CONFIG_MATCH_IFACE */
6976 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006977 return -1;
6978 }
6979 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6980 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6981 "driver_param '%s'", wpa_s->conf->driver_param);
6982 return -1;
6983 }
6984
6985 ifname = wpa_drv_get_ifname(wpa_s);
6986 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6987 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6988 "interface name with '%s'", ifname);
6989 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6990 }
6991
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006992 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006993 if (rn && rn[0] == '\0')
6994 rn = NULL;
6995
6996 wpa_s->radio = radio_add_interface(wpa_s, rn);
6997 if (wpa_s->radio == NULL)
6998 return -1;
6999
7000 return 0;
7001}
7002
7003
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007004#ifdef CONFIG_GAS_SERVER
7005
7006static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
7007 unsigned int freq, const u8 *dst,
7008 const u8 *src, const u8 *bssid,
7009 const u8 *data, size_t data_len,
7010 enum offchannel_send_action_result result)
7011{
7012 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
7013 " result=%s",
7014 freq, MAC2STR(dst),
7015 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
7016 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
7017 "FAILED"));
7018 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
7019 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
7020}
7021
7022
7023static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
7024 struct wpabuf *buf, unsigned int wait_time)
7025{
7026 struct wpa_supplicant *wpa_s = ctx;
7027 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7028
7029 if (wait_time > wpa_s->max_remain_on_chan)
7030 wait_time = wpa_s->max_remain_on_chan;
7031
7032 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
7033 wpabuf_head(buf), wpabuf_len(buf),
7034 wait_time, wpas_gas_server_tx_status, 0);
7035}
7036
7037#endif /* CONFIG_GAS_SERVER */
7038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007039static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007040 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007041{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007042 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007043 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007044 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007045
7046 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
7047 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
7048 iface->confname ? iface->confname : "N/A",
7049 iface->driver ? iface->driver : "default",
7050 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
7051 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
7052
7053 if (iface->confname) {
7054#ifdef CONFIG_BACKEND_FILE
7055 wpa_s->confname = os_rel2abs_path(iface->confname);
7056 if (wpa_s->confname == NULL) {
7057 wpa_printf(MSG_ERROR, "Failed to get absolute path "
7058 "for configuration file '%s'.",
7059 iface->confname);
7060 return -1;
7061 }
7062 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
7063 iface->confname, wpa_s->confname);
7064#else /* CONFIG_BACKEND_FILE */
7065 wpa_s->confname = os_strdup(iface->confname);
7066#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00007067 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007068 if (wpa_s->conf == NULL) {
7069 wpa_printf(MSG_ERROR, "Failed to read or parse "
7070 "configuration '%s'.", wpa_s->confname);
7071 return -1;
7072 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07007073 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007074 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00007075 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007076 wpa_printf(MSG_ERROR,
7077 "Failed to read or parse configuration '%s'.",
7078 wpa_s->confanother);
7079 return -1;
7080 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007081
7082 /*
7083 * Override ctrl_interface and driver_param if set on command
7084 * line.
7085 */
7086 if (iface->ctrl_interface) {
7087 os_free(wpa_s->conf->ctrl_interface);
7088 wpa_s->conf->ctrl_interface =
7089 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007090 if (!wpa_s->conf->ctrl_interface) {
7091 wpa_printf(MSG_ERROR,
7092 "Failed to duplicate control interface '%s'.",
7093 iface->ctrl_interface);
7094 return -1;
7095 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007096 }
7097
7098 if (iface->driver_param) {
7099 os_free(wpa_s->conf->driver_param);
7100 wpa_s->conf->driver_param =
7101 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007102 if (!wpa_s->conf->driver_param) {
7103 wpa_printf(MSG_ERROR,
7104 "Failed to duplicate driver param '%s'.",
7105 iface->driver_param);
7106 return -1;
7107 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007108 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007109
7110 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7111 os_free(wpa_s->conf->ctrl_interface);
7112 wpa_s->conf->ctrl_interface = NULL;
7113 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007114 } else
7115 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7116 iface->driver_param);
7117
7118 if (wpa_s->conf == NULL) {
7119 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7120 return -1;
7121 }
7122
7123 if (iface->ifname == NULL) {
7124 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7125 return -1;
7126 }
7127 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7128 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7129 iface->ifname);
7130 return -1;
7131 }
7132 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007133#ifdef CONFIG_MATCH_IFACE
7134 wpa_s->matched = iface->matched;
7135#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007136
7137 if (iface->bridge_ifname) {
7138 if (os_strlen(iface->bridge_ifname) >=
7139 sizeof(wpa_s->bridge_ifname)) {
7140 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7141 "name '%s'.", iface->bridge_ifname);
7142 return -1;
7143 }
7144 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7145 sizeof(wpa_s->bridge_ifname));
7146 }
7147
7148 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007149 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7150 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007151
7152 /* Initialize driver interface and register driver event handler before
7153 * L2 receive handler so that association events are processed before
7154 * EAPOL-Key packets if both become available for the same select()
7155 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007156 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007157 return -1;
7158
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007159 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7160 return -1;
7161
7162 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7163 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7164 NULL);
7165 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7166
7167 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7168 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7169 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7170 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7171 "dot11RSNAConfigPMKLifetime");
7172 return -1;
7173 }
7174
7175 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7176 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7177 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7178 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7179 "dot11RSNAConfigPMKReauthThreshold");
7180 return -1;
7181 }
7182
7183 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7184 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7185 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7186 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7187 "dot11RSNAConfigSATimeout");
7188 return -1;
7189 }
7190
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007191 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7192 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007193 &wpa_s->hw.flags,
7194 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007195 if (wpa_s->hw.modes) {
7196 u16 i;
7197
7198 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7199 if (wpa_s->hw.modes[i].vht_capab) {
7200 wpa_s->hw_capab = CAPAB_VHT;
7201 break;
7202 }
7203
7204 if (wpa_s->hw.modes[i].ht_capab &
7205 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7206 wpa_s->hw_capab = CAPAB_HT40;
7207 else if (wpa_s->hw.modes[i].ht_capab &&
7208 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7209 wpa_s->hw_capab = CAPAB_HT;
7210 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007211 wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007212 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007213
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007214 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7215 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007216 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007217 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007218 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007219 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007220 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007221 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007222 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007223 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007224 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007225 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7226 wpa_s->max_sched_scan_plan_interval =
7227 capa.max_sched_scan_plan_interval;
7228 wpa_s->max_sched_scan_plan_iterations =
7229 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007230 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7231 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007232 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7233 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007234 wpa_s->extended_capa = capa.extended_capa;
7235 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7236 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007237 wpa_s->num_multichan_concurrent =
7238 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007239 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007240 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007241
7242 if (capa.mac_addr_rand_scan_supported)
7243 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7244 if (wpa_s->sched_scan_supported &&
7245 capa.mac_addr_rand_sched_scan_supported)
7246 wpa_s->mac_addr_rand_supported |=
7247 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007248
7249 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7250 if (wpa_s->extended_capa &&
7251 wpa_s->extended_capa_len >= 3 &&
7252 wpa_s->extended_capa[2] & 0x40)
7253 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007254 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007255#ifdef CONFIG_PASN
7256 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7257#endif /* CONFIG_PASN */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007258 wpa_sm_set_driver_bss_selection(wpa_s->wpa,
7259 !!(wpa_s->drv_flags &
7260 WPA_DRIVER_FLAGS_BSS_SELECTION));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007261 if (wpa_s->max_remain_on_chan == 0)
7262 wpa_s->max_remain_on_chan = 1000;
7263
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007264 /*
7265 * Only take p2p_mgmt parameters when P2P Device is supported.
7266 * Doing it here as it determines whether l2_packet_init() will be done
7267 * during wpa_supplicant_driver_init().
7268 */
7269 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7270 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007271
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007272 if (wpa_s->num_multichan_concurrent == 0)
7273 wpa_s->num_multichan_concurrent = 1;
7274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007275 if (wpa_supplicant_driver_init(wpa_s) < 0)
7276 return -1;
7277
7278#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007279 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007280 return -1;
7281#endif /* CONFIG_TDLS */
7282
7283 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7284 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7285 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7286 return -1;
7287 }
7288
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007289#ifdef CONFIG_FST
7290 if (wpa_s->conf->fst_group_id) {
7291 struct fst_iface_cfg cfg;
7292 struct fst_wpa_obj iface_obj;
7293
7294 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7295 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7296 sizeof(cfg.group_id));
7297 cfg.priority = wpa_s->conf->fst_priority;
7298 cfg.llt = wpa_s->conf->fst_llt;
7299
7300 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7301 &iface_obj, &cfg);
7302 if (!wpa_s->fst) {
7303 wpa_msg(wpa_s, MSG_ERROR,
7304 "FST: Cannot attach iface %s to group %s",
7305 wpa_s->ifname, cfg.group_id);
7306 return -1;
7307 }
7308 }
7309#endif /* CONFIG_FST */
7310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007311 if (wpas_wps_init(wpa_s))
7312 return -1;
7313
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007314#ifdef CONFIG_GAS_SERVER
7315 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7316 if (!wpa_s->gas_server) {
7317 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7318 return -1;
7319 }
7320#endif /* CONFIG_GAS_SERVER */
7321
7322#ifdef CONFIG_DPP
7323 if (wpas_dpp_init(wpa_s) < 0)
7324 return -1;
7325#endif /* CONFIG_DPP */
7326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007327 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7328 return -1;
7329 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7330
7331 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7332 if (wpa_s->ctrl_iface == NULL) {
7333 wpa_printf(MSG_ERROR,
7334 "Failed to initialize control interface '%s'.\n"
7335 "You may have another wpa_supplicant process "
7336 "already running or the file was\n"
7337 "left by an unclean termination of wpa_supplicant "
7338 "in which case you will need\n"
7339 "to manually remove this file before starting "
7340 "wpa_supplicant again.\n",
7341 wpa_s->conf->ctrl_interface);
7342 return -1;
7343 }
7344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007345 wpa_s->gas = gas_query_init(wpa_s);
7346 if (wpa_s->gas == NULL) {
7347 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7348 return -1;
7349 }
7350
Roshan Pius3a1667e2018-07-03 15:17:14 -07007351 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7352 wpa_s->p2p_mgmt) &&
7353 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007354 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7355 return -1;
7356 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007357
7358 if (wpa_bss_init(wpa_s) < 0)
7359 return -1;
7360
Paul Stewart092955c2017-02-06 09:13:09 -08007361#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7362#ifdef CONFIG_MESH
7363 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7364#endif /* CONFIG_MESH */
7365#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7366
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007367 /*
7368 * Set Wake-on-WLAN triggers, if configured.
7369 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7370 * have effect anyway when the interface is down).
7371 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007372 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007373 return -1;
7374
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007375#ifdef CONFIG_EAP_PROXY
7376{
7377 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007378 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7379 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007380 if (wpa_s->mnc_len > 0) {
7381 wpa_s->imsi[len] = '\0';
7382 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7383 wpa_s->imsi, wpa_s->mnc_len);
7384 } else {
7385 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7386 }
7387}
7388#endif /* CONFIG_EAP_PROXY */
7389
Dmitry Shmidt04949592012-07-19 12:16:46 -07007390 if (pcsc_reader_init(wpa_s) < 0)
7391 return -1;
7392
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007393 if (wpas_init_ext_pw(wpa_s) < 0)
7394 return -1;
7395
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007396 wpas_rrm_reset(wpa_s);
7397
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007398 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7399
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007400#ifdef CONFIG_HS20
7401 hs20_init(wpa_s);
7402#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007403#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007404 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007405 if ((wpa_s->conf->oce & OCE_STA) &&
7406 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7407 wpa_s->enable_oce = OCE_STA;
7408 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7409 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7410 /* TODO: Need to add STA-CFON support */
7411 wpa_printf(MSG_ERROR,
7412 "OCE STA-CFON feature is not yet supported");
7413 }
7414 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007415 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7416#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007417
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007418 wpa_supplicant_set_default_scan_ies(wpa_s);
7419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007420 return 0;
7421}
7422
7423
7424static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007425 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007426{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007427 struct wpa_global *global = wpa_s->global;
7428 struct wpa_supplicant *iface, *prev;
7429
Jimmy Chen0e73c002021-08-18 13:21:30 +08007430 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007431 wpas_p2p_group_remove(wpa_s, "*");
7432
7433 iface = global->ifaces;
7434 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007435 if (iface->p2pdev == wpa_s)
7436 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007437 if (iface == wpa_s || iface->parent != wpa_s) {
7438 iface = iface->next;
7439 continue;
7440 }
7441 wpa_printf(MSG_DEBUG,
7442 "Remove remaining child interface %s from parent %s",
7443 iface->ifname, wpa_s->ifname);
7444 prev = iface;
7445 iface = iface->next;
7446 wpa_supplicant_remove_iface(global, prev, terminate);
7447 }
7448
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007449 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007450 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007451 /*
7452 * Don't deauthenticate if WoWLAN is enable and not explicitly
7453 * been configured to disconnect.
7454 */
7455 if (!wpa_drv_get_wowlan(wpa_s) ||
7456 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007457 wpa_supplicant_deauthenticate(
7458 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007459
Hai Shalomfdcde762020-04-02 11:19:20 -07007460 wpa_drv_set_countermeasures(wpa_s, 0);
7461 wpa_clear_keys(wpa_s, NULL);
7462 } else {
7463 wpa_msg(wpa_s, MSG_INFO,
7464 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7465 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007466 }
7467
7468 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007469 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007470
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007471 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007472 radio_remove_interface(wpa_s);
7473
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007474#ifdef CONFIG_FST
7475 if (wpa_s->fst) {
7476 fst_detach(wpa_s->fst);
7477 wpa_s->fst = NULL;
7478 }
7479 if (wpa_s->received_mb_ies) {
7480 wpabuf_free(wpa_s->received_mb_ies);
7481 wpa_s->received_mb_ies = NULL;
7482 }
7483#endif /* CONFIG_FST */
7484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007485 if (wpa_s->drv_priv)
7486 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007487
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007488 if (notify)
7489 wpas_notify_iface_removed(wpa_s);
7490
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007491 if (terminate)
7492 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007493
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007494 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7495 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007496
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007497#ifdef CONFIG_MESH
7498 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007499 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007500 wpa_s->ifmsh = NULL;
7501 }
7502#endif /* CONFIG_MESH */
7503
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007504 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007505 wpa_config_free(wpa_s->conf);
7506 wpa_s->conf = NULL;
7507 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007508
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007509 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007510 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007511
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007512 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007513}
7514
7515
Dmitry Shmidte4663042016-04-04 10:07:49 -07007516#ifdef CONFIG_MATCH_IFACE
7517
7518/**
7519 * wpa_supplicant_match_iface - Match an interface description to a name
7520 * @global: Pointer to global data from wpa_supplicant_init()
7521 * @ifname: Name of the interface to match
7522 * Returns: Pointer to the created interface description or %NULL on failure
7523 */
7524struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7525 const char *ifname)
7526{
7527 int i;
7528 struct wpa_interface *iface, *miface;
7529
7530 for (i = 0; i < global->params.match_iface_count; i++) {
7531 miface = &global->params.match_ifaces[i];
7532 if (!miface->ifname ||
7533 fnmatch(miface->ifname, ifname, 0) == 0) {
7534 iface = os_zalloc(sizeof(*iface));
7535 if (!iface)
7536 return NULL;
7537 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007538 if (!miface->ifname)
7539 iface->matched = WPA_IFACE_MATCHED_NULL;
7540 else
7541 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007542 iface->ifname = ifname;
7543 return iface;
7544 }
7545 }
7546
7547 return NULL;
7548}
7549
7550
7551/**
7552 * wpa_supplicant_match_existing - Match existing interfaces
7553 * @global: Pointer to global data from wpa_supplicant_init()
7554 * Returns: 0 on success, -1 on failure
7555 */
7556static int wpa_supplicant_match_existing(struct wpa_global *global)
7557{
7558 struct if_nameindex *ifi, *ifp;
7559 struct wpa_supplicant *wpa_s;
7560 struct wpa_interface *iface;
7561
7562 ifp = if_nameindex();
7563 if (!ifp) {
7564 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7565 return -1;
7566 }
7567
7568 for (ifi = ifp; ifi->if_name; ifi++) {
7569 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7570 if (wpa_s)
7571 continue;
7572 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7573 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007574 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007575 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007576 }
7577 }
7578
7579 if_freenameindex(ifp);
7580 return 0;
7581}
7582
7583#endif /* CONFIG_MATCH_IFACE */
7584
7585
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007586/**
7587 * wpa_supplicant_add_iface - Add a new network interface
7588 * @global: Pointer to global data from wpa_supplicant_init()
7589 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007590 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007591 * Returns: Pointer to the created interface or %NULL on failure
7592 *
7593 * This function is used to add new network interfaces for %wpa_supplicant.
7594 * This can be called before wpa_supplicant_run() to add interfaces before the
7595 * main event loop has been started. In addition, new interfaces can be added
7596 * dynamically while %wpa_supplicant is already running. This could happen,
7597 * e.g., when a hotplug network adapter is inserted.
7598 */
7599struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007600 struct wpa_interface *iface,
7601 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007602{
7603 struct wpa_supplicant *wpa_s;
7604 struct wpa_interface t_iface;
7605 struct wpa_ssid *ssid;
7606
7607 if (global == NULL || iface == NULL)
7608 return NULL;
7609
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007610 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007611 if (wpa_s == NULL)
7612 return NULL;
7613
7614 wpa_s->global = global;
7615
7616 t_iface = *iface;
7617 if (global->params.override_driver) {
7618 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7619 "('%s' -> '%s')",
7620 iface->driver, global->params.override_driver);
7621 t_iface.driver = global->params.override_driver;
7622 }
7623 if (global->params.override_ctrl_interface) {
7624 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7625 "ctrl_interface ('%s' -> '%s')",
7626 iface->ctrl_interface,
7627 global->params.override_ctrl_interface);
7628 t_iface.ctrl_interface =
7629 global->params.override_ctrl_interface;
7630 }
7631 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7632 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7633 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007634 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007635 return NULL;
7636 }
7637
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007638 /* Notify the control interfaces about new iface */
7639 if (wpas_notify_iface_added(wpa_s)) {
7640 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7641 return NULL;
7642 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007643
Jimmy Chene2206be2022-07-10 10:25:21 +08007644 /* Notify the control interfaces about new networks */
7645 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7646 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007647 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007648 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7649 && os_strncmp((const char *) ssid->ssid,
7650 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7651 wpas_notify_persistent_group_added(wpa_s, ssid);
7652 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007653 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007654
7655 wpa_s->next = global->ifaces;
7656 global->ifaces = wpa_s;
7657
7658 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007659 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007660
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007661#ifdef CONFIG_P2P
7662 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007663 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007664 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007665 wpas_p2p_add_p2pdev_interface(
7666 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007667 wpa_printf(MSG_INFO,
7668 "P2P: Failed to enable P2P Device interface");
7669 /* Try to continue without. P2P will be disabled. */
7670 }
7671#endif /* CONFIG_P2P */
7672
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007673 return wpa_s;
7674}
7675
7676
7677/**
7678 * wpa_supplicant_remove_iface - Remove a network interface
7679 * @global: Pointer to global data from wpa_supplicant_init()
7680 * @wpa_s: Pointer to the network interface to be removed
7681 * Returns: 0 if interface was removed, -1 if interface was not found
7682 *
7683 * This function can be used to dynamically remove network interfaces from
7684 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7685 * addition, this function is used to remove all remaining interfaces when
7686 * %wpa_supplicant is terminated.
7687 */
7688int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007689 struct wpa_supplicant *wpa_s,
7690 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007691{
7692 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007693#ifdef CONFIG_MESH
7694 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7695 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007696 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007697#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007698
7699 /* Remove interface from the global list of interfaces */
7700 prev = global->ifaces;
7701 if (prev == wpa_s) {
7702 global->ifaces = wpa_s->next;
7703 } else {
7704 while (prev && prev->next != wpa_s)
7705 prev = prev->next;
7706 if (prev == NULL)
7707 return -1;
7708 prev->next = wpa_s->next;
7709 }
7710
7711 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007713#ifdef CONFIG_MESH
7714 if (mesh_if_created) {
7715 ifname = os_strdup(wpa_s->ifname);
7716 if (ifname == NULL) {
7717 wpa_dbg(wpa_s, MSG_ERROR,
7718 "mesh: Failed to malloc ifname");
7719 return -1;
7720 }
7721 }
7722#endif /* CONFIG_MESH */
7723
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007724 if (global->p2p_group_formation == wpa_s)
7725 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007726 if (global->p2p_invite_group == wpa_s)
7727 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007728 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007729
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007730#ifdef CONFIG_MESH
7731 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007732 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007733 os_free(ifname);
7734 }
7735#endif /* CONFIG_MESH */
7736
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007737 return 0;
7738}
7739
7740
7741/**
7742 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7743 * @wpa_s: Pointer to the network interface
7744 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7745 */
7746const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7747{
7748 const char *eapol_method;
7749
7750 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7751 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7752 return "NO-EAP";
7753 }
7754
7755 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7756 if (eapol_method == NULL)
7757 return "UNKNOWN-EAP";
7758
7759 return eapol_method;
7760}
7761
7762
7763/**
7764 * wpa_supplicant_get_iface - Get a new network interface
7765 * @global: Pointer to global data from wpa_supplicant_init()
7766 * @ifname: Interface name
7767 * Returns: Pointer to the interface or %NULL if not found
7768 */
7769struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7770 const char *ifname)
7771{
7772 struct wpa_supplicant *wpa_s;
7773
7774 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7775 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7776 return wpa_s;
7777 }
7778 return NULL;
7779}
7780
7781
7782#ifndef CONFIG_NO_WPA_MSG
7783static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7784{
7785 struct wpa_supplicant *wpa_s = ctx;
7786 if (wpa_s == NULL)
7787 return NULL;
7788 return wpa_s->ifname;
7789}
7790#endif /* CONFIG_NO_WPA_MSG */
7791
7792
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007793#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7794#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7795#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7796
7797/* Periodic cleanup tasks */
7798static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7799{
7800 struct wpa_global *global = eloop_ctx;
7801 struct wpa_supplicant *wpa_s;
7802
7803 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7804 wpas_periodic, global, NULL);
7805
7806#ifdef CONFIG_P2P
7807 if (global->p2p)
7808 p2p_expire_peers(global->p2p);
7809#endif /* CONFIG_P2P */
7810
7811 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7812 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7813#ifdef CONFIG_AP
7814 ap_periodic(wpa_s);
7815#endif /* CONFIG_AP */
7816 }
7817}
7818
7819
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007820/**
7821 * wpa_supplicant_init - Initialize %wpa_supplicant
7822 * @params: Parameters for %wpa_supplicant
7823 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7824 *
7825 * This function is used to initialize %wpa_supplicant. After successful
7826 * initialization, the returned data pointer can be used to add and remove
7827 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7828 */
7829struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7830{
7831 struct wpa_global *global;
7832 int ret, i;
7833
7834 if (params == NULL)
7835 return NULL;
7836
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007837#ifdef CONFIG_DRIVER_NDIS
7838 {
7839 void driver_ndis_init_ops(void);
7840 driver_ndis_init_ops();
7841 }
7842#endif /* CONFIG_DRIVER_NDIS */
7843
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007844#ifndef CONFIG_NO_WPA_MSG
7845 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7846#endif /* CONFIG_NO_WPA_MSG */
7847
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007848 if (params->wpa_debug_file_path)
7849 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007850 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007851 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007852 if (params->wpa_debug_syslog)
7853 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007854 if (params->wpa_debug_tracing) {
7855 ret = wpa_debug_open_linux_tracing();
7856 if (ret) {
7857 wpa_printf(MSG_ERROR,
7858 "Failed to enable trace logging");
7859 return NULL;
7860 }
7861 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007862
7863 ret = eap_register_methods();
7864 if (ret) {
7865 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7866 if (ret == -2)
7867 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7868 "the same EAP type.");
7869 return NULL;
7870 }
7871
7872 global = os_zalloc(sizeof(*global));
7873 if (global == NULL)
7874 return NULL;
7875 dl_list_init(&global->p2p_srv_bonjour);
7876 dl_list_init(&global->p2p_srv_upnp);
7877 global->params.daemonize = params->daemonize;
7878 global->params.wait_for_monitor = params->wait_for_monitor;
7879 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007880
7881 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007882 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007883 if (!global->params.pid_file) {
7884 wpa_supplicant_deinit(global);
7885 return NULL;
7886 }
7887 }
7888
7889 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007890 global->params.ctrl_interface =
7891 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007892 if (!global->params.ctrl_interface) {
7893 wpa_supplicant_deinit(global);
7894 return NULL;
7895 }
7896 }
7897
7898 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007899 global->params.ctrl_interface_group =
7900 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007901 if (!global->params.ctrl_interface_group) {
7902 wpa_supplicant_deinit(global);
7903 return NULL;
7904 }
7905 }
7906
7907 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 global->params.override_driver =
7909 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007910 if (!global->params.override_driver) {
7911 wpa_supplicant_deinit(global);
7912 return NULL;
7913 }
7914 }
7915
7916 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007917 global->params.override_ctrl_interface =
7918 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007919 if (!global->params.override_ctrl_interface) {
7920 wpa_supplicant_deinit(global);
7921 return NULL;
7922 }
7923 }
7924
Dmitry Shmidte4663042016-04-04 10:07:49 -07007925#ifdef CONFIG_MATCH_IFACE
7926 global->params.match_iface_count = params->match_iface_count;
7927 if (params->match_iface_count) {
7928 global->params.match_ifaces =
7929 os_calloc(params->match_iface_count,
7930 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007931 if (!global->params.match_ifaces) {
7932 wpa_printf(MSG_ERROR,
7933 "Failed to allocate match interfaces");
7934 wpa_supplicant_deinit(global);
7935 return NULL;
7936 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007937 os_memcpy(global->params.match_ifaces,
7938 params->match_ifaces,
7939 params->match_iface_count *
7940 sizeof(struct wpa_interface));
7941 }
7942#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007943#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007944 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007945 global->params.conf_p2p_dev =
7946 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007947 if (!global->params.conf_p2p_dev) {
7948 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7949 wpa_supplicant_deinit(global);
7950 return NULL;
7951 }
7952 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007953#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007954 wpa_debug_level = global->params.wpa_debug_level =
7955 params->wpa_debug_level;
7956 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7957 params->wpa_debug_show_keys;
7958 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7959 params->wpa_debug_timestamp;
7960
Hai Shalomfdcde762020-04-02 11:19:20 -07007961 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007962
7963 if (eloop_init()) {
7964 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7965 wpa_supplicant_deinit(global);
7966 return NULL;
7967 }
7968
Jouni Malinen75ecf522011-06-27 15:19:46 -07007969 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007970
7971 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7972 if (global->ctrl_iface == NULL) {
7973 wpa_supplicant_deinit(global);
7974 return NULL;
7975 }
7976
7977 if (wpas_notify_supplicant_initialized(global)) {
7978 wpa_supplicant_deinit(global);
7979 return NULL;
7980 }
7981
7982 for (i = 0; wpa_drivers[i]; i++)
7983 global->drv_count++;
7984 if (global->drv_count == 0) {
7985 wpa_printf(MSG_ERROR, "No drivers enabled");
7986 wpa_supplicant_deinit(global);
7987 return NULL;
7988 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007989 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007990 if (global->drv_priv == NULL) {
7991 wpa_supplicant_deinit(global);
7992 return NULL;
7993 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007994
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007995#ifdef CONFIG_WIFI_DISPLAY
7996 if (wifi_display_init(global) < 0) {
7997 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7998 wpa_supplicant_deinit(global);
7999 return NULL;
8000 }
8001#endif /* CONFIG_WIFI_DISPLAY */
8002
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008003 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
8004 wpas_periodic, global, NULL);
8005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008006 return global;
8007}
8008
8009
8010/**
8011 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
8012 * @global: Pointer to global data from wpa_supplicant_init()
8013 * Returns: 0 after successful event loop run, -1 on failure
8014 *
8015 * This function starts the main event loop and continues running as long as
8016 * there are any remaining events. In most cases, this function is running as
8017 * long as the %wpa_supplicant process in still in use.
8018 */
8019int wpa_supplicant_run(struct wpa_global *global)
8020{
8021 struct wpa_supplicant *wpa_s;
8022
8023 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08008024 (wpa_supplicant_daemon(global->params.pid_file) ||
8025 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008026 return -1;
8027
Dmitry Shmidte4663042016-04-04 10:07:49 -07008028#ifdef CONFIG_MATCH_IFACE
8029 if (wpa_supplicant_match_existing(global))
8030 return -1;
8031#endif
8032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008033 if (global->params.wait_for_monitor) {
8034 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08008035 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008036 wpa_supplicant_ctrl_iface_wait(
8037 wpa_s->ctrl_iface);
8038 }
8039
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008040#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00008041 // If daemonize is enabled, initialize AIDL here.
8042 if (global->params.daemonize) {
8043 global->aidl = wpas_aidl_init(global);
8044 if (!global->aidl)
8045 return -1;
8046 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07008047#endif /* CONFIG_AIDL */
8048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008049 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
8050 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
8051
8052 eloop_run();
8053
8054 return 0;
8055}
8056
8057
8058/**
8059 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
8060 * @global: Pointer to global data from wpa_supplicant_init()
8061 *
8062 * This function is called to deinitialize %wpa_supplicant and to free all
8063 * allocated resources. Remaining network interfaces will also be removed.
8064 */
8065void wpa_supplicant_deinit(struct wpa_global *global)
8066{
8067 int i;
8068
8069 if (global == NULL)
8070 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008071
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008072 eloop_cancel_timeout(wpas_periodic, global, NULL);
8073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008074#ifdef CONFIG_WIFI_DISPLAY
8075 wifi_display_deinit(global);
8076#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008077
8078 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07008079 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008080
8081 if (global->ctrl_iface)
8082 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
8083
8084 wpas_notify_supplicant_deinitialized(global);
8085
8086 eap_peer_unregister_methods();
8087#ifdef CONFIG_AP
8088 eap_server_unregister_methods();
8089#endif /* CONFIG_AP */
8090
8091 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8092 if (!global->drv_priv[i])
8093 continue;
8094 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8095 }
8096 os_free(global->drv_priv);
8097
8098 random_deinit();
8099
8100 eloop_destroy();
8101
8102 if (global->params.pid_file) {
8103 os_daemonize_terminate(global->params.pid_file);
8104 os_free(global->params.pid_file);
8105 }
8106 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008107 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008108 os_free(global->params.override_driver);
8109 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008110#ifdef CONFIG_MATCH_IFACE
8111 os_free(global->params.match_ifaces);
8112#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008113#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008114 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008115#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008116
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008117 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008118 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008119 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008121 os_free(global);
8122 wpa_debug_close_syslog();
8123 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008124 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008125}
8126
8127
8128void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8129{
8130 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8131 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8132 char country[3];
8133 country[0] = wpa_s->conf->country[0];
8134 country[1] = wpa_s->conf->country[1];
8135 country[2] = '\0';
8136 if (wpa_drv_set_country(wpa_s, country) < 0) {
8137 wpa_printf(MSG_ERROR, "Failed to set country code "
8138 "'%s'", country);
8139 }
8140 }
8141
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008142 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8143 wpas_init_ext_pw(wpa_s);
8144
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008145 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8146 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8147
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008148 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8149 struct wpa_driver_capa capa;
8150 int res = wpa_drv_get_capa(wpa_s, &capa);
8151
8152 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8153 wpa_printf(MSG_ERROR,
8154 "Failed to update wowlan_triggers to '%s'",
8155 wpa_s->conf->wowlan_triggers);
8156 }
8157
Hai Shalom81f62d82019-07-22 12:10:00 -07008158 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8159 wpa_supplicant_set_default_scan_ies(wpa_s);
8160
Hai Shalom899fcc72020-10-19 14:38:18 -07008161#ifdef CONFIG_BGSCAN
8162 /*
8163 * We default to global bgscan parameters only when per-network bgscan
8164 * parameters aren't set. Only bother resetting bgscan parameters if
8165 * this is the case.
8166 */
8167 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8168 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8169 wpa_s->wpa_state == WPA_COMPLETED)
8170 wpa_supplicant_reset_bgscan(wpa_s);
8171#endif /* CONFIG_BGSCAN */
8172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008173#ifdef CONFIG_WPS
8174 wpas_wps_update_config(wpa_s);
8175#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008176 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008177 wpa_s->conf->changed_parameters = 0;
8178}
8179
8180
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008181void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008182{
8183 int i;
8184
8185 for (i = 0; i < *num_freqs; i++) {
8186 if (freqs[i] == freq)
8187 return;
8188 }
8189
8190 freqs[*num_freqs] = freq;
8191 (*num_freqs)++;
8192}
8193
8194
8195static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8196{
8197 struct wpa_bss *bss, *cbss;
8198 const int max_freqs = 10;
8199 int *freqs;
8200 int num_freqs = 0;
8201
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008202 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008203 if (freqs == NULL)
8204 return NULL;
8205
8206 cbss = wpa_s->current_bss;
8207
8208 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8209 if (bss == cbss)
8210 continue;
8211 if (bss->ssid_len == cbss->ssid_len &&
8212 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008213 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008214 add_freq(freqs, &num_freqs, bss->freq);
8215 if (num_freqs == max_freqs)
8216 break;
8217 }
8218 }
8219
8220 if (num_freqs == 0) {
8221 os_free(freqs);
8222 freqs = NULL;
8223 }
8224
8225 return freqs;
8226}
8227
8228
8229void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8230{
8231 int timeout;
8232 int count;
8233 int *freqs = NULL;
8234
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008235 wpas_connect_work_done(wpa_s);
8236
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008237 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008238 * Remove possible authentication timeout since the connection failed.
8239 */
8240 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8241
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008242 /*
Hai Shalom60840252021-02-19 19:02:11 -08008243 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008244 * generated based on local request to disconnect.
8245 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008246 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008247 wpa_s->own_disconnect_req = 0;
8248 wpa_dbg(wpa_s, MSG_DEBUG,
8249 "Ignore connection failure due to local request to disconnect");
8250 return;
8251 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008252 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008253 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8254 "indication since interface has been put into "
8255 "disconnected state");
8256 return;
8257 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008258 if (wpa_s->auto_reconnect_disabled) {
8259 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8260 "indication since auto connect is disabled");
8261 return;
8262 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008263
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008264 /*
Hai Shalom60840252021-02-19 19:02:11 -08008265 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008266 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008267 */
Hai Shalom60840252021-02-19 19:02:11 -08008268 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008269 if (count == 1 && wpa_s->current_bss) {
8270 /*
Hai Shalom60840252021-02-19 19:02:11 -08008271 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008272 * another BSS available for the same ESS, we should try that
8273 * next. Otherwise, we may as well try this one once more
8274 * before allowing other, likely worse, ESSes to be considered.
8275 */
8276 freqs = get_bss_freqs_in_ess(wpa_s);
8277 if (freqs) {
8278 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8279 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008280 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008281 /*
8282 * On the next scan, go through only the known channels
8283 * used in this ESS based on previous scans to speed up
8284 * common load balancing use case.
8285 */
8286 os_free(wpa_s->next_scan_freqs);
8287 wpa_s->next_scan_freqs = freqs;
8288 }
8289 }
8290
Hai Shalom899fcc72020-10-19 14:38:18 -07008291 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008292
Hai Shalom899fcc72020-10-19 14:38:18 -07008293 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008294 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8295 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008296 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008297 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008298 /*
8299 * Multiple consecutive connection failures mean that other APs are
8300 * either not available or have already been tried, so we can start
8301 * increasing the delay here to avoid constant scanning.
8302 */
8303 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008304 case 1:
8305 timeout = 100;
8306 break;
8307 case 2:
8308 timeout = 500;
8309 break;
8310 case 3:
8311 timeout = 1000;
8312 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008313 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008314 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008315 break;
8316 default:
8317 timeout = 10000;
8318 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008319 }
8320
Hai Shalom899fcc72020-10-19 14:38:18 -07008321 wpa_dbg(wpa_s, MSG_DEBUG,
8322 "Consecutive connection failures: %d --> request scan in %d ms",
8323 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008324
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008325 /*
8326 * TODO: if more than one possible AP is available in scan results,
8327 * could try the other ones before requesting a new scan.
8328 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008329
8330 /* speed up the connection attempt with normal scan */
8331 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008332 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8333 1000 * (timeout % 1000));
8334}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008335
8336
Hai Shalomce48b4a2018-09-05 11:41:35 -07008337#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008338
8339void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8340{
8341 struct wpa_ssid *ssid = wpa_s->current_ssid;
8342 const u8 *realm, *username, *rrk;
8343 size_t realm_len, username_len, rrk_len;
8344 u16 next_seq_num;
8345
8346 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8347 * Check for ERP keys existing to limit when this can be done since
8348 * the rejection response is not protected and such triggers should
8349 * really not allow internal state to be modified unless required to
8350 * avoid significant issues in functionality. In addition, drop
8351 * externally configure PMKSA entries even without ERP keys since it
8352 * is possible for an external component to add PMKSA entries for FILS
8353 * authentication without restoring previously generated ERP keys.
8354 *
8355 * In this case, this is needed to allow recovery from cases where the
8356 * AP or authentication server has dropped PMKSAs and ERP keys. */
8357 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8358 return;
8359
8360 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8361 &username, &username_len,
8362 &realm, &realm_len, &next_seq_num,
8363 &rrk, &rrk_len) != 0 ||
8364 !realm) {
8365 wpa_dbg(wpa_s, MSG_DEBUG,
8366 "FILS: Drop external PMKSA cache entry");
8367 wpa_sm_aborted_external_cached(wpa_s->wpa);
8368 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8369 return;
8370 }
8371
8372 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8373 wpa_sm_aborted_cached(wpa_s->wpa);
8374 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8375}
8376
8377
Hai Shalomce48b4a2018-09-05 11:41:35 -07008378void fils_connection_failure(struct wpa_supplicant *wpa_s)
8379{
8380 struct wpa_ssid *ssid = wpa_s->current_ssid;
8381 const u8 *realm, *username, *rrk;
8382 size_t realm_len, username_len, rrk_len;
8383 u16 next_seq_num;
8384
8385 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8386 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8387 &username, &username_len,
8388 &realm, &realm_len, &next_seq_num,
8389 &rrk, &rrk_len) != 0 ||
8390 !realm)
8391 return;
8392
8393 wpa_hexdump_ascii(MSG_DEBUG,
8394 "FILS: Store last connection failure realm",
8395 realm, realm_len);
8396 os_free(wpa_s->last_con_fail_realm);
8397 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8398 if (wpa_s->last_con_fail_realm) {
8399 wpa_s->last_con_fail_realm_len = realm_len;
8400 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8401 }
8402}
8403#endif /* CONFIG_FILS */
8404
8405
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008406int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8407{
8408 return wpa_s->conf->ap_scan == 2 ||
8409 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8410}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008411
Dmitry Shmidt04949592012-07-19 12:16:46 -07008412
Gabriel Biren57ededa2021-09-03 16:08:50 +00008413#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008414int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8415 struct wpa_ssid *ssid,
8416 const char *field,
8417 const char *value)
8418{
8419#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008420 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008421
8422 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8423 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8424 (const u8 *) value, os_strlen(value));
8425
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008426 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008427 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008428#else /* IEEE8021X_EAPOL */
8429 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8430 return -1;
8431#endif /* IEEE8021X_EAPOL */
8432}
8433
8434int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8435 struct wpa_ssid *ssid,
8436 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008437 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008438{
8439#ifdef IEEE8021X_EAPOL
8440 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008441 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008442
8443 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008444 case WPA_CTRL_REQ_EAP_IDENTITY:
8445 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008446 os_free(eap->imsi_identity);
8447 if (value == NULL)
8448 return -1;
8449 identity = os_strchr(value, ':');
8450 if (identity == NULL) {
8451 /* plain identity */
8452 eap->identity = (u8 *)os_strdup(value);
8453 eap->identity_len = os_strlen(value);
8454 } else {
8455 /* have both plain identity and encrypted identity */
8456 imsi_identity = value;
8457 *identity++ = '\0';
8458 /* plain identity */
8459 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8460 eap->imsi_identity_len = strlen(imsi_identity);
8461 /* encrypted identity */
8462 eap->identity = (u8 *)dup_binstr(identity,
8463 value_len - strlen(imsi_identity) - 1);
8464 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8465 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008466 eap->pending_req_identity = 0;
8467 if (ssid == wpa_s->current_ssid)
8468 wpa_s->reassociate = 1;
8469 break;
8470 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008471 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008472 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008473 if (!eap->password)
8474 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008475 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008476 eap->pending_req_password = 0;
8477 if (ssid == wpa_s->current_ssid)
8478 wpa_s->reassociate = 1;
8479 break;
8480 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008481 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008482 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008483 if (!eap->new_password)
8484 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008485 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008486 eap->pending_req_new_password = 0;
8487 if (ssid == wpa_s->current_ssid)
8488 wpa_s->reassociate = 1;
8489 break;
8490 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008491 str_clear_free(eap->cert.pin);
8492 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008493 if (!eap->cert.pin)
8494 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008495 eap->pending_req_pin = 0;
8496 if (ssid == wpa_s->current_ssid)
8497 wpa_s->reassociate = 1;
8498 break;
8499 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008500 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008501 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008502 if (!eap->otp)
8503 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008504 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008505 os_free(eap->pending_req_otp);
8506 eap->pending_req_otp = NULL;
8507 eap->pending_req_otp_len = 0;
8508 break;
8509 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008510 str_clear_free(eap->cert.private_key_passwd);
8511 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008512 if (!eap->cert.private_key_passwd)
8513 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008514 eap->pending_req_passphrase = 0;
8515 if (ssid == wpa_s->current_ssid)
8516 wpa_s->reassociate = 1;
8517 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008518 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008519 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008520 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008521 if (!eap->external_sim_resp)
8522 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008523 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008524 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008525 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8526 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8527 return -1;
8528 ssid->mem_only_psk = 1;
8529 if (ssid->passphrase)
8530 wpa_config_update_psk(ssid);
8531 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8532 wpa_supplicant_req_scan(wpa_s, 0, 0);
8533 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008534 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8535 if (eap->pending_ext_cert_check != PENDING_CHECK)
8536 return -1;
8537 if (os_strcmp(value, "good") == 0)
8538 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8539 else if (os_strcmp(value, "bad") == 0)
8540 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8541 else
8542 return -1;
8543 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008544 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008545 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008546 return -1;
8547 }
8548
8549 return 0;
8550#else /* IEEE8021X_EAPOL */
8551 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8552 return -1;
8553#endif /* IEEE8021X_EAPOL */
8554}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008555#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008556
8557
8558int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8559{
Hai Shalomfdcde762020-04-02 11:19:20 -07008560#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008561 int i;
8562 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008563#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008564
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008565 if (wpa_s->p2p_mgmt)
8566 return 1; /* no normal network profiles on p2p_mgmt interface */
8567
Dmitry Shmidt04949592012-07-19 12:16:46 -07008568 if (ssid == NULL)
8569 return 1;
8570
8571 if (ssid->disabled)
8572 return 1;
8573
Hai Shalomfdcde762020-04-02 11:19:20 -07008574#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008575 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008576 drv_enc = wpa_s->drv_enc;
8577 else
8578 drv_enc = (unsigned int) -1;
8579
8580 for (i = 0; i < NUM_WEP_KEYS; i++) {
8581 size_t len = ssid->wep_key_len[i];
8582 if (len == 0)
8583 continue;
8584 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8585 continue;
8586 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8587 continue;
8588 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8589 continue;
8590 return 1; /* invalid WEP key */
8591 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008592#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008593
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008594 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008595 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008596 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008597 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008598 return 1;
8599
Sunil Ravi89eba102022-09-13 21:04:37 -07008600#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008601#ifdef CRYPTO_RSA_OAEP_SHA256
8602 if (ssid->eap.imsi_privacy_cert) {
8603 struct crypto_rsa_key *key;
8604 bool failed = false;
8605
8606 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8607 if (!key)
8608 failed = true;
8609 crypto_rsa_key_free(key);
8610 if (failed) {
8611 wpa_printf(MSG_DEBUG,
8612 "Invalid imsi_privacy_cert (%s) - disable network",
8613 ssid->eap.imsi_privacy_cert);
8614 return 1;
8615 }
8616 }
8617#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008618#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008619
Dmitry Shmidt04949592012-07-19 12:16:46 -07008620 return 0;
8621}
8622
8623
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008624int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8625{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008626 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8627 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8628 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8629 /*
8630 * Driver does not support BIP -- ignore pmf=1 default
8631 * since the connection with PMF would fail and the
8632 * configuration does not require PMF to be enabled.
8633 */
8634 return NO_MGMT_FRAME_PROTECTION;
8635 }
8636
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008637 if (ssid &&
8638 (ssid->key_mgmt &
8639 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8640 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8641 /*
8642 * Do not use the default PMF value for non-RSN networks
8643 * since PMF is available only with RSN and pmf=2
8644 * configuration would otherwise prevent connections to
8645 * all open networks.
8646 */
8647 return NO_MGMT_FRAME_PROTECTION;
8648 }
8649
Sunil Ravi77d572f2023-01-17 23:58:31 +00008650#ifdef CONFIG_OCV
8651 /* Enable PMF if OCV is being enabled */
8652 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8653 ssid && ssid->ocv)
8654 return MGMT_FRAME_PROTECTION_OPTIONAL;
8655#endif /* CONFIG_OCV */
8656
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008657 return wpa_s->conf->pmf;
8658 }
8659
8660 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008661}
8662
8663
Sunil Ravi77d572f2023-01-17 23:58:31 +00008664#ifdef CONFIG_SAE
8665bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8666 struct wpa_ssid *ssid,
8667 const struct wpa_ie_data *ie)
8668{
8669 return wpa_s->conf->sae_check_mfp &&
8670 (!(ie->capabilities &
8671 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8672 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8673}
8674#endif /* CONFIG_SAE */
8675
8676
Hai Shalomc1a21442022-02-04 13:43:00 -08008677int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8678{
8679 if (wpa_s->current_ssid == NULL ||
8680 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8681 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8682 return 0;
8683 return wpa_sm_pmf_enabled(wpa_s->wpa);
8684}
8685
8686
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008687int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008688{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008689 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008690 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008691 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008692 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008693 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008694}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008695
8696
Sunil Ravi77d572f2023-01-17 23:58:31 +00008697void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8698 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008699{
8700 struct wpa_ssid *ssid = wpa_s->current_ssid;
8701 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008702 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008703
8704 if (ssid == NULL) {
8705 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8706 "SSID block");
8707 return;
8708 }
8709
8710 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8711 return;
8712
8713 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008714
8715#ifdef CONFIG_P2P
8716 if (ssid->p2p_group &&
8717 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8718 /*
8719 * Skip the wait time since there is a short timeout on the
8720 * connection to a P2P group.
8721 */
8722 return;
8723 }
8724#endif /* CONFIG_P2P */
8725
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008726 if (ssid->auth_failures > 50)
8727 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008728 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008729 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008730 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008731 dur = 90;
8732 else if (ssid->auth_failures > 3)
8733 dur = 60;
8734 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008735 dur = 30;
8736 else if (ssid->auth_failures > 1)
8737 dur = 20;
8738 else
8739 dur = 10;
8740
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008741 if (ssid->auth_failures > 1 &&
8742 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8743 dur += os_random() % (ssid->auth_failures * 10);
8744
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008745 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008746 if (now.sec + dur <= ssid->disabled_until.sec)
8747 return;
8748
8749 ssid->disabled_until.sec = now.sec + dur;
8750
8751 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008752 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008753 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008754 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008755
8756 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8757 int msg_len = snprintf(NULL, 0, format_str,
8758 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8759 ssid->auth_failures, dur, reason) + 1;
8760 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308761 if (!msg)
8762 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008763 snprintf(msg, msg_len, format_str,
8764 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8765 ssid->auth_failures, dur, reason);
8766 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8767 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008768
8769 if (bssid)
8770 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008771}
8772
8773
8774void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8775 struct wpa_ssid *ssid, int clear_failures)
8776{
8777 if (ssid == NULL)
8778 return;
8779
8780 if (ssid->disabled_until.sec) {
8781 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8782 "id=%d ssid=\"%s\"",
8783 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8784 }
8785 ssid->disabled_until.sec = 0;
8786 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008787 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008788 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008789 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8790 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8791 " ignored to allow a lower priority BSS, if any, to be tried next",
8792 MAC2STR(ssid->disabled_due_to));
8793 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8794 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8795 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008796}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008797
8798
8799int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8800{
8801 size_t i;
8802
8803 if (wpa_s->disallow_aps_bssid == NULL)
8804 return 0;
8805
8806 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8807 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8808 bssid, ETH_ALEN) == 0)
8809 return 1;
8810 }
8811
8812 return 0;
8813}
8814
8815
8816int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8817 size_t ssid_len)
8818{
8819 size_t i;
8820
8821 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8822 return 0;
8823
8824 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8825 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8826 if (ssid_len == s->ssid_len &&
8827 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8828 return 1;
8829 }
8830
8831 return 0;
8832}
8833
8834
8835/**
8836 * wpas_request_connection - Request a new connection
8837 * @wpa_s: Pointer to the network interface
8838 *
8839 * This function is used to request a new connection to be found. It will mark
8840 * the interface to allow reassociation and request a new scan to find a
8841 * suitable network to connect to.
8842 */
8843void wpas_request_connection(struct wpa_supplicant *wpa_s)
8844{
8845 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008846 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008847 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008848 wpa_s->disconnected = 0;
8849 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008850 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008851
8852 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8853 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008854 else
8855 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008856}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008857
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008858
Roshan Pius02242d72016-08-09 15:31:48 -07008859/**
8860 * wpas_request_disconnection - Request disconnection
8861 * @wpa_s: Pointer to the network interface
8862 *
8863 * This function is used to request disconnection from the currently connected
8864 * network. This will stop any ongoing scans and initiate deauthentication.
8865 */
8866void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8867{
8868#ifdef CONFIG_SME
8869 wpa_s->sme.prev_bssid_set = 0;
8870#endif /* CONFIG_SME */
8871 wpa_s->reassociate = 0;
8872 wpa_s->disconnected = 1;
8873 wpa_supplicant_cancel_sched_scan(wpa_s);
8874 wpa_supplicant_cancel_scan(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00008875 wpas_abort_ongoing_scan(wpa_s);
Roshan Pius02242d72016-08-09 15:31:48 -07008876 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8877 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008878 radio_remove_works(wpa_s, "connect", 0);
8879 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008880 wpa_s->roam_in_progress = false;
8881#ifdef CONFIG_WNM
8882 wpa_s->bss_trans_mgmt_in_progress = false;
8883#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008884}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008885
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008886
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008887void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8888 struct wpa_used_freq_data *freqs_data,
8889 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008890{
8891 unsigned int i;
8892
8893 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8894 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008895 for (i = 0; i < len; i++) {
8896 struct wpa_used_freq_data *cur = &freqs_data[i];
8897 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8898 i, cur->freq, cur->flags);
8899 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008900}
8901
8902
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008903/*
8904 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008905 * are using the same radio as the current interface, and in addition, get
8906 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008907 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008908int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8909 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008910 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008911{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008912 struct wpa_supplicant *ifs;
8913 u8 bssid[ETH_ALEN];
8914 int freq;
8915 unsigned int idx = 0, i;
8916
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008917 wpa_dbg(wpa_s, MSG_DEBUG,
8918 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008919 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008920
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008921 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8922 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008923 if (idx == len)
8924 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008925
Sunil Ravi77d572f2023-01-17 23:58:31 +00008926 if (exclude_current && ifs == wpa_s)
8927 continue;
8928
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008929 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8930 continue;
8931
8932 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008933 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8934 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008935 freq = ifs->current_ssid->frequency;
8936 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8937 freq = ifs->assoc_freq;
8938 else
8939 continue;
8940
8941 /* Hold only distinct freqs */
8942 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008943 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008944 break;
8945
8946 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008947 freqs_data[idx++].freq = freq;
8948
8949 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008950 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008951 WPA_FREQ_USED_BY_P2P_CLIENT :
8952 WPA_FREQ_USED_BY_INFRA_STATION;
8953 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008954 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008955
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008956 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008957 return idx;
8958}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008959
8960
8961/*
8962 * Find the operating frequencies of any of the virtual interfaces that
8963 * are using the same radio as the current interface.
8964 */
8965int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008966 int *freq_array, unsigned int len,
8967 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008968{
8969 struct wpa_used_freq_data *freqs_data;
8970 int num, i;
8971
8972 os_memset(freq_array, 0, sizeof(int) * len);
8973
8974 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8975 if (!freqs_data)
8976 return -1;
8977
Sunil Ravi77d572f2023-01-17 23:58:31 +00008978 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8979 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008980 for (i = 0; i < num; i++)
8981 freq_array[i] = freqs_data[i].freq;
8982
8983 os_free(freqs_data);
8984
8985 return num;
8986}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008987
8988
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008989struct wpa_supplicant *
8990wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8991{
8992 switch (frame) {
8993#ifdef CONFIG_P2P
8994 case VENDOR_ELEM_PROBE_REQ_P2P:
8995 case VENDOR_ELEM_PROBE_RESP_P2P:
8996 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8997 case VENDOR_ELEM_BEACON_P2P_GO:
8998 case VENDOR_ELEM_P2P_PD_REQ:
8999 case VENDOR_ELEM_P2P_PD_RESP:
9000 case VENDOR_ELEM_P2P_GO_NEG_REQ:
9001 case VENDOR_ELEM_P2P_GO_NEG_RESP:
9002 case VENDOR_ELEM_P2P_GO_NEG_CONF:
9003 case VENDOR_ELEM_P2P_INV_REQ:
9004 case VENDOR_ELEM_P2P_INV_RESP:
9005 case VENDOR_ELEM_P2P_ASSOC_REQ:
9006 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009007 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009008#endif /* CONFIG_P2P */
9009 default:
9010 return wpa_s;
9011 }
9012}
9013
9014
9015void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
9016{
9017 unsigned int i;
9018 char buf[30];
9019
9020 wpa_printf(MSG_DEBUG, "Update vendor elements");
9021
9022 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
9023 if (wpa_s->vendor_elem[i]) {
9024 int res;
9025
9026 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
9027 if (!os_snprintf_error(sizeof(buf), res)) {
9028 wpa_hexdump_buf(MSG_DEBUG, buf,
9029 wpa_s->vendor_elem[i]);
9030 }
9031 }
9032 }
9033
9034#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08009035 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009036 wpa_s->global->p2p &&
9037 !wpa_s->global->p2p_disabled)
9038 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
9039#endif /* CONFIG_P2P */
9040}
9041
9042
9043int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
9044 const u8 *elem, size_t len)
9045{
9046 u8 *ie, *end;
9047
9048 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
9049 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
9050
9051 for (; ie + 1 < end; ie += 2 + ie[1]) {
9052 if (ie + len > end)
9053 break;
9054 if (os_memcmp(ie, elem, len) != 0)
9055 continue;
9056
9057 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
9058 wpabuf_free(wpa_s->vendor_elem[frame]);
9059 wpa_s->vendor_elem[frame] = NULL;
9060 } else {
9061 os_memmove(ie, ie + len, end - (ie + len));
9062 wpa_s->vendor_elem[frame]->used -= len;
9063 }
9064 wpas_vendor_elem_update(wpa_s);
9065 return 0;
9066 }
9067
9068 return -1;
9069}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009070
9071
9072struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07009073 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08009074 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009075{
9076 u16 i;
9077
Hai Shalomc1a21442022-02-04 13:43:00 -08009078 if (!modes)
9079 return NULL;
9080
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009081 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07009082 if (modes[i].mode != mode ||
9083 !modes[i].num_channels || !modes[i].channels)
9084 continue;
9085 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
9086 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009087 return &modes[i];
9088 }
9089
9090 return NULL;
9091}
9092
9093
Hai Shalomc1a21442022-02-04 13:43:00 -08009094struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9095 u16 num_modes, int freq)
9096{
9097 int i, j;
9098
9099 for (i = 0; i < num_modes; i++) {
9100 for (j = 0; j < modes[i].num_channels; j++) {
9101 if (freq == modes[i].channels[j].freq)
9102 return &modes[i];
9103 }
9104 }
9105
9106 return NULL;
9107}
9108
9109
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009110static struct
9111wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9112 const u8 *bssid)
9113{
9114 struct wpa_bss_tmp_disallowed *bss;
9115
9116 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9117 struct wpa_bss_tmp_disallowed, list) {
9118 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
9119 return bss;
9120 }
9121
9122 return NULL;
9123}
9124
9125
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009126static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9127{
9128 struct wpa_bss_tmp_disallowed *tmp;
9129 unsigned int num_bssid = 0;
9130 u8 *bssids;
9131 int ret;
9132
9133 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9134 if (!bssids)
9135 return -1;
9136 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9137 struct wpa_bss_tmp_disallowed, list) {
9138 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9139 ETH_ALEN);
9140 num_bssid++;
9141 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009142 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009143 os_free(bssids);
9144 return ret;
9145}
9146
9147
9148static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9149{
9150 struct wpa_supplicant *wpa_s = eloop_ctx;
9151 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9152
9153 /* Make sure the bss is not already freed */
9154 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9155 struct wpa_bss_tmp_disallowed, list) {
9156 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009157 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009158 wpa_set_driver_tmp_disallow_list(wpa_s);
9159 break;
9160 }
9161 }
9162}
9163
9164
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009165void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009166 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009167{
9168 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009169
9170 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9171 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009172 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009173 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009174 }
9175
9176 bss = os_malloc(sizeof(*bss));
9177 if (!bss) {
9178 wpa_printf(MSG_DEBUG,
9179 "Failed to allocate memory for temp disallow BSS");
9180 return;
9181 }
9182
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009183 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9184 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009185 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009186
9187finish:
9188 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009189 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9190 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009191}
9192
9193
Hai Shalom74f70d42019-02-11 14:42:39 -08009194int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9195 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009196{
Hai Shalom74f70d42019-02-11 14:42:39 -08009197 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009198
9199 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9200 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009201 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9202 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009203 break;
9204 }
9205 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009206 if (!disallowed)
9207 return 0;
9208
9209 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009210 bss->level > disallowed->rssi_threshold) {
9211 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9212 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009213 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009214 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009215
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009216 return 1;
9217}
Hai Shalom81f62d82019-07-22 12:10:00 -07009218
9219
9220int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9221 unsigned int type, const u8 *addr,
9222 const u8 *mask)
9223{
9224 if ((addr && !mask) || (!addr && mask)) {
9225 wpa_printf(MSG_INFO,
9226 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9227 return -1;
9228 }
9229
9230 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9231 wpa_printf(MSG_INFO,
9232 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9233 return -1;
9234 }
9235
9236 if (type & MAC_ADDR_RAND_SCAN) {
9237 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9238 addr, mask))
9239 return -1;
9240 }
9241
9242 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9243 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9244 addr, mask))
9245 return -1;
9246
9247 if (wpa_s->sched_scanning && !wpa_s->pno)
9248 wpas_scan_restart_sched_scan(wpa_s);
9249 }
9250
9251 if (type & MAC_ADDR_RAND_PNO) {
9252 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9253 addr, mask))
9254 return -1;
9255
9256 if (wpa_s->pno) {
9257 wpas_stop_pno(wpa_s);
9258 wpas_start_pno(wpa_s);
9259 }
9260 }
9261
9262 return 0;
9263}
9264
9265
9266int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9267 unsigned int type)
9268{
9269 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9270 if (wpa_s->pno) {
9271 if (type & MAC_ADDR_RAND_PNO) {
9272 wpas_stop_pno(wpa_s);
9273 wpas_start_pno(wpa_s);
9274 }
9275 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9276 wpas_scan_restart_sched_scan(wpa_s);
9277 }
9278
9279 return 0;
9280}
Hai Shalomfdcde762020-04-02 11:19:20 -07009281
9282
9283int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9284 struct wpa_signal_info *si)
9285{
9286 int res;
9287
9288 if (!wpa_s->driver->signal_poll)
9289 return -1;
9290
9291 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9292
9293#ifdef CONFIG_TESTING_OPTIONS
9294 if (res == 0) {
9295 struct driver_signal_override *dso;
9296
9297 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9298 struct driver_signal_override, list) {
9299 if (os_memcmp(wpa_s->bssid, dso->bssid,
9300 ETH_ALEN) != 0)
9301 continue;
9302 wpa_printf(MSG_DEBUG,
9303 "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 +00009304 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009305 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009306 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009307 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009308 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009309 dso->si_avg_beacon_signal,
9310 si->current_noise,
9311 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009312 si->data.signal = dso->si_current_signal;
9313 si->data.avg_signal = dso->si_avg_signal;
9314 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009315 si->current_noise = dso->si_current_noise;
9316 break;
9317 }
9318 }
9319#endif /* CONFIG_TESTING_OPTIONS */
9320
9321 return res;
9322}
9323
9324
9325struct wpa_scan_results *
9326wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9327{
9328 struct wpa_scan_results *scan_res;
9329#ifdef CONFIG_TESTING_OPTIONS
9330 size_t idx;
9331#endif /* CONFIG_TESTING_OPTIONS */
9332
9333 if (!wpa_s->driver->get_scan_results2)
9334 return NULL;
9335
9336 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9337
9338#ifdef CONFIG_TESTING_OPTIONS
9339 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9340 struct driver_signal_override *dso;
9341 struct wpa_scan_res *res = scan_res->res[idx];
9342
9343 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9344 struct driver_signal_override, list) {
9345 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9346 continue;
9347 wpa_printf(MSG_DEBUG,
9348 "Override driver scan signal level %d->%d for "
9349 MACSTR,
9350 res->level, dso->scan_level,
9351 MAC2STR(res->bssid));
9352 res->flags |= WPA_SCAN_QUAL_INVALID;
9353 if (dso->scan_level < 0)
9354 res->flags |= WPA_SCAN_LEVEL_DBM;
9355 else
9356 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9357 res->level = dso->scan_level;
9358 break;
9359 }
9360 }
9361#endif /* CONFIG_TESTING_OPTIONS */
9362
9363 return scan_res;
9364}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009365
9366
9367static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9368{
9369 int i;
9370
9371 if (!wpa_s->valid_links)
9372 return false;
9373
9374 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9375 if (!(wpa_s->valid_links & BIT(i)))
9376 continue;
9377
9378 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9379 return true;
9380 }
9381
9382 return false;
9383}
9384
9385
9386int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9387 unsigned int wait, const u8 *dst, const u8 *src,
9388 const u8 *bssid, const u8 *data, size_t data_len,
9389 int no_cck)
9390{
9391 if (!wpa_s->driver->send_action)
9392 return -1;
9393
9394 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9395 if (wpas_ap_link_address(wpa_s, dst))
9396 dst = wpa_s->ap_mld_addr;
9397
9398 if (wpas_ap_link_address(wpa_s, bssid))
9399 bssid = wpa_s->ap_mld_addr;
9400 }
9401
9402 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9403 bssid, data, data_len, no_cck);
9404}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00009405
9406
9407bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
9408{
9409 struct hostapd_channel_data *chnl;
9410 int i, j;
9411
9412 for (i = 0; i < wpa_s->hw.num_modes; i++) {
9413 if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
9414 chnl = wpa_s->hw.modes[i].channels;
9415 for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
9416 if (only_enabled &&
9417 (chnl[j].flag & HOSTAPD_CHAN_DISABLED))
9418 continue;
9419 if (is_6ghz_freq(chnl[j].freq))
9420 return true;
9421 }
9422 }
9423 }
9424
9425 return false;
9426}