blob: d84f3089d438ee0a2e46b5c5042b6d21548dece0 [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);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754}
755
756
757/**
758 * wpa_clear_keys - Clear keys configured for the driver
759 * @wpa_s: Pointer to wpa_supplicant data
760 * @addr: Previously used BSSID or %NULL if not available
761 *
762 * This function clears the encryption keys that has been previously configured
763 * for the driver.
764 */
765void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
766{
Hai Shalomc3565922019-10-28 11:58:20 -0700767 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768
769 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800770 for (i = 0; i < max; i++) {
771 if (wpa_s->keys_cleared & BIT(i))
772 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000773 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700774 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800775 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700776 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
777 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800778 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700779 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000780 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
781 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700782 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000783 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
784 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 /* MLME-SETPROTECTION.request(None) */
786 wpa_drv_mlme_setprotection(
787 wpa_s, addr,
788 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
789 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
790 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800791 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792}
793
794
795/**
796 * wpa_supplicant_state_txt - Get the connection state name as a text string
797 * @state: State (wpa_state; WPA_*)
798 * Returns: The state name as a printable text string
799 */
800const char * wpa_supplicant_state_txt(enum wpa_states state)
801{
802 switch (state) {
803 case WPA_DISCONNECTED:
804 return "DISCONNECTED";
805 case WPA_INACTIVE:
806 return "INACTIVE";
807 case WPA_INTERFACE_DISABLED:
808 return "INTERFACE_DISABLED";
809 case WPA_SCANNING:
810 return "SCANNING";
811 case WPA_AUTHENTICATING:
812 return "AUTHENTICATING";
813 case WPA_ASSOCIATING:
814 return "ASSOCIATING";
815 case WPA_ASSOCIATED:
816 return "ASSOCIATED";
817 case WPA_4WAY_HANDSHAKE:
818 return "4WAY_HANDSHAKE";
819 case WPA_GROUP_HANDSHAKE:
820 return "GROUP_HANDSHAKE";
821 case WPA_COMPLETED:
822 return "COMPLETED";
823 default:
824 return "UNKNOWN";
825 }
826}
827
828
829#ifdef CONFIG_BGSCAN
830
Hai Shalom899fcc72020-10-19 14:38:18 -0700831static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
832{
833 if (wpa_s->bgscan_ssid) {
834 bgscan_deinit(wpa_s);
835 wpa_s->bgscan_ssid = NULL;
836 }
837}
838
839
840/**
841 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
842 * @wpa_s: Pointer to the wpa_supplicant data
843 *
844 * Stop, start, or reconfigure the scan parameters depending on the method.
845 */
846void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800848 const char *name;
849
850 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
851 name = wpa_s->current_ssid->bgscan;
852 else
853 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700854 if (!name || name[0] == '\0') {
855 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800856 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700857 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800858 if (wpas_driver_bss_selection(wpa_s))
859 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800860#ifdef CONFIG_P2P
861 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
862 return;
863#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864
865 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800866 if (wpa_s->current_ssid) {
867 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700868 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
869 "bgscan");
870 /*
871 * Live without bgscan; it is only used as a roaming
872 * optimization, so the initial connection is not
873 * affected.
874 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700875 } else {
876 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700877 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700878 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
879 0);
880 if (scan_res) {
881 bgscan_notify_scan(wpa_s, scan_res);
882 wpa_scan_results_free(scan_res);
883 }
884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 } else
886 wpa_s->bgscan_ssid = NULL;
887}
888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889#endif /* CONFIG_BGSCAN */
890
891
Dmitry Shmidt04949592012-07-19 12:16:46 -0700892static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
893{
894 if (autoscan_init(wpa_s, 0))
895 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
896}
897
898
899static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
900{
901 autoscan_deinit(wpa_s);
902}
903
904
905void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
906{
907 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
908 wpa_s->wpa_state == WPA_SCANNING) {
909 autoscan_deinit(wpa_s);
910 wpa_supplicant_start_autoscan(wpa_s);
911 }
912}
913
914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915/**
916 * wpa_supplicant_set_state - Set current connection state
917 * @wpa_s: Pointer to wpa_supplicant data
918 * @state: The new connection state
919 *
920 * This function is called whenever the connection state changes, e.g.,
921 * association is completed for WPA/WPA2 4-Way Handshake is started.
922 */
923void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
924 enum wpa_states state)
925{
926 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700927#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700928 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700929#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930
931 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
932 wpa_supplicant_state_txt(wpa_s->wpa_state),
933 wpa_supplicant_state_txt(state));
934
Hai Shalom74f70d42019-02-11 14:42:39 -0800935 if (state == WPA_COMPLETED &&
936 os_reltime_initialized(&wpa_s->roam_start)) {
937 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
938 wpa_s->roam_start.sec = 0;
939 wpa_s->roam_start.usec = 0;
940 wpas_notify_auth_changed(wpa_s);
941 wpas_notify_roam_time(wpa_s);
942 wpas_notify_roam_complete(wpa_s);
943 } else if (state == WPA_DISCONNECTED &&
944 os_reltime_initialized(&wpa_s->roam_start)) {
945 wpa_s->roam_start.sec = 0;
946 wpa_s->roam_start.usec = 0;
947 wpa_s->roam_time.sec = 0;
948 wpa_s->roam_time.usec = 0;
949 wpas_notify_roam_complete(wpa_s);
950 }
951
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800952 if (state == WPA_INTERFACE_DISABLED) {
953 /* Assure normal scan when interface is restored */
954 wpa_s->normal_scans = 0;
955 }
956
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700957 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800958 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700959 /* Reinitialize normal_scan counter */
960 wpa_s->normal_scans = 0;
961 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800962
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700963#ifdef CONFIG_P2P
964 /*
965 * P2PS client has to reply to Probe Request frames received on the
966 * group operating channel. Enable Probe Request frame reporting for
967 * P2P connected client in case p2p_cli_probe configuration property is
968 * set to 1.
969 */
970 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
971 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
972 wpa_s->current_ssid->p2p_group) {
973 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
974 wpa_dbg(wpa_s, MSG_DEBUG,
975 "P2P: Enable CLI Probe Request RX reporting");
976 wpa_s->p2p_cli_probe =
977 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
978 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
979 wpa_dbg(wpa_s, MSG_DEBUG,
980 "P2P: Disable CLI Probe Request RX reporting");
981 wpa_s->p2p_cli_probe = 0;
982 wpa_drv_probe_req_report(wpa_s, 0);
983 }
984 }
985#endif /* CONFIG_P2P */
986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 if (state != WPA_SCANNING)
988 wpa_supplicant_notify_scanning(wpa_s, 0);
989
990 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700992 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -0700993 char mld_addr[50];
994
995 mld_addr[0] = '\0';
996 if (wpa_s->valid_links)
997 os_snprintf(mld_addr, sizeof(mld_addr),
998 " ap_mld_addr=" MACSTR,
999 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001000
1001#ifdef CONFIG_SME
1002 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1003 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1004 fils_hlp_sent = 1;
1005#endif /* CONFIG_SME */
1006 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1007 wpa_auth_alg_fils(wpa_s->auth_alg))
1008 fils_hlp_sent = 1;
1009
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001010#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001012 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001013 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001015 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001016 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001018 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001019 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001020 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001021 wpa_drv_set_operstate(wpa_s, 1);
1022#ifndef IEEE8021X_EAPOL
1023 wpa_drv_set_supp_port(wpa_s, 1);
1024#endif /* IEEE8021X_EAPOL */
1025 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001026 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001028
1029 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001030
1031#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1032 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001033 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001034#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001035#ifdef CONFIG_OWE
1036 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1037 wpas_update_owe_connect_params(wpa_s);
1038#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001039#ifdef CONFIG_HS20
1040 hs20_configure_frame_filters(wpa_s);
1041#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1043 state == WPA_ASSOCIATED) {
1044 wpa_s->new_connection = 1;
1045 wpa_drv_set_operstate(wpa_s, 0);
1046#ifndef IEEE8021X_EAPOL
1047 wpa_drv_set_supp_port(wpa_s, 0);
1048#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050 }
1051 wpa_s->wpa_state = state;
1052
1053#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001054 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1055 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001056 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 wpa_supplicant_stop_bgscan(wpa_s);
1058#endif /* CONFIG_BGSCAN */
1059
Hai Shalom5f92bc92019-04-18 11:54:11 -07001060 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001061 wpa_supplicant_stop_autoscan(wpa_s);
1062
1063 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1064 wpa_supplicant_start_autoscan(wpa_s);
1065
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001066 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1067 wmm_ac_notify_disassoc(wpa_s);
1068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 if (wpa_s->wpa_state != old_state) {
1070 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1071
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001072 /*
1073 * Notify the P2P Device interface about a state change in one
1074 * of the interfaces.
1075 */
1076 wpas_p2p_indicate_state_change(wpa_s);
1077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078 if (wpa_s->wpa_state == WPA_COMPLETED ||
1079 old_state == WPA_COMPLETED)
1080 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001081#ifdef CONFIG_DPP2
1082 if (wpa_s->wpa_state == WPA_COMPLETED)
1083 wpas_dpp_connected(wpa_s);
1084#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085 }
Hai Shalomc3565922019-10-28 11:58:20 -07001086#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1087 if (update_fils_connect_params)
1088 wpas_update_fils_connect_params(wpa_s);
1089#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090}
1091
1092
1093void wpa_supplicant_terminate_proc(struct wpa_global *global)
1094{
1095 int pending = 0;
1096#ifdef CONFIG_WPS
1097 struct wpa_supplicant *wpa_s = global->ifaces;
1098 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001099 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001100 if (wpas_wps_terminate_pending(wpa_s) == 1)
1101 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001102#ifdef CONFIG_P2P
1103 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1104 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1105 wpas_p2p_disconnect(wpa_s);
1106#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001107 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 }
1109#endif /* CONFIG_WPS */
1110 if (pending)
1111 return;
1112 eloop_terminate();
1113}
1114
1115
1116static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1117{
1118 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 wpa_supplicant_terminate_proc(global);
1120}
1121
1122
1123void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1124{
1125 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001126 enum wpa_states new_state;
1127
1128 if (old_state == WPA_SCANNING)
1129 new_state = WPA_SCANNING;
1130 else
1131 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132
1133 wpa_s->pairwise_cipher = 0;
1134 wpa_s->group_cipher = 0;
1135 wpa_s->mgmt_group_cipher = 0;
1136 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001137 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001139 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001140
1141 if (wpa_s->wpa_state != old_state)
1142 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1143}
1144
1145
1146/**
1147 * wpa_supplicant_reload_configuration - Reload configuration data
1148 * @wpa_s: Pointer to wpa_supplicant data
1149 * Returns: 0 on success or -1 if configuration parsing failed
1150 *
1151 * This function can be used to request that the configuration data is reloaded
1152 * (e.g., after configuration file change). This function is reloading
1153 * configuration only for one interface, so this may need to be called multiple
1154 * times if %wpa_supplicant is controlling multiple interfaces and all
1155 * interfaces need reconfiguration.
1156 */
1157int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1158{
1159 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 int reconf_ctrl;
1161 int old_ap_scan;
1162
1163 if (wpa_s->confname == NULL)
1164 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001165 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 if (conf == NULL) {
1167 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1168 "file '%s' - exiting", wpa_s->confname);
1169 return -1;
1170 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001171 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001172 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001173 wpa_msg(wpa_s, MSG_ERROR,
1174 "Failed to parse the configuration file '%s' - exiting",
1175 wpa_s->confanother);
1176 return -1;
1177 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001179 conf->changed_parameters = (unsigned int) -1;
1180
1181 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1182 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1183 os_strcmp(conf->ctrl_interface,
1184 wpa_s->conf->ctrl_interface) != 0);
1185
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001186 if (reconf_ctrl) {
1187 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 wpa_s->ctrl_iface = NULL;
1189 }
1190
1191 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001192 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001193 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1194 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001195 wpa_supplicant_deauthenticate(wpa_s,
1196 WLAN_REASON_DEAUTH_LEAVING);
1197 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198
1199 /*
1200 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001201 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001203 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1204 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1205 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 /*
1207 * Clear forced success to clear EAP state for next
1208 * authentication.
1209 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001210 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 }
1212 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1213 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001214 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001215 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1216 rsn_preauth_deinit(wpa_s->wpa);
1217
1218 old_ap_scan = wpa_s->conf->ap_scan;
1219 wpa_config_free(wpa_s->conf);
1220 wpa_s->conf = conf;
1221 if (old_ap_scan != wpa_s->conf->ap_scan)
1222 wpas_notify_ap_scan_changed(wpa_s);
1223
1224 if (reconf_ctrl)
1225 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1226
1227 wpa_supplicant_update_config(wpa_s);
1228
1229 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001230 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231 wpa_s->reassociate = 1;
1232 wpa_supplicant_req_scan(wpa_s, 0, 0);
1233 }
Hai Shalom60840252021-02-19 19:02:11 -08001234 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1236 return 0;
1237}
1238
1239
1240static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1241{
1242 struct wpa_global *global = signal_ctx;
1243 struct wpa_supplicant *wpa_s;
1244 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1245 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1246 sig);
1247 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1248 wpa_supplicant_terminate_proc(global);
1249 }
1250 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001251
1252 if (wpa_debug_reopen_file() < 0) {
1253 /* Ignore errors since we cannot really do much to fix this */
1254 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1255 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256}
1257
1258
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001259static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1260 struct wpa_ssid *ssid,
1261 struct wpa_ie_data *ie)
1262{
1263 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1264 if (ret) {
1265 if (ret == -2) {
1266 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1267 "from association info");
1268 }
1269 return -1;
1270 }
1271
1272 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1273 "cipher suites");
1274 if (!(ie->group_cipher & ssid->group_cipher)) {
1275 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1276 "cipher 0x%x (mask 0x%x) - reject",
1277 ie->group_cipher, ssid->group_cipher);
1278 return -1;
1279 }
1280 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1281 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1282 "cipher 0x%x (mask 0x%x) - reject",
1283 ie->pairwise_cipher, ssid->pairwise_cipher);
1284 return -1;
1285 }
1286 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1287 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1288 "management 0x%x (mask 0x%x) - reject",
1289 ie->key_mgmt, ssid->key_mgmt);
1290 return -1;
1291 }
1292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001294 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1296 "that does not support management frame protection - "
1297 "reject");
1298 return -1;
1299 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300
1301 return 0;
1302}
1303
1304
Hai Shalom021b0b52019-04-10 11:17:58 -07001305static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1306 int freq)
1307{
1308 if (!ie->has_group)
1309 ie->group_cipher = wpa_default_rsn_cipher(freq);
1310 if (!ie->has_pairwise)
1311 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1312 return (ie->group_cipher & ssid->group_cipher) &&
1313 (ie->pairwise_cipher & ssid->pairwise_cipher);
1314}
1315
1316
Hai Shalomc1a21442022-02-04 13:43:00 -08001317void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1318 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1319{
1320 int sel;
1321
1322 sel = ie->mgmt_group_cipher;
1323 if (ssid->group_mgmt_cipher)
1324 sel &= ssid->group_mgmt_cipher;
1325 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1326 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1327 sel = 0;
1328 wpa_dbg(wpa_s, MSG_DEBUG,
1329 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1330 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1331 if (sel & WPA_CIPHER_AES_128_CMAC) {
1332 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: using MGMT group cipher AES-128-CMAC");
1335 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1336 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1337 wpa_dbg(wpa_s, MSG_DEBUG,
1338 "WPA: using MGMT group cipher BIP-GMAC-128");
1339 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1340 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1341 wpa_dbg(wpa_s, MSG_DEBUG,
1342 "WPA: using MGMT group cipher BIP-GMAC-256");
1343 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1344 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1345 wpa_dbg(wpa_s, MSG_DEBUG,
1346 "WPA: using MGMT group cipher BIP-CMAC-256");
1347 } else {
1348 wpa_s->mgmt_group_cipher = 0;
1349 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1350 }
1351 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1352 wpa_s->mgmt_group_cipher);
1353 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1354 wpas_get_ssid_pmf(wpa_s, ssid));
1355}
1356
Sunil Ravi77d572f2023-01-17 23:58:31 +00001357/**
1358 * wpa_supplicant_get_psk - Get PSK from config or external database
1359 * @wpa_s: Pointer to wpa_supplicant data
1360 * @bss: Scan results for the selected BSS, or %NULL if not available
1361 * @ssid: Configuration data for the selected network
1362 * @psk: Buffer for the PSK
1363 * Returns: 0 on success or -1 if configuration parsing failed
1364 *
1365 * This function obtains the PSK for a network, either included inline in the
1366 * config or retrieved from an external database.
1367 */
1368static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1369 struct wpa_bss *bss, struct wpa_ssid *ssid,
1370 u8 *psk)
1371{
1372 if (ssid->psk_set) {
1373 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1374 ssid->psk, PMK_LEN);
1375 os_memcpy(psk, ssid->psk, PMK_LEN);
1376 return 0;
1377 }
1378
1379#ifndef CONFIG_NO_PBKDF2
1380 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1381 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1382 4096, psk, PMK_LEN) != 0) {
1383 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1384 return -1;
1385 }
1386 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1387 psk, PMK_LEN);
1388 return 0;
1389 }
1390#endif /* CONFIG_NO_PBKDF2 */
1391
1392#ifdef CONFIG_EXT_PASSWORD
1393 if (ssid->ext_psk) {
1394 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1395 ssid->ext_psk);
1396 char pw_str[64 + 1];
1397
1398 if (!pw) {
1399 wpa_msg(wpa_s, MSG_INFO,
1400 "EXT PW: No PSK found from external storage");
1401 return -1;
1402 }
1403
1404 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1405 wpa_msg(wpa_s, MSG_INFO,
1406 "EXT PW: Unexpected PSK length %d in external storage",
1407 (int) wpabuf_len(pw));
1408 ext_password_free(pw);
1409 return -1;
1410 }
1411
1412 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1413 pw_str[wpabuf_len(pw)] = '\0';
1414
1415#ifndef CONFIG_NO_PBKDF2
1416 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1417 {
1418 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1419 4096, psk, PMK_LEN) != 0) {
1420 wpa_msg(wpa_s, MSG_WARNING,
1421 "Error in pbkdf2_sha1()");
1422 forced_memzero(pw_str, sizeof(pw_str));
1423 ext_password_free(pw);
1424 return -1;
1425 }
1426 wpa_hexdump_key(MSG_MSGDUMP,
1427 "PSK (from external passphrase)",
1428 psk, PMK_LEN);
1429 } else
1430#endif /* CONFIG_NO_PBKDF2 */
1431 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1432 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1433 wpa_msg(wpa_s, MSG_INFO,
1434 "EXT PW: Invalid PSK hex string");
1435 forced_memzero(pw_str, sizeof(pw_str));
1436 ext_password_free(pw);
1437 return -1;
1438 }
1439 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1440 psk, PMK_LEN);
1441 } else {
1442 wpa_msg(wpa_s, MSG_INFO,
1443 "EXT PW: No suitable PSK available");
1444 forced_memzero(pw_str, sizeof(pw_str));
1445 ext_password_free(pw);
1446 return -1;
1447 }
1448
1449 forced_memzero(pw_str, sizeof(pw_str));
1450 ext_password_free(pw);
1451
1452 return 0;
1453 }
1454#endif /* CONFIG_EXT_PASSWORD */
1455
1456 return -1;
1457}
1458
Hai Shalomc1a21442022-02-04 13:43:00 -08001459
Sunil Ravi89eba102022-09-13 21:04:37 -07001460static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1461 struct wpa_ssid *ssid)
1462{
1463 int akm_count = wpa_s->max_num_akms;
1464 u8 capab = 0;
1465
1466 if (akm_count < 2)
1467 return;
1468
1469 akm_count--;
1470 wpa_s->allowed_key_mgmts = 0;
1471 switch (wpa_s->key_mgmt) {
1472 case WPA_KEY_MGMT_PSK:
1473 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1474 akm_count--;
1475 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1476 }
1477 if (!akm_count)
1478 break;
1479 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1480 akm_count--;
1481 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1482 }
1483 if (!akm_count)
1484 break;
1485 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1486 wpa_s->allowed_key_mgmts |=
1487 WPA_KEY_MGMT_PSK_SHA256;
1488 break;
1489 case WPA_KEY_MGMT_PSK_SHA256:
1490 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1491 akm_count--;
1492 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1493 }
1494 if (!akm_count)
1495 break;
1496 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1497 akm_count--;
1498 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1499 }
1500 if (!akm_count)
1501 break;
1502 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1503 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1504 break;
1505 case WPA_KEY_MGMT_SAE:
1506 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1507 akm_count--;
1508 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1509 }
1510 if (!akm_count)
1511 break;
1512 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1513 akm_count--;
1514 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1515 }
1516 if (!akm_count)
1517 break;
1518 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1519 wpa_s->allowed_key_mgmts |=
1520 WPA_KEY_MGMT_PSK_SHA256;
1521 break;
1522 case WPA_KEY_MGMT_SAE_EXT_KEY:
1523 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1524 akm_count--;
1525 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1526 }
1527 if (!akm_count)
1528 break;
1529 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1530 akm_count--;
1531 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1532 }
1533 if (!akm_count)
1534 break;
1535 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1536 wpa_s->allowed_key_mgmts |=
1537 WPA_KEY_MGMT_PSK_SHA256;
1538 break;
1539 default:
1540 return;
1541 }
1542
Sunil Ravi77d572f2023-01-17 23:58:31 +00001543 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1544 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001545 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1546#ifdef CONFIG_SAE_PK
1547 if (ssid->sae_pk)
1548 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1549#endif /* CONFIG_SAE_PK */
1550
1551 if (!((wpa_s->allowed_key_mgmts &
1552 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1553 return;
1554
1555 if (!wpa_s->rsnxe_len) {
1556 wpa_s->rsnxe_len = 3;
1557 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1558 wpa_s->rsnxe[1] = 1;
1559 wpa_s->rsnxe[2] = 0;
1560 }
1561
1562 wpa_s->rsnxe[2] |= capab;
1563}
1564
1565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566/**
1567 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1568 * @wpa_s: Pointer to wpa_supplicant data
1569 * @bss: Scan results for the selected BSS, or %NULL if not available
1570 * @ssid: Configuration data for the selected network
1571 * @wpa_ie: Buffer for the WPA/RSN IE
1572 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1573 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001574 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 * Returns: 0 on success or -1 on failure
1576 *
1577 * This function is used to configure authentication and encryption parameters
1578 * based on the network configuration and scan result for the selected BSS (if
1579 * available).
1580 */
1581int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1582 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001583 u8 *wpa_ie, size_t *wpa_ie_len,
1584 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585{
1586 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001587 int sel, proto;
1588 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001589 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590
1591 if (bss) {
1592 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1593 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001594 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001595 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001596 } else {
1597 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1598 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001599
1600 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1601 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001602 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603 (ie.key_mgmt & ssid->key_mgmt)) {
1604 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1605 proto = WPA_PROTO_RSN;
1606 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001607 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001608 (ie.group_cipher & ssid->group_cipher) &&
1609 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1610 (ie.key_mgmt & ssid->key_mgmt)) {
1611 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1612 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001613#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001614 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1615 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1616 (ie.group_cipher & ssid->group_cipher) &&
1617 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1618 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001619 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001620 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001621 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1622 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1623 (ie.group_cipher & ssid->group_cipher) &&
1624 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1625 (ie.key_mgmt & ssid->key_mgmt)) {
1626 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1627 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001628#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 } else if (bss) {
1630 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001631 wpa_dbg(wpa_s, MSG_DEBUG,
1632 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1633 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1634 ssid->key_mgmt);
1635 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1636 MAC2STR(bss->bssid),
1637 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1638 bss_wpa ? " WPA" : "",
1639 bss_rsn ? " RSN" : "",
1640 bss_osen ? " OSEN" : "");
1641 if (bss_rsn) {
1642 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1643 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1644 wpa_dbg(wpa_s, MSG_DEBUG,
1645 "Could not parse RSN element");
1646 } else {
1647 wpa_dbg(wpa_s, MSG_DEBUG,
1648 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1649 ie.pairwise_cipher, ie.group_cipher,
1650 ie.key_mgmt);
1651 }
1652 }
1653 if (bss_wpa) {
1654 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1655 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1656 wpa_dbg(wpa_s, MSG_DEBUG,
1657 "Could not parse WPA element");
1658 } else {
1659 wpa_dbg(wpa_s, MSG_DEBUG,
1660 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1661 ie.pairwise_cipher, ie.group_cipher,
1662 ie.key_mgmt);
1663 }
1664 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 return -1;
1666 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001667 if (ssid->proto & WPA_PROTO_OSEN)
1668 proto = WPA_PROTO_OSEN;
1669 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 proto = WPA_PROTO_RSN;
1671 else
1672 proto = WPA_PROTO_WPA;
1673 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1674 os_memset(&ie, 0, sizeof(ie));
1675 ie.group_cipher = ssid->group_cipher;
1676 ie.pairwise_cipher = ssid->pairwise_cipher;
1677 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001678 ie.mgmt_group_cipher = 0;
1679 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1680 if (ssid->group_mgmt_cipher &
1681 WPA_CIPHER_BIP_GMAC_256)
1682 ie.mgmt_group_cipher =
1683 WPA_CIPHER_BIP_GMAC_256;
1684 else if (ssid->group_mgmt_cipher &
1685 WPA_CIPHER_BIP_CMAC_256)
1686 ie.mgmt_group_cipher =
1687 WPA_CIPHER_BIP_CMAC_256;
1688 else if (ssid->group_mgmt_cipher &
1689 WPA_CIPHER_BIP_GMAC_128)
1690 ie.mgmt_group_cipher =
1691 WPA_CIPHER_BIP_GMAC_128;
1692 else
1693 ie.mgmt_group_cipher =
1694 WPA_CIPHER_AES_128_CMAC;
1695 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001696#ifdef CONFIG_OWE
1697 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1698 !ssid->owe_only &&
1699 !bss_wpa && !bss_rsn && !bss_osen) {
1700 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1701 wpa_s->wpa_proto = 0;
1702 *wpa_ie_len = 0;
1703 return 0;
1704 }
1705#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1707 "based on configuration");
1708 } else
1709 proto = ie.proto;
1710 }
1711
1712 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1713 "pairwise %d key_mgmt %d proto %d",
1714 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001715 if (ssid->ieee80211w) {
1716 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1717 ie.mgmt_group_cipher);
1718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001720 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1722 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001723 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001724
1725 if (bss || !wpa_s->ap_ies_from_associnfo) {
1726 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1727 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1728 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001729 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1730 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1731 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 return -1;
1733 }
1734
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001735#ifdef CONFIG_NO_WPA
1736 wpa_s->group_cipher = WPA_CIPHER_NONE;
1737 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1738#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001740 wpa_dbg(wpa_s, MSG_DEBUG,
1741 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1742 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001743 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1744 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1746 "cipher");
1747 return -1;
1748 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001749 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1750 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751
1752 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001753 wpa_dbg(wpa_s, MSG_DEBUG,
1754 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1755 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001756 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1757 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1759 "cipher");
1760 return -1;
1761 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001762 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1763 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001764#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765
1766 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001767#ifdef CONFIG_SAE
Sunil Ravi77d572f2023-01-17 23:58:31 +00001768 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) ||
1769 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001770 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1771 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001772#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001773#ifdef CONFIG_IEEE80211R
1774 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1775 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1776 sel &= ~WPA_KEY_MGMT_FT;
1777#endif /* CONFIG_IEEE80211R */
1778 wpa_dbg(wpa_s, MSG_DEBUG,
1779 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1780 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001782#ifdef CONFIG_IEEE80211R
1783#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001784 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1785 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001786 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1787 wpa_dbg(wpa_s, MSG_DEBUG,
1788 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001789 if (!ssid->ft_eap_pmksa_caching &&
1790 pmksa_cache_get_current(wpa_s->wpa)) {
1791 /* PMKSA caching with FT may have interoperability
1792 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001793 wpa_dbg(wpa_s, MSG_DEBUG,
1794 "WPA: Disable PMKSA caching for FT/802.1X connection");
1795 pmksa_cache_clear_current(wpa_s->wpa);
1796 }
1797#endif /* CONFIG_SHA384 */
1798#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001799#ifdef CONFIG_SUITEB192
1800 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1801 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1802 wpa_dbg(wpa_s, MSG_DEBUG,
1803 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1804#endif /* CONFIG_SUITEB192 */
1805#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001806 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1807 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1808 wpa_dbg(wpa_s, MSG_DEBUG,
1809 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001810#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001811#ifdef CONFIG_FILS
1812#ifdef CONFIG_IEEE80211R
1813 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1814 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1815 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001816#endif /* CONFIG_IEEE80211R */
1817 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1818 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1819 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001820#ifdef CONFIG_IEEE80211R
1821 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1822 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1823 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1824#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001825 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1826 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1827 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1828#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001829#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001830 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1831 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1833 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001834 if (!ssid->ft_eap_pmksa_caching &&
1835 pmksa_cache_get_current(wpa_s->wpa)) {
1836 /* PMKSA caching with FT may have interoperability
1837 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001838 wpa_dbg(wpa_s, MSG_DEBUG,
1839 "WPA: Disable PMKSA caching for FT/802.1X connection");
1840 pmksa_cache_clear_current(wpa_s->wpa);
1841 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001842#endif /* CONFIG_IEEE80211R */
1843#ifdef CONFIG_DPP
1844 } else if (sel & WPA_KEY_MGMT_DPP) {
1845 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1846 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1847#endif /* CONFIG_DPP */
1848#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001849 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1850 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1851 wpa_dbg(wpa_s, MSG_DEBUG,
1852 "RSN: using KEY_MGMT FT/SAE (ext key)");
1853 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1854 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1855 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001856 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1857 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1858 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1859 } else if (sel & WPA_KEY_MGMT_SAE) {
1860 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1861 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1862#endif /* CONFIG_SAE */
1863#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1865 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1866 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1867#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1869 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1870 wpa_dbg(wpa_s, MSG_DEBUG,
1871 "WPA: using KEY_MGMT 802.1X with SHA256");
1872 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1873 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1874 wpa_dbg(wpa_s, MSG_DEBUG,
1875 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1877 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1878 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1879 } else if (sel & WPA_KEY_MGMT_PSK) {
1880 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1881 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1882 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1883 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1884 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001885#ifdef CONFIG_HS20
1886 } else if (sel & WPA_KEY_MGMT_OSEN) {
1887 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1888 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1889#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001890#ifdef CONFIG_OWE
1891 } else if (sel & WPA_KEY_MGMT_OWE) {
1892 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1893 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1894#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001895 } else {
1896 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1897 "authenticated key management type");
1898 return -1;
1899 }
1900
1901 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1902 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1903 wpa_s->pairwise_cipher);
1904 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1905
Hai Shalomc3565922019-10-28 11:58:20 -07001906 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001907 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1908 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001909 wpa_msg(wpa_s, MSG_INFO,
1910 "RSN: Management frame protection required but the selected AP does not enable it");
1911 return -1;
1912 }
1913
Hai Shalomc1a21442022-02-04 13:43:00 -08001914 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001915#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001916 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1917 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1918 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001919#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001920 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001921 if ((ssid->sae_password_id ||
1922 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001923 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1924 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1925 if (bss && is_6ghz_freq(bss->freq) &&
1926 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1927 wpa_dbg(wpa_s, MSG_DEBUG,
1928 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1929 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001930 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001931 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001932#ifdef CONFIG_SAE_PK
1933 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1934 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1935 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1936 ((ssid->sae_password &&
1937 sae_pk_valid_password(ssid->sae_password)) ||
1938 (!ssid->sae_password && ssid->passphrase &&
1939 sae_pk_valid_password(ssid->passphrase))));
1940#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001941 if (bss && is_6ghz_freq(bss->freq) &&
1942 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1943 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1944 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1945 MGMT_FRAME_PROTECTION_REQUIRED);
1946 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001947#ifdef CONFIG_TESTING_OPTIONS
1948 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1949 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001950 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1951 wpa_s->oci_freq_override_eapol);
1952 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1953 wpa_s->oci_freq_override_eapol_g2);
1954 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1955 wpa_s->oci_freq_override_ft_assoc);
1956 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1957 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001958 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1959 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001960#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001961
1962 /* Extended Key ID is only supported in infrastructure BSS so far */
1963 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1964 (ssid->proto & WPA_PROTO_RSN) &&
1965 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1966 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1967 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1968 int use_ext_key_id = 0;
1969
1970 wpa_msg(wpa_s, MSG_DEBUG,
1971 "WPA: Enable Extended Key ID support");
1972 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1973 wpa_s->conf->extended_key_id);
1974 if (bss_rsn &&
1975 wpa_s->conf->extended_key_id &&
1976 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1977 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1978 use_ext_key_id = 1;
1979 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1980 use_ext_key_id);
1981 } else {
1982 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1983 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1984 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985
Sunil Ravi77d572f2023-01-17 23:58:31 +00001986 if (!skip_default_rsne) {
1987 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
1988 wpa_ie_len)) {
1989 wpa_msg(wpa_s, MSG_WARNING,
1990 "RSN: Failed to generate RSNE/WPA IE");
1991 return -1;
1992 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993
Sunil Ravi77d572f2023-01-17 23:58:31 +00001994 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1995 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1996 &wpa_s->rsnxe_len)) {
1997 wpa_msg(wpa_s, MSG_WARNING,
1998 "RSN: Failed to generate RSNXE");
1999 return -1;
2000 }
Hai Shalomc3565922019-10-28 11:58:20 -07002001 }
2002
Hai Shalom021b0b52019-04-10 11:17:58 -07002003 if (0) {
2004#ifdef CONFIG_DPP
2005 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2006 /* Use PMK from DPP network introduction (PMKSA entry) */
2007 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002008#ifdef CONFIG_DPP2
2009 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2010#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002011#endif /* CONFIG_DPP */
2012 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002013 int psk_set = 0;
2014
Sunil Ravi77d572f2023-01-17 23:58:31 +00002015 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2016 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002017
Sunil Ravi77d572f2023-01-17 23:58:31 +00002018 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2019 psk) == 0) {
2020 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2021 NULL);
2022 psk_set = 1;
2023 }
2024 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002025 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002026
Roshan Pius3a1667e2018-07-03 15:17:14 -07002027 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002028 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002029 psk_set = 1;
2030
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002031 if (!psk_set) {
2032 wpa_msg(wpa_s, MSG_INFO,
2033 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002034 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002035 return -1;
2036 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002037#ifdef CONFIG_OWE
2038 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2039 /* OWE Diffie-Hellman exchange in (Re)Association
2040 * Request/Response frames set the PMK, so do not override it
2041 * here. */
2042#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002043 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2045
Hai Shalomfdcde762020-04-02 11:19:20 -07002046 if (ssid->mode != WPAS_MODE_IBSS &&
2047 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2048 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2049 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2050 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2051 wpa_msg(wpa_s, MSG_INFO,
2052 "Disable PTK0 rekey support - replaced with reconnect");
2053 wpa_s->deny_ptk0_rekey = 1;
2054 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2055 } else {
2056 wpa_s->deny_ptk0_rekey = 0;
2057 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2058 }
2059
Winnie Chen4138eec2022-11-10 16:32:53 +08002060#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302061 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002062 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2063 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002064 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2065 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302066 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2067 wpa_dbg(wpa_s, MSG_INFO,
2068 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2069 }
Sunil Ravif42be322022-11-04 03:31:21 +00002070#else
2071 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2072 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2073 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002074#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 return 0;
2077}
2078
2079
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002080static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
2081{
Hai Shalomc1a21442022-02-04 13:43:00 -08002082 bool scs = true, mscs = true;
2083
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002084 *pos = 0x00;
2085
2086 switch (idx) {
2087 case 0: /* Bits 0-7 */
2088 break;
2089 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002090 if (wpa_s->conf->coloc_intf_reporting) {
2091 /* Bit 13 - Collocated Interference Reporting */
2092 *pos |= 0x20;
2093 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002094 break;
2095 case 2: /* Bits 16-23 */
2096#ifdef CONFIG_WNM
2097 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002098 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002099 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002100#endif /* CONFIG_WNM */
2101 break;
2102 case 3: /* Bits 24-31 */
2103#ifdef CONFIG_WNM
2104 *pos |= 0x02; /* Bit 25 - SSID List */
2105#endif /* CONFIG_WNM */
2106#ifdef CONFIG_INTERWORKING
2107 if (wpa_s->conf->interworking)
2108 *pos |= 0x80; /* Bit 31 - Interworking */
2109#endif /* CONFIG_INTERWORKING */
2110 break;
2111 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002112#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002113 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002114 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002115#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002116 break;
2117 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002118#ifdef CONFIG_HS20
2119 if (wpa_s->conf->hs20)
2120 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2121#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002122#ifdef CONFIG_MBO
2123 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2124#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002125 break;
2126 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002127#ifdef CONFIG_TESTING_OPTIONS
2128 if (wpa_s->disable_scs_support)
2129 scs = false;
2130#endif /* CONFIG_TESTING_OPTIONS */
2131 if (scs)
2132 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002133 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002134 case 7: /* Bits 56-63 */
2135 break;
2136 case 8: /* Bits 64-71 */
2137 if (wpa_s->conf->ftm_responder)
2138 *pos |= 0x40; /* Bit 70 - FTM responder */
2139 if (wpa_s->conf->ftm_initiator)
2140 *pos |= 0x80; /* Bit 71 - FTM initiator */
2141 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002142 case 9: /* Bits 72-79 */
2143#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002144 if (!wpa_s->disable_fils)
2145 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002146#endif /* CONFIG_FILS */
2147 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002148 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002149#ifdef CONFIG_TESTING_OPTIONS
2150 if (wpa_s->disable_mscs_support)
2151 mscs = false;
2152#endif /* CONFIG_TESTING_OPTIONS */
2153 if (mscs)
2154 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002155 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002156 }
2157}
2158
2159
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002160int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002161{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002162 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002163 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002164
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002165 if (len < wpa_s->extended_capa_len)
2166 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002167 if (buflen < (size_t) len + 2) {
2168 wpa_printf(MSG_INFO,
2169 "Not enough room for building extended capabilities element");
2170 return -1;
2171 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002172
2173 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002174 *pos++ = len;
2175 for (i = 0; i < len; i++, pos++) {
2176 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002177
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002178 if (i < wpa_s->extended_capa_len) {
2179 *pos &= ~wpa_s->extended_capa_mask[i];
2180 *pos |= wpa_s->extended_capa[i];
2181 }
2182 }
2183
2184 while (len > 0 && buf[1 + len] == 0) {
2185 len--;
2186 buf[1] = len;
2187 }
2188 if (len == 0)
2189 return 0;
2190
2191 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002192}
2193
2194
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002195static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2196 struct wpa_bss *test_bss)
2197{
2198 struct wpa_bss *bss;
2199
2200 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2201 if (bss == test_bss)
2202 return 1;
2203 }
2204
2205 return 0;
2206}
2207
2208
2209static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2210 struct wpa_ssid *test_ssid)
2211{
2212 struct wpa_ssid *ssid;
2213
2214 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2215 if (ssid == test_ssid)
2216 return 1;
2217 }
2218
2219 return 0;
2220}
2221
2222
2223int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2224 struct wpa_ssid *test_ssid)
2225{
2226 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2227 return 0;
2228
2229 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2230}
2231
2232
2233void wpas_connect_work_free(struct wpa_connect_work *cwork)
2234{
2235 if (cwork == NULL)
2236 return;
2237 os_free(cwork);
2238}
2239
2240
2241void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2242{
2243 struct wpa_connect_work *cwork;
2244 struct wpa_radio_work *work = wpa_s->connect_work;
2245
2246 if (!work)
2247 return;
2248
2249 wpa_s->connect_work = NULL;
2250 cwork = work->ctx;
2251 work->ctx = NULL;
2252 wpas_connect_work_free(cwork);
2253 radio_work_done(work);
2254}
2255
2256
Sunil Ravi77d572f2023-01-17 23:58:31 +00002257int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2258 enum wpas_mac_addr_style style,
2259 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002260{
2261 struct os_reltime now;
2262 u8 addr[ETH_ALEN];
2263
2264 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002265 /* Random addresses are valid within a given ESS so check
2266 * expiration/value only when continuing to use the same ESS. */
2267 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2268 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2269 /* Pregenerated addresses do not expire but their value
2270 * might have changed, so let's check that. */
2271 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2272 ETH_ALEN) == 0)
2273 return 0;
2274 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2275 wpa_s->last_mac_addr_change.usec != 0) &&
2276 !os_reltime_expired(
2277 &now,
2278 &wpa_s->last_mac_addr_change,
2279 wpa_s->conf->rand_addr_lifetime)) {
2280 wpa_msg(wpa_s, MSG_DEBUG,
2281 "Previously selected random MAC address has not yet expired");
2282 return 0;
2283 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002284 }
2285
2286 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002287 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002288 if (random_mac_addr(addr) < 0)
2289 return -1;
2290 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002291 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002292 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2293 if (random_mac_addr_keep_oui(addr) < 0)
2294 return -1;
2295 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002296 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2297 if (!ssid) {
2298 wpa_msg(wpa_s, MSG_INFO,
2299 "Invalid 'ssid' for address policy 3");
2300 return -1;
2301 }
2302 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2303 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002304 default:
2305 return -1;
2306 }
2307
2308 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2309 wpa_msg(wpa_s, MSG_INFO,
2310 "Failed to set random MAC address");
2311 return -1;
2312 }
2313
2314 os_get_reltime(&wpa_s->last_mac_addr_change);
2315 wpa_s->mac_addr_changed = 1;
2316 wpa_s->last_mac_addr_style = style;
2317
2318 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2319 wpa_msg(wpa_s, MSG_INFO,
2320 "Could not update MAC address information");
2321 return -1;
2322 }
2323
2324 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2325 MAC2STR(addr));
2326
Sunil Ravi77d572f2023-01-17 23:58:31 +00002327 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002328}
2329
2330
2331int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2332{
2333 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2334 !wpa_s->conf->preassoc_mac_addr)
2335 return 0;
2336
Sunil Ravi77d572f2023-01-17 23:58:31 +00002337 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2338 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002339}
2340
2341
Sunil Ravi89eba102022-09-13 21:04:37 -07002342void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
Hai Shalomc3565922019-10-28 11:58:20 -07002343{
2344#ifdef CONFIG_SAE
2345 int *groups = conf->sae_groups;
2346 int default_groups[] = { 19, 20, 21, 0 };
2347 const char *password;
2348
2349 if (!groups || groups[0] <= 0)
2350 groups = default_groups;
2351
2352 password = ssid->sae_password;
2353 if (!password)
2354 password = ssid->passphrase;
2355
Hai Shalom899fcc72020-10-19 14:38:18 -07002356 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002357 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002358 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002359 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002360 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002361 /* PT derivation not needed */
2362 sae_deinit_pt(ssid->pt);
2363 ssid->pt = NULL;
2364 return;
2365 }
2366
2367 if (ssid->pt)
2368 return; /* PT already derived */
2369 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2370 (const u8 *) password, os_strlen(password),
2371 ssid->sae_password_id);
2372#endif /* CONFIG_SAE */
2373}
2374
2375
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002376static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2377{
2378#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2379 os_free(wpa_s->sme.sae_rejected_groups);
2380 wpa_s->sme.sae_rejected_groups = NULL;
2381#ifdef CONFIG_TESTING_OPTIONS
2382 if (wpa_s->extra_sae_rejected_groups) {
2383 int i, *groups = wpa_s->extra_sae_rejected_groups;
2384
2385 for (i = 0; groups[i]; i++) {
2386 wpa_printf(MSG_DEBUG,
2387 "TESTING: Indicate rejection of an extra SAE group %d",
2388 groups[i]);
2389 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2390 groups[i]);
2391 }
2392 }
2393#endif /* CONFIG_TESTING_OPTIONS */
2394#endif /* CONFIG_SAE && CONFIG_SME */
2395}
2396
2397
Hai Shalom60840252021-02-19 19:02:11 -08002398int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2399{
2400 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2401 wpa_msg(wpa_s, MSG_INFO,
2402 "Could not restore permanent MAC address");
2403 return -1;
2404 }
2405 wpa_s->mac_addr_changed = 0;
2406 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2407 wpa_msg(wpa_s, MSG_INFO,
2408 "Could not update MAC address information");
2409 return -1;
2410 }
2411 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2412 return 0;
2413}
2414
2415
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002416static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418/**
2419 * wpa_supplicant_associate - Request association
2420 * @wpa_s: Pointer to wpa_supplicant data
2421 * @bss: Scan results for the selected BSS, or %NULL if not available
2422 * @ssid: Configuration data for the selected network
2423 *
2424 * This function is used to request %wpa_supplicant to associate with a BSS.
2425 */
2426void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2427 struct wpa_bss *bss, struct wpa_ssid *ssid)
2428{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002429 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002430 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002431
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002432 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002433 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002434
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002435 /*
2436 * If we are starting a new connection, any previously pending EAPOL
2437 * RX cannot be valid anymore.
2438 */
2439 wpabuf_free(wpa_s->pending_eapol_rx);
2440 wpa_s->pending_eapol_rx = NULL;
2441
Sunil Ravi77d572f2023-01-17 23:58:31 +00002442 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002443 rand_style = wpa_s->conf->mac_addr;
2444 else
2445 rand_style = ssid->mac_addr;
2446
Sunil Ravia04bd252022-05-02 22:54:18 -07002447 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002448 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002449 wmm_ac_clear_saved_tspecs(wpa_s);
2450 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002451 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002452#ifdef CONFIG_TESTING_OPTIONS
2453 wpa_s->testing_resend_assoc = 0;
2454#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002455
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002456 if (wpa_s->last_ssid == ssid) {
2457 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002458 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002459 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2460 wmm_ac_save_tspecs(wpa_s);
2461 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002462 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2463 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002464 }
Hai Shalomc3565922019-10-28 11:58:20 -07002465 } else {
2466#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002467 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002468#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002469 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002470#ifdef CONFIG_SAE
2471 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2472#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002473
Sunil Ravi77d572f2023-01-17 23:58:31 +00002474 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2475 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2476
2477 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002478 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002479 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2480 status > 0) /* MAC changed */
2481 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2482 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2483 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002484 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002485 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002486 }
2487 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488
2489#ifdef CONFIG_IBSS_RSN
2490 ibss_rsn_deinit(wpa_s->ibss_rsn);
2491 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002492#else /* CONFIG_IBSS_RSN */
2493 if (ssid->mode == WPAS_MODE_IBSS &&
2494 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2495 wpa_msg(wpa_s, MSG_INFO,
2496 "IBSS RSN not supported in the build");
2497 return;
2498 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499#endif /* CONFIG_IBSS_RSN */
2500
2501 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2502 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2503#ifdef CONFIG_AP
2504 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2505 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2506 "mode");
2507 return;
2508 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002509 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2510 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002511 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2512 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002513 return;
2514 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 wpa_s->current_bss = bss;
2516#else /* CONFIG_AP */
2517 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2518 "the build");
2519#endif /* CONFIG_AP */
2520 return;
2521 }
2522
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002523 if (ssid->mode == WPAS_MODE_MESH) {
2524#ifdef CONFIG_MESH
2525 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2526 wpa_msg(wpa_s, MSG_INFO,
2527 "Driver does not support mesh mode");
2528 return;
2529 }
2530 if (bss)
2531 ssid->frequency = bss->freq;
2532 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2533 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2534 return;
2535 }
2536 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002537#else /* CONFIG_MESH */
2538 wpa_msg(wpa_s, MSG_ERROR,
2539 "mesh mode support not included in the build");
2540#endif /* CONFIG_MESH */
2541 return;
2542 }
2543
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002544 /*
2545 * Set WPA state machine configuration to match the selected network now
2546 * so that the information is available before wpas_start_assoc_cb()
2547 * gets called. This is needed at least for RSN pre-authentication where
2548 * candidate APs are added to a list based on scan result processing
2549 * before completion of the first association.
2550 */
2551 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2552
2553#ifdef CONFIG_DPP
2554 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2555 return;
2556#endif /* CONFIG_DPP */
2557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558#ifdef CONFIG_TDLS
2559 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002560 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561#endif /* CONFIG_TDLS */
2562
Hai Shalomc3565922019-10-28 11:58:20 -07002563#ifdef CONFIG_MBO
2564 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2565#endif /* CONFIG_MBO */
2566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002568 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 sme_authenticate(wpa_s, bss, ssid);
2570 return;
2571 }
2572
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002573 if (wpa_s->connect_work) {
2574 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2575 return;
2576 }
2577
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002578 if (radio_work_pending(wpa_s, "connect")) {
2579 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2580 return;
2581 }
2582
Dmitry Shmidt29333592017-01-09 12:27:11 -08002583#ifdef CONFIG_SME
2584 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2585 /* Clear possibly set auth_alg, if any, from last attempt. */
2586 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2587 }
2588#endif /* CONFIG_SME */
2589
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002590 wpas_abort_ongoing_scan(wpa_s);
2591
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002592 cwork = os_zalloc(sizeof(*cwork));
2593 if (cwork == NULL)
2594 return;
2595
2596 cwork->bss = bss;
2597 cwork->ssid = ssid;
2598
2599 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2600 wpas_start_assoc_cb, cwork) < 0) {
2601 os_free(cwork);
2602 }
2603}
2604
2605
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002606static int bss_is_ibss(struct wpa_bss *bss)
2607{
2608 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2609 IEEE80211_CAP_IBSS;
2610}
2611
2612
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002613static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2614 const struct wpa_ssid *ssid)
2615{
2616 enum hostapd_hw_mode hw_mode;
2617 struct hostapd_hw_modes *mode = NULL;
2618 u8 channel;
2619 int i;
2620
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002621 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2622 if (hw_mode == NUM_HOSTAPD_MODES)
2623 return 0;
2624 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2625 if (wpa_s->hw.modes[i].mode == hw_mode) {
2626 mode = &wpa_s->hw.modes[i];
2627 break;
2628 }
2629 }
2630
2631 if (!mode)
2632 return 0;
2633
2634 return mode->vht_capab != 0;
2635}
2636
2637
Hai Shalomc1a21442022-02-04 13:43:00 -08002638static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2639{
2640 int i;
2641
2642 for (i = channel; i < channel + 16; i += 4) {
2643 struct hostapd_channel_data *chan;
2644
2645 chan = hw_get_channel_chan(mode, i, NULL);
2646 if (!chan ||
2647 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2648 return false;
2649 }
2650
2651 return true;
2652}
2653
2654
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002655void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2656 const struct wpa_ssid *ssid,
2657 struct hostapd_freq_params *freq)
2658{
Hai Shalom81f62d82019-07-22 12:10:00 -07002659 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002660 enum hostapd_hw_mode hw_mode;
2661 struct hostapd_hw_modes *mode = NULL;
2662 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2663 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002664 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2665 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2666 6595, 6675, 6755, 6835, 6915, 6995 };
2667 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002668 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2669 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002670 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002671 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002673 int chwidth, seg0, seg1;
2674 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002675 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002676
2677 freq->freq = ssid->frequency;
2678
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002679 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2680 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2681
2682 if (ssid->mode != WPAS_MODE_IBSS)
2683 break;
2684
2685 /* Don't adjust control freq in case of fixed_freq */
2686 if (ssid->fixed_freq)
2687 break;
2688
2689 if (!bss_is_ibss(bss))
2690 continue;
2691
2692 if (ssid->ssid_len == bss->ssid_len &&
2693 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2694 wpa_printf(MSG_DEBUG,
2695 "IBSS already found in scan results, adjust control freq: %d",
2696 bss->freq);
2697 freq->freq = bss->freq;
2698 obss_scan = 0;
2699 break;
2700 }
2701 }
2702
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002703 /* For IBSS check HT_IBSS flag */
2704 if (ssid->mode == WPAS_MODE_IBSS &&
2705 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2706 return;
2707
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002708 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2709 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2710 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2711 wpa_printf(MSG_DEBUG,
2712 "IBSS: WEP/TKIP detected, do not try to enable HT");
2713 return;
2714 }
2715
2716 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002717 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2718 if (wpa_s->hw.modes[i].mode == hw_mode) {
2719 mode = &wpa_s->hw.modes[i];
2720 break;
2721 }
2722 }
2723
2724 if (!mode)
2725 return;
2726
Hai Shalom60840252021-02-19 19:02:11 -08002727 freq->channel = channel;
2728
Hai Shalomc3565922019-10-28 11:58:20 -07002729 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2730 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002731
Hai Shalomc1a21442022-02-04 13:43:00 -08002732 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2733 * However, HE is mandatory for 6 GHz.
2734 */
2735 is_6ghz = is_6ghz_freq(freq->freq);
2736 if (is_6ghz)
2737 goto skip_to_6ghz;
2738
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002739#ifdef CONFIG_HT_OVERRIDES
2740 if (ssid->disable_ht) {
2741 freq->ht_enabled = 0;
2742 return;
2743 }
2744#endif /* CONFIG_HT_OVERRIDES */
2745
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002746 freq->ht_enabled = ht_supported(mode);
2747 if (!freq->ht_enabled)
2748 return;
2749
Hai Shalomc3565922019-10-28 11:58:20 -07002750 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2751 if (is_24ghz)
2752 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002753#ifdef CONFIG_HE_OVERRIDES
2754 if (is_24ghz && ssid->disable_he)
2755 freq->he_enabled = 0;
2756#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002757
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002758 /* Setup higher BW only for 5 GHz */
2759 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2760 return;
2761
2762 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2763 pri_chan = &mode->channels[chan_idx];
2764 if (pri_chan->chan == channel)
2765 break;
2766 pri_chan = NULL;
2767 }
2768 if (!pri_chan)
2769 return;
2770
2771 /* Check primary channel flags */
2772 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2773 return;
2774
Hai Shalom74f70d42019-02-11 14:42:39 -08002775 freq->channel = pri_chan->chan;
2776
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002777#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002778 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002779#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002780 if (ssid->disable_vht)
2781 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002782#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002783 goto skip_ht40;
2784 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002785#endif /* CONFIG_HT_OVERRIDES */
2786
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002787 /* Check/setup HT40+/HT40- */
2788 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2789 if (ht40plus[j] == channel) {
2790 ht40 = 1;
2791 break;
2792 }
2793 }
2794
2795 /* Find secondary channel */
2796 for (i = 0; i < mode->num_channels; i++) {
2797 sec_chan = &mode->channels[i];
2798 if (sec_chan->chan == channel + ht40 * 4)
2799 break;
2800 sec_chan = NULL;
2801 }
2802 if (!sec_chan)
2803 return;
2804
2805 /* Check secondary channel flags */
2806 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2807 return;
2808
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002809 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002810 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2811 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002812 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002813 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2814 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002815 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002816 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002817
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002818 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002819 struct wpa_scan_results *scan_res;
2820
2821 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2822 if (scan_res == NULL) {
2823 /* Back to HT20 */
2824 freq->sec_channel_offset = 0;
2825 return;
2826 }
2827
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002828 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002829 switch (res) {
2830 case 0:
2831 /* Back to HT20 */
2832 freq->sec_channel_offset = 0;
2833 break;
2834 case 1:
2835 /* Configuration allowed */
2836 break;
2837 case 2:
2838 /* Switch pri/sec channels */
2839 freq->freq = hw_get_freq(mode, sec_chan->chan);
2840 freq->sec_channel_offset = -freq->sec_channel_offset;
2841 freq->channel = sec_chan->chan;
2842 break;
2843 default:
2844 freq->sec_channel_offset = 0;
2845 break;
2846 }
2847
2848 wpa_scan_results_free(scan_res);
2849 }
2850
Hai Shalom74f70d42019-02-11 14:42:39 -08002851#ifdef CONFIG_HT_OVERRIDES
2852skip_ht40:
2853#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002854 wpa_printf(MSG_DEBUG,
2855 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2856 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002857
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002858 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002859 return;
2860
2861 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002862 if (ssid->mode == WPAS_MODE_IBSS &&
2863 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002864 return;
2865
Paul Stewart092955c2017-02-06 09:13:09 -08002866#ifdef CONFIG_VHT_OVERRIDES
2867 if (ssid->disable_vht) {
2868 freq->vht_enabled = 0;
2869 return;
2870 }
2871#endif /* CONFIG_VHT_OVERRIDES */
2872
Hai Shalomc1a21442022-02-04 13:43:00 -08002873skip_to_6ghz:
2874 vht_freq = *freq;
2875
2876 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002877 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002878 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002879 return;
2880
Hai Shalomfdcde762020-04-02 11:19:20 -07002881 /* Enable HE with VHT for 5 GHz */
2882 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002883
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002884 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002885 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2886 if (freq->freq >= bw80[j] &&
2887 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002888 break;
2889 }
2890
Hai Shalomc1a21442022-02-04 13:43:00 -08002891 if (j == ARRAY_SIZE(bw80) ||
2892 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002893 return;
2894
Hai Shalomc1a21442022-02-04 13:43:00 -08002895 /* Back to HT configuration if channel not usable */
2896 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2897 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002898
Sunil8cd6f4d2022-06-28 18:40:46 +00002899 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002900 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002901 seg1 = 0;
2902
Hai Shalomc1a21442022-02-04 13:43:00 -08002903 if ((mode->he_capab[ieee80211_mode].phy_cap[
2904 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2905 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2906 /* In 160 MHz, the initial four 20 MHz channels were validated
2907 * above; check the remaining four 20 MHz channels for the total
2908 * of 160 MHz bandwidth.
2909 */
2910 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2911 return;
2912
2913 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2914 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002915 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002916 seg0 = channel + 14;
2917 break;
2918 }
2919 }
2920 }
2921
Sunil8cd6f4d2022-06-28 18:40:46 +00002922 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002923 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002924 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002925 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002926 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002927 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002928
2929 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2930 NUM_HOSTAPD_MODES)
2931 return;
2932
2933 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002934 struct hostapd_channel_data *chan;
2935
2936 chan = hw_get_channel_chan(mode, i, NULL);
2937 if (!chan)
2938 continue;
2939
2940 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2941 HOSTAPD_CHAN_NO_IR |
2942 HOSTAPD_CHAN_RADAR))
2943 continue;
2944
2945 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002946 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002947 if (!is_6ghz)
2948 vht_caps |=
2949 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2950 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002951 }
2952
Sunil8cd6f4d2022-06-28 18:40:46 +00002953 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002954 break;
2955 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002956 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002957 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002958 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002959 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2960 seg0 = 50;
2961 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002962 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002963 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2964 seg0 = 114;
2965 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002966 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2967 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002968 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002969#ifdef CONFIG_HT_OVERRIDES
2970 if (ssid->disable_ht40)
2971 seg0 = 0;
2972#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002973 }
2974
Hai Shalomfdcde762020-04-02 11:19:20 -07002975#ifdef CONFIG_HE_OVERRIDES
2976 if (ssid->disable_he) {
2977 vht_freq.he_enabled = 0;
2978 freq->he_enabled = 0;
2979 }
2980#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002981 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002982 freq->channel, ssid->enable_edmg,
2983 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002984 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002985 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002986 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002987 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002988 &mode->he_capab[ieee80211_mode],
2989 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002990 return;
2991
2992 *freq = vht_freq;
2993
2994 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2995 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002996}
2997
2998
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002999#ifdef CONFIG_FILS
3000static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3001 size_t ie_buf_len)
3002{
3003 struct fils_hlp_req *req;
3004 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3005 const u8 *pos;
3006 u8 *buf = ie_buf;
3007
3008 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3009 list) {
3010 rem_len = ie_buf_len - ie_len;
3011 pos = wpabuf_head(req->pkt);
3012 hdr_len = 1 + 2 * ETH_ALEN + 6;
3013 hlp_len = wpabuf_len(req->pkt);
3014
3015 if (rem_len < 2 + hdr_len + hlp_len) {
3016 wpa_printf(MSG_ERROR,
3017 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3018 (unsigned long) rem_len,
3019 (unsigned long) (2 + hdr_len + hlp_len));
3020 break;
3021 }
3022
3023 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3024 /* Element ID */
3025 *buf++ = WLAN_EID_EXTENSION;
3026 /* Length */
3027 *buf++ = len;
3028 /* Element ID Extension */
3029 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3030 /* Destination MAC address */
3031 os_memcpy(buf, req->dst, ETH_ALEN);
3032 buf += ETH_ALEN;
3033 /* Source MAC address */
3034 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3035 buf += ETH_ALEN;
3036 /* LLC/SNAP Header */
3037 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3038 buf += 6;
3039 /* HLP Packet */
3040 os_memcpy(buf, pos, len - hdr_len);
3041 buf += len - hdr_len;
3042 pos += len - hdr_len;
3043
3044 hlp_len -= len - hdr_len;
3045 ie_len += 2 + len;
3046 rem_len -= 2 + len;
3047
3048 while (hlp_len) {
3049 len = (hlp_len > 255) ? 255 : hlp_len;
3050 if (rem_len < 2 + len)
3051 break;
3052 *buf++ = WLAN_EID_FRAGMENT;
3053 *buf++ = len;
3054 os_memcpy(buf, pos, len);
3055 buf += len;
3056 pos += len;
3057
3058 hlp_len -= len;
3059 ie_len += 2 + len;
3060 rem_len -= 2 + len;
3061 }
3062 }
3063
3064 return ie_len;
3065}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003066
3067
3068int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3069{
3070 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3071 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3072 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3073 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3074}
3075
3076
3077int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3078{
3079#ifdef CONFIG_FILS_SK_PFS
3080 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3081 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3082#else /* CONFIG_FILS_SK_PFS */
3083 return 0;
3084#endif /* CONFIG_FILS_SK_PFS */
3085}
3086
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087#endif /* CONFIG_FILS */
3088
3089
Hai Shalomc1a21442022-02-04 13:43:00 -08003090static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3091 struct wpa_bss *bss,
3092 u8 *wpa_ie, size_t wpa_ie_len,
3093 size_t max_wpa_ie_len)
3094{
3095 struct wpabuf *wfa_ie = NULL;
3096 u8 wfa_capa[1];
3097 size_t wfa_ie_len, buf_len;
3098
3099 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3100 if (wpa_s->enable_dscp_policy_capa)
3101 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3102
3103 if (!wfa_capa[0])
3104 return wpa_ie_len;
3105
3106 /* Wi-Fi Alliance element */
3107 buf_len = 1 + /* Element ID */
3108 1 + /* Length */
3109 3 + /* OUI */
3110 1 + /* OUI Type */
3111 1 + /* Capabilities Length */
3112 sizeof(wfa_capa); /* Capabilities */
3113 wfa_ie = wpabuf_alloc(buf_len);
3114 if (!wfa_ie)
3115 return wpa_ie_len;
3116
3117 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3118 wpabuf_put_u8(wfa_ie, buf_len - 2);
3119 wpabuf_put_be24(wfa_ie, OUI_WFA);
3120 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3121 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3122 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3123
3124 wfa_ie_len = wpabuf_len(wfa_ie);
3125 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3126 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3127 wfa_ie);
3128 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3129 wfa_ie_len);
3130 wpa_ie_len += wfa_ie_len;
3131 }
3132
3133 wpabuf_free(wfa_ie);
3134 return wpa_ie_len;
3135}
3136
3137
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138static u8 * wpas_populate_assoc_ies(
3139 struct wpa_supplicant *wpa_s,
3140 struct wpa_bss *bss, struct wpa_ssid *ssid,
3141 struct wpa_driver_associate_params *params,
3142 enum wpa_drv_update_connect_params_mask *mask)
3143{
3144 u8 *wpa_ie;
3145 size_t max_wpa_ie_len = 500;
3146 size_t wpa_ie_len;
3147 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003148#ifdef CONFIG_MBO
3149 const u8 *mbo_ie;
3150#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303151#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3152 int pmksa_cached = 0;
3153#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003154#ifdef CONFIG_FILS
3155 const u8 *realm, *username, *rrk;
3156 size_t realm_len, username_len, rrk_len;
3157 u16 next_seq_num;
3158 struct fils_hlp_req *req;
3159
3160 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3161 list) {
3162 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3163 2 + 2 * wpabuf_len(req->pkt) / 255;
3164 }
3165#endif /* CONFIG_FILS */
3166
3167 wpa_ie = os_malloc(max_wpa_ie_len);
3168 if (!wpa_ie) {
3169 wpa_printf(MSG_ERROR,
3170 "Failed to allocate connect IE buffer for %lu bytes",
3171 (unsigned long) max_wpa_ie_len);
3172 return NULL;
3173 }
3174
3175 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3176 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3177 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3178 int try_opportunistic;
3179 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003180 const u8 *addr = bss->bssid;
3181
3182 if (wpa_s->valid_links)
3183 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003184
3185 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3186 wpa_s->conf->okc :
3187 ssid->proactive_key_caching) &&
3188 (ssid->proto & WPA_PROTO_RSN);
3189#ifdef CONFIG_FILS
3190 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3191 cache_id = wpa_bss_get_fils_cache_id(bss);
3192#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003193 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003194 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003195 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003196 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303197#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3198 pmksa_cached = 1;
3199#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003200 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003201 wpa_ie_len = max_wpa_ie_len;
3202 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003203 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003204 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3205 "key management and encryption suites");
3206 os_free(wpa_ie);
3207 return NULL;
3208 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003209#ifdef CONFIG_HS20
3210 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3211 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3212 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3213 wpa_ie_len = max_wpa_ie_len;
3214 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003215 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003216 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3217 "key management and encryption suites");
3218 os_free(wpa_ie);
3219 return NULL;
3220 }
3221#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003222 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3223 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3224 /*
3225 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3226 * use non-WPA since the scan results did not indicate that the
3227 * AP is using WPA or WPA2.
3228 */
3229 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3230 wpa_ie_len = 0;
3231 wpa_s->wpa_proto = 0;
3232 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3233 wpa_ie_len = max_wpa_ie_len;
3234 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003235 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003236 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3237 "key management and encryption suites (no "
3238 "scan results)");
3239 os_free(wpa_ie);
3240 return NULL;
3241 }
3242#ifdef CONFIG_WPS
3243 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3244 struct wpabuf *wps_ie;
3245 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3246 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3247 wpa_ie_len = wpabuf_len(wps_ie);
3248 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3249 } else
3250 wpa_ie_len = 0;
3251 wpabuf_free(wps_ie);
3252 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3253 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3254 params->wps = WPS_MODE_PRIVACY;
3255 else
3256 params->wps = WPS_MODE_OPEN;
3257 wpa_s->wpa_proto = 0;
3258#endif /* CONFIG_WPS */
3259 } else {
3260 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3261 wpa_ie_len = 0;
3262 wpa_s->wpa_proto = 0;
3263 }
3264
3265#ifdef IEEE8021X_EAPOL
3266 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3267 if (ssid->leap) {
3268 if (ssid->non_leap == 0)
3269 algs = WPA_AUTH_ALG_LEAP;
3270 else
3271 algs |= WPA_AUTH_ALG_LEAP;
3272 }
3273 }
3274
3275#ifdef CONFIG_FILS
3276 /* Clear FILS association */
3277 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3278
3279 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3280 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3281 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3282 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003283 &next_seq_num, &rrk, &rrk_len) == 0 &&
3284 (!wpa_s->last_con_fail_realm ||
3285 wpa_s->last_con_fail_realm_len != realm_len ||
3286 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287 algs = WPA_AUTH_ALG_FILS;
3288 params->fils_erp_username = username;
3289 params->fils_erp_username_len = username_len;
3290 params->fils_erp_realm = realm;
3291 params->fils_erp_realm_len = realm_len;
3292 params->fils_erp_next_seq_num = next_seq_num;
3293 params->fils_erp_rrk = rrk;
3294 params->fils_erp_rrk_len = rrk_len;
3295
3296 if (mask)
3297 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303298 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3299 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3300 pmksa_cached) {
3301 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003302 }
3303#endif /* CONFIG_FILS */
3304#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003305#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003306 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003307 algs = WPA_AUTH_ALG_SAE;
3308#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003309
3310 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3311 if (ssid->auth_alg) {
3312 algs = ssid->auth_alg;
3313 wpa_dbg(wpa_s, MSG_DEBUG,
3314 "Overriding auth_alg selection: 0x%x", algs);
3315 }
3316
Hai Shalom5f92bc92019-04-18 11:54:11 -07003317#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303318 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003319 wpa_dbg(wpa_s, MSG_DEBUG,
3320 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3321 algs = WPA_AUTH_ALG_OPEN;
3322 }
3323#endif /* CONFIG_SAE */
3324
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003325#ifdef CONFIG_P2P
3326 if (wpa_s->global->p2p) {
3327 u8 *pos;
3328 size_t len;
3329 int res;
3330 pos = wpa_ie + wpa_ie_len;
3331 len = max_wpa_ie_len - wpa_ie_len;
3332 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3333 ssid->p2p_group);
3334 if (res >= 0)
3335 wpa_ie_len += res;
3336 }
3337
3338 wpa_s->cross_connect_disallowed = 0;
3339 if (bss) {
3340 struct wpabuf *p2p;
3341 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3342 if (p2p) {
3343 wpa_s->cross_connect_disallowed =
3344 p2p_get_cross_connect_disallowed(p2p);
3345 wpabuf_free(p2p);
3346 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3347 "connection",
3348 wpa_s->cross_connect_disallowed ?
3349 "disallows" : "allows");
3350 }
3351 }
3352
3353 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3354#endif /* CONFIG_P2P */
3355
3356 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003357 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003358 wpa_ie + wpa_ie_len,
3359 max_wpa_ie_len -
3360 wpa_ie_len);
3361 }
3362
3363 /*
3364 * Workaround: Add Extended Capabilities element only if the AP
3365 * included this element in Beacon/Probe Response frames. Some older
3366 * APs seem to have interoperability issues if this element is
3367 * included, so while the standard may require us to include the
3368 * element in all cases, it is justifiable to skip it to avoid
3369 * interoperability issues.
3370 */
3371 if (ssid->p2p_group)
3372 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3373 else
3374 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3375
3376 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3377 u8 ext_capab[18];
3378 int ext_capab_len;
3379 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3380 sizeof(ext_capab));
3381 if (ext_capab_len > 0 &&
3382 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3383 u8 *pos = wpa_ie;
3384 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3385 pos += 2 + pos[1];
3386 os_memmove(pos + ext_capab_len, pos,
3387 wpa_ie_len - (pos - wpa_ie));
3388 wpa_ie_len += ext_capab_len;
3389 os_memcpy(pos, ext_capab, ext_capab_len);
3390 }
3391 }
3392
3393#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003394 if (is_hs20_network(wpa_s, ssid, bss)
3395#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3396 && is_hs20_config(wpa_s)
3397#endif /* ANDROID */
3398 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003399 struct wpabuf *hs20;
3400
Roshan Pius3a1667e2018-07-03 15:17:14 -07003401 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003402 if (hs20) {
3403 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3404 size_t len;
3405
Hai Shalom74f70d42019-02-11 14:42:39 -08003406 wpas_hs20_add_indication(hs20, pps_mo_id,
3407 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003408 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003409 len = max_wpa_ie_len - wpa_ie_len;
3410 if (wpabuf_len(hs20) <= len) {
3411 os_memcpy(wpa_ie + wpa_ie_len,
3412 wpabuf_head(hs20), wpabuf_len(hs20));
3413 wpa_ie_len += wpabuf_len(hs20);
3414 }
3415 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003416 }
3417 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003418 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003419#endif /* CONFIG_HS20 */
3420
3421 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3422 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3423 size_t len;
3424
3425 len = max_wpa_ie_len - wpa_ie_len;
3426 if (wpabuf_len(buf) <= len) {
3427 os_memcpy(wpa_ie + wpa_ie_len,
3428 wpabuf_head(buf), wpabuf_len(buf));
3429 wpa_ie_len += wpabuf_len(buf);
3430 }
3431 }
3432
3433#ifdef CONFIG_FST
3434 if (wpa_s->fst_ies) {
3435 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3436
3437 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3438 os_memcpy(wpa_ie + wpa_ie_len,
3439 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3440 wpa_ie_len += fst_ies_len;
3441 }
3442 }
3443#endif /* CONFIG_FST */
3444
3445#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003446 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003447 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003448 int len;
3449
3450 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003451 max_wpa_ie_len - wpa_ie_len,
3452 !!mbo_attr_from_mbo_ie(mbo_ie,
3453 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003454 if (len >= 0)
3455 wpa_ie_len += len;
3456 }
3457#endif /* CONFIG_MBO */
3458
3459#ifdef CONFIG_FILS
3460 if (algs == WPA_AUTH_ALG_FILS) {
3461 size_t len;
3462
3463 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3464 max_wpa_ie_len - wpa_ie_len);
3465 wpa_ie_len += len;
3466 }
3467#endif /* CONFIG_FILS */
3468
3469#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003470#ifdef CONFIG_TESTING_OPTIONS
3471 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3472 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3473 } else
3474#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475 if (algs == WPA_AUTH_ALG_OPEN &&
3476 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3477 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003478 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003479
Roshan Pius3a1667e2018-07-03 15:17:14 -07003480 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003481 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003482 } else if (wpa_s->assoc_status_code ==
3483 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003484 if (wpa_s->last_owe_group == 19)
3485 group = 20;
3486 else if (wpa_s->last_owe_group == 20)
3487 group = 21;
3488 else
3489 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003490 } else {
3491 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003492 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003493
Roshan Pius3a1667e2018-07-03 15:17:14 -07003494 wpa_s->last_owe_group = group;
3495 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003496 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3497 if (owe_ie &&
3498 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3499 os_memcpy(wpa_ie + wpa_ie_len,
3500 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3501 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003502 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003503 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003504 }
3505#endif /* CONFIG_OWE */
3506
Hai Shalom021b0b52019-04-10 11:17:58 -07003507#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003508 if (DPP_VERSION > 1 &&
3509 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003510 ssid->dpp_netaccesskey &&
3511 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003512 struct rsn_pmksa_cache_entry *pmksa;
3513
3514 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3515 if (!pmksa || !pmksa->dpp_pfs)
3516 goto pfs_fail;
3517
Hai Shalom021b0b52019-04-10 11:17:58 -07003518 dpp_pfs_free(wpa_s->dpp_pfs);
3519 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3520 ssid->dpp_netaccesskey_len);
3521 if (!wpa_s->dpp_pfs) {
3522 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3523 /* Try to continue without PFS */
3524 goto pfs_fail;
3525 }
3526 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3527 max_wpa_ie_len - wpa_ie_len) {
3528 os_memcpy(wpa_ie + wpa_ie_len,
3529 wpabuf_head(wpa_s->dpp_pfs->ie),
3530 wpabuf_len(wpa_s->dpp_pfs->ie));
3531 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3532 }
3533 }
3534pfs_fail:
3535#endif /* CONFIG_DPP2 */
3536
Roshan Pius3a1667e2018-07-03 15:17:14 -07003537#ifdef CONFIG_IEEE80211R
3538 /*
3539 * Add MDIE under these conditions: the network profile allows FT,
3540 * the AP supports FT, and the mobility domain ID matches.
3541 */
3542 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3543 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3544
3545 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3546 size_t len = 0;
3547 const u8 *md = mdie + 2;
3548 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3549
3550 if (os_memcmp(md, wpa_md,
3551 MOBILITY_DOMAIN_ID_LEN) == 0) {
3552 /* Add mobility domain IE */
3553 len = wpa_ft_add_mdie(
3554 wpa_s->wpa, wpa_ie + wpa_ie_len,
3555 max_wpa_ie_len - wpa_ie_len, mdie);
3556 wpa_ie_len += len;
3557 }
3558#ifdef CONFIG_SME
3559 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003560 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003561 wpa_dbg(wpa_s, MSG_DEBUG,
3562 "SME: Trying to use FT over-the-air");
3563 algs |= WPA_AUTH_ALG_FT;
3564 }
3565#endif /* CONFIG_SME */
3566 }
3567 }
3568#endif /* CONFIG_IEEE80211R */
3569
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003570#ifdef CONFIG_TESTING_OPTIONS
3571 if (wpa_s->rsnxe_override_assoc &&
3572 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3573 max_wpa_ie_len - wpa_ie_len) {
3574 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3575 os_memcpy(wpa_ie + wpa_ie_len,
3576 wpabuf_head(wpa_s->rsnxe_override_assoc),
3577 wpabuf_len(wpa_s->rsnxe_override_assoc));
3578 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3579 } else
3580#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003581 if (wpa_s->rsnxe_len > 0 &&
3582 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3583 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3584 wpa_ie_len += wpa_s->rsnxe_len;
3585 }
3586
Hai Shalomc1a21442022-02-04 13:43:00 -08003587#ifdef CONFIG_TESTING_OPTIONS
3588 if (wpa_s->disable_mscs_support)
3589 goto mscs_end;
3590#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003591 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3592 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003593 struct wpabuf *mscs_ie;
3594 size_t mscs_ie_len, buf_len;
3595
Hai Shalom899fcc72020-10-19 14:38:18 -07003596 buf_len = 3 + /* MSCS descriptor IE header */
3597 1 + /* Request type */
3598 2 + /* User priority control */
3599 4 + /* Stream timeout */
3600 3 + /* TCLAS Mask IE header */
3601 wpa_s->robust_av.frame_classifier_len;
3602 mscs_ie = wpabuf_alloc(buf_len);
3603 if (!mscs_ie) {
3604 wpa_printf(MSG_INFO,
3605 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003606 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003607 }
3608
3609 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3610 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3611 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3612 mscs_ie_len = wpabuf_len(mscs_ie);
3613 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3614 mscs_ie_len);
3615 wpa_ie_len += mscs_ie_len;
3616 }
3617
3618 wpabuf_free(mscs_ie);
3619 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003620mscs_end:
3621
3622 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3623 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003624
Hai Shalom74f70d42019-02-11 14:42:39 -08003625 if (ssid->multi_ap_backhaul_sta) {
3626 size_t multi_ap_ie_len;
3627
3628 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3629 max_wpa_ie_len - wpa_ie_len,
3630 MULTI_AP_BACKHAUL_STA);
3631 if (multi_ap_ie_len == 0) {
3632 wpa_printf(MSG_ERROR,
3633 "Multi-AP: Failed to build Multi-AP IE");
3634 os_free(wpa_ie);
3635 return NULL;
3636 }
3637 wpa_ie_len += multi_ap_ie_len;
3638 }
3639
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003640 params->wpa_ie = wpa_ie;
3641 params->wpa_ie_len = wpa_ie_len;
3642 params->auth_alg = algs;
3643 if (mask)
3644 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3645
3646 return wpa_ie;
3647}
3648
3649
Hai Shalomc3565922019-10-28 11:58:20 -07003650#ifdef CONFIG_OWE
3651static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3652{
3653 struct wpa_driver_associate_params params;
3654 u8 *wpa_ie;
3655
3656 os_memset(&params, 0, sizeof(params));
3657 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3658 wpa_s->current_ssid, &params, NULL);
3659 if (!wpa_ie)
3660 return;
3661
3662 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3663 os_free(wpa_ie);
3664}
3665#endif /* CONFIG_OWE */
3666
3667
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003668#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3669static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3670{
3671 struct wpa_driver_associate_params params;
3672 enum wpa_drv_update_connect_params_mask mask = 0;
3673 u8 *wpa_ie;
3674
3675 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3676 return; /* nothing to do */
3677
3678 os_memset(&params, 0, sizeof(params));
3679 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3680 wpa_s->current_ssid, &params, &mask);
3681 if (!wpa_ie)
3682 return;
3683
Hai Shalomc1a21442022-02-04 13:43:00 -08003684 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3685 wpa_s->auth_alg = params.auth_alg;
3686 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003687 }
3688
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003689 os_free(wpa_ie);
3690}
3691#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3692
3693
Hai Shalomc3565922019-10-28 11:58:20 -07003694static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3695{
3696 if (!edmg_ie || edmg_ie[1] < 6)
3697 return 0;
3698 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3699}
3700
3701
3702static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3703{
3704 if (!edmg_ie || edmg_ie[1] < 6)
3705 return 0;
3706 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3707}
3708
3709
3710/* Returns the intersection of two EDMG configurations.
3711 * Note: The current implementation is limited to CB2 only (CB1 included),
3712 * i.e., the implementation supports up to 2 contiguous channels.
3713 * For supporting non-contiguous (aggregated) channels and for supporting
3714 * CB3 and above, this function will need to be extended.
3715 */
3716static struct ieee80211_edmg_config
3717get_edmg_intersection(struct ieee80211_edmg_config a,
3718 struct ieee80211_edmg_config b,
3719 u8 primary_channel)
3720{
3721 struct ieee80211_edmg_config result;
3722 int i, contiguous = 0;
3723 int max_contiguous = 0;
3724
3725 result.channels = b.channels & a.channels;
3726 if (!result.channels) {
3727 wpa_printf(MSG_DEBUG,
3728 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3729 a.channels, b.channels);
3730 goto fail;
3731 }
3732
3733 if (!(result.channels & BIT(primary_channel - 1))) {
3734 wpa_printf(MSG_DEBUG,
3735 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3736 primary_channel, result.channels);
3737 goto fail;
3738 }
3739
3740 /* Find max contiguous channels */
3741 for (i = 0; i < 6; i++) {
3742 if (result.channels & BIT(i))
3743 contiguous++;
3744 else
3745 contiguous = 0;
3746
3747 if (contiguous > max_contiguous)
3748 max_contiguous = contiguous;
3749 }
3750
3751 /* Assuming AP and STA supports ONLY contiguous channels,
3752 * bw configuration can have value between 4-7.
3753 */
3754 if ((b.bw_config < a.bw_config))
3755 result.bw_config = b.bw_config;
3756 else
3757 result.bw_config = a.bw_config;
3758
3759 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3760 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3761 wpa_printf(MSG_DEBUG,
3762 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3763 max_contiguous);
3764 goto fail;
3765 }
3766
3767 return result;
3768
3769fail:
3770 result.channels = 0;
3771 result.bw_config = 0;
3772 return result;
3773}
3774
3775
3776static struct ieee80211_edmg_config
3777get_supported_edmg(struct wpa_supplicant *wpa_s,
3778 struct hostapd_freq_params *freq,
3779 struct ieee80211_edmg_config request_edmg)
3780{
3781 enum hostapd_hw_mode hw_mode;
3782 struct hostapd_hw_modes *mode = NULL;
3783 u8 primary_channel;
3784
3785 if (!wpa_s->hw.modes)
3786 goto fail;
3787
3788 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3789 if (hw_mode == NUM_HOSTAPD_MODES)
3790 goto fail;
3791
Hai Shalom60840252021-02-19 19:02:11 -08003792 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003793 if (!mode)
3794 goto fail;
3795
3796 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3797
3798fail:
3799 request_edmg.channels = 0;
3800 request_edmg.bw_config = 0;
3801 return request_edmg;
3802}
3803
3804
Hai Shalom021b0b52019-04-10 11:17:58 -07003805#ifdef CONFIG_MBO
3806void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3807{
3808 struct wpa_driver_associate_params params;
3809 u8 *wpa_ie;
3810
3811 /*
3812 * Update MBO connect params only in case of change of MBO attributes
3813 * when connected, if the AP support MBO.
3814 */
3815
3816 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3817 !wpa_s->current_bss ||
3818 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3819 return;
3820
3821 os_memset(&params, 0, sizeof(params));
3822 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3823 wpa_s->current_ssid, &params, NULL);
3824 if (!wpa_ie)
3825 return;
3826
3827 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3828 os_free(wpa_ie);
3829}
3830#endif /* CONFIG_MBO */
3831
3832
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003833static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3834{
3835 struct wpa_connect_work *cwork = work->ctx;
3836 struct wpa_bss *bss = cwork->bss;
3837 struct wpa_ssid *ssid = cwork->ssid;
3838 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003839 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003840 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003841 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003842 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003843 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003844 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003845#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003846 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003847#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003848 int assoc_failed = 0;
3849 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003850 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003851#ifdef CONFIG_HT_OVERRIDES
3852 struct ieee80211_ht_capabilities htcaps;
3853 struct ieee80211_ht_capabilities htcaps_mask;
3854#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003855#ifdef CONFIG_VHT_OVERRIDES
3856 struct ieee80211_vht_capabilities vhtcaps;
3857 struct ieee80211_vht_capabilities vhtcaps_mask;
3858#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003859
Hai Shalomc1a21442022-02-04 13:43:00 -08003860 wpa_s->roam_in_progress = false;
3861#ifdef CONFIG_WNM
3862 wpa_s->bss_trans_mgmt_in_progress = false;
3863#endif /* CONFIG_WNM */
3864
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003865 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003866 if (work->started) {
3867 wpa_s->connect_work = NULL;
3868
3869 /* cancel possible auth. timeout */
3870 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3871 NULL);
3872 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003873 wpas_connect_work_free(cwork);
3874 return;
3875 }
3876
3877 wpa_s->connect_work = work;
3878
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003879 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3880 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003881 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3882 wpas_connect_work_done(wpa_s);
3883 return;
3884 }
3885
Dmitry Shmidte4663042016-04-04 10:07:49 -07003886 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003887 os_memset(&params, 0, sizeof(params));
3888 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003889 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003890
3891 /* Starting new association, so clear the possibly used WPA IE from the
3892 * previous association. */
3893 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3894 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3895 wpa_s->rsnxe_len = 0;
3896 wpa_s->mscs_setup_done = false;
3897
3898 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3899 if (!wpa_ie) {
3900 wpas_connect_work_done(wpa_s);
3901 return;
3902 }
3903
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003904 if (bss &&
3905 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003906#ifdef CONFIG_IEEE80211R
3907 const u8 *ie, *md = NULL;
3908#endif /* CONFIG_IEEE80211R */
3909 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3910 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3911 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3912 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3913 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3914 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3915 if (bssid_changed)
3916 wpas_notify_bssid_changed(wpa_s);
3917#ifdef CONFIG_IEEE80211R
3918 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3919 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3920 md = ie + 2;
3921 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3922 if (md) {
3923 /* Prepare for the next transition */
3924 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3925 }
3926#endif /* CONFIG_IEEE80211R */
3927#ifdef CONFIG_WPS
3928 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3929 wpa_s->conf->ap_scan == 2 &&
3930 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3931 /* Use ap_scan==1 style network selection to find the network
3932 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003933 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003934 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 wpa_s->reassociate = 1;
3936 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003937 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003938 return;
3939#endif /* CONFIG_WPS */
3940 } else {
3941 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3942 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003943 if (bss)
3944 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3945 else
3946 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003948 if (!wpa_s->pno)
3949 wpa_supplicant_cancel_sched_scan(wpa_s);
3950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951 wpa_supplicant_cancel_scan(wpa_s);
3952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003953 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3954 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003955 cipher_pairwise = wpa_s->pairwise_cipher;
3956 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003957 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3959 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3960 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3961 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003962#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 if (wpa_set_wep_keys(wpa_s, ssid)) {
3964 use_crypt = 1;
3965 wep_keys_set = 1;
3966 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003967#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003968 }
3969 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3970 use_crypt = 0;
3971
3972#ifdef IEEE8021X_EAPOL
3973 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3974 if ((ssid->eapol_flags &
3975 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3976 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3977 !wep_keys_set) {
3978 use_crypt = 0;
3979 } else {
3980 /* Assume that dynamic WEP-104 keys will be used and
3981 * set cipher suites in order for drivers to expect
3982 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003983 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003984 }
3985 }
3986#endif /* IEEE8021X_EAPOL */
3987
3988 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3989 /* Set the key before (and later after) association */
3990 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3991 }
3992
Sunil8cd6f4d2022-06-28 18:40:46 +00003993 /* Set current_ssid before changing state to ASSOCIATING, so that the
3994 * selected SSID is available to wpas_notify_state_changed(). */
3995 old_ssid = wpa_s->current_ssid;
3996 wpa_s->current_ssid = ssid;
3997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3999 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000 params.ssid = bss->ssid;
4001 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004002 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4003 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004004 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4005 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004006 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004007 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004008 ssid->bssid_set,
4009 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004010 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004011 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004012 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004013 params.bssid_hint = bss->bssid;
4014 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004015 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004016 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004017 if (ssid->bssid_hint_set)
4018 params.bssid_hint = ssid->bssid_hint;
4019
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 params.ssid = ssid->ssid;
4021 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004022 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004024
4025 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4026 wpa_s->conf->ap_scan == 2) {
4027 params.bssid = ssid->bssid;
4028 params.fixed_bssid = 1;
4029 }
4030
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004031 /* Initial frequency for IBSS/mesh */
4032 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004033 ssid->frequency > 0 && params.freq.freq == 0)
4034 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004035
4036 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004037 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004038 if (ssid->beacon_int)
4039 params.beacon_int = ssid->beacon_int;
4040 else
4041 params.beacon_int = wpa_s->conf->beacon_int;
4042 }
4043
Hai Shalomc3565922019-10-28 11:58:20 -07004044 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004045 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4046 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004047 else
4048 edmg_ie_oper = NULL;
4049
4050 if (edmg_ie_oper) {
4051 params.freq.edmg.channels =
4052 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4053 params.freq.edmg.bw_config =
4054 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4055 wpa_printf(MSG_DEBUG,
4056 "AP supports EDMG channels 0x%x, bw_config %d",
4057 params.freq.edmg.channels,
4058 params.freq.edmg.bw_config);
4059
4060 /* User may ask for specific EDMG channel for EDMG connection
4061 * (must be supported by AP)
4062 */
4063 if (ssid->edmg_channel) {
4064 struct ieee80211_edmg_config configured_edmg;
4065 enum hostapd_hw_mode hw_mode;
4066 u8 primary_channel;
4067
4068 hw_mode = ieee80211_freq_to_chan(bss->freq,
4069 &primary_channel);
4070 if (hw_mode == NUM_HOSTAPD_MODES)
4071 goto edmg_fail;
4072
4073 hostapd_encode_edmg_chan(ssid->enable_edmg,
4074 ssid->edmg_channel,
4075 primary_channel,
4076 &configured_edmg);
4077
4078 if (ieee802_edmg_is_allowed(params.freq.edmg,
4079 configured_edmg)) {
4080 params.freq.edmg = configured_edmg;
4081 wpa_printf(MSG_DEBUG,
4082 "Use EDMG channel %d for connection",
4083 ssid->edmg_channel);
4084 } else {
4085 edmg_fail:
4086 params.freq.edmg.channels = 0;
4087 params.freq.edmg.bw_config = 0;
4088 wpa_printf(MSG_WARNING,
4089 "EDMG channel %d not supported by AP, fallback to DMG",
4090 ssid->edmg_channel);
4091 }
4092 }
4093
4094 if (params.freq.edmg.channels) {
4095 wpa_printf(MSG_DEBUG,
4096 "EDMG before: channels 0x%x, bw_config %d",
4097 params.freq.edmg.channels,
4098 params.freq.edmg.bw_config);
4099 params.freq.edmg = get_supported_edmg(wpa_s,
4100 &params.freq,
4101 params.freq.edmg);
4102 wpa_printf(MSG_DEBUG,
4103 "EDMG after: channels 0x%x, bw_config %d",
4104 params.freq.edmg.channels,
4105 params.freq.edmg.bw_config);
4106 }
4107 }
4108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109 params.pairwise_suite = cipher_pairwise;
4110 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004111 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004112 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004113 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004114 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004115 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004117 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004118#ifdef CONFIG_WEP
4119 {
4120 int i;
4121
4122 for (i = 0; i < NUM_WEP_KEYS; i++) {
4123 if (ssid->wep_key_len[i])
4124 params.wep_key[i] = ssid->wep_key[i];
4125 params.wep_key_len[i] = ssid->wep_key_len[i];
4126 }
4127 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004129#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004130
Hai Shalom74f70d42019-02-11 14:42:39 -08004131 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004132#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004133 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4134 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304135#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004136 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4137 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4138 (params.allowed_key_mgmts &
4139 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004140#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004142 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4143 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 }
4145
Hai Shalom74f70d42019-02-11 14:42:39 -08004146 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4147 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4148 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4149 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4150 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004151 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004152
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004153 if (wpa_s->conf->key_mgmt_offload) {
4154 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4155 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004156 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4157 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004158 params.req_key_mgmt_offload =
4159 ssid->proactive_key_caching < 0 ?
4160 wpa_s->conf->okc : ssid->proactive_key_caching;
4161 else
4162 params.req_key_mgmt_offload = 1;
4163
Winnie Chen4138eec2022-11-10 16:32:53 +08004164#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004165 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004166 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4167 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004168#else
4169 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4170 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004171#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004172 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4173 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004174 }
4175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176 params.drop_unencrypted = use_crypt;
4177
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004178 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004179 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004180 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4181 struct wpa_ie_data ie;
4182 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4183 ie.capabilities &
4184 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4185 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4186 "MFP: require MFP");
4187 params.mgmt_frame_protection =
4188 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004189#ifdef CONFIG_OWE
4190 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4191 !ssid->owe_only) {
4192 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4193#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 }
4195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004197 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004199 if (wpa_s->p2pdev->set_sta_uapsd)
4200 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 else
4202 params.uapsd = -1;
4203
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004204#ifdef CONFIG_HT_OVERRIDES
4205 os_memset(&htcaps, 0, sizeof(htcaps));
4206 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4207 params.htcaps = (u8 *) &htcaps;
4208 params.htcaps_mask = (u8 *) &htcaps_mask;
4209 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4210#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004211#ifdef CONFIG_VHT_OVERRIDES
4212 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4213 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4214 params.vhtcaps = &vhtcaps;
4215 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004216 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004217#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004218#ifdef CONFIG_HE_OVERRIDES
4219 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4220#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004221 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004222
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004223#ifdef CONFIG_P2P
4224 /*
4225 * If multi-channel concurrency is not supported, check for any
4226 * frequency conflict. In case of any frequency conflict, remove the
4227 * least prioritized connection.
4228 */
4229 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004230 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004231 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004232 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004233 wpa_printf(MSG_DEBUG,
4234 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004235 freq, params.freq.freq);
4236 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004237 wpa_s, params.freq.freq, ssid) < 0) {
4238 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004239 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004240 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004241 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004242 }
4243 }
4244#endif /* CONFIG_P2P */
4245
Dmitry Shmidte4663042016-04-04 10:07:49 -07004246 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004247 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004248 params.prev_bssid = prev_bssid;
4249
Hai Shalom60840252021-02-19 19:02:11 -08004250#ifdef CONFIG_SAE
4251 params.sae_pwe = wpa_s->conf->sae_pwe;
4252#endif /* CONFIG_SAE */
4253
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004254 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004255 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004256 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 if (ret < 0) {
4258 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4259 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004260 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004261 /*
4262 * The driver is known to mean what is saying, so we
4263 * can stop right here; the association will not
4264 * succeed.
4265 */
4266 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004267 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004268 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004269 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004270 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4271 return;
4272 }
4273 /* try to continue anyway; new association will be tried again
4274 * after timeout */
4275 assoc_failed = 1;
4276 }
4277
4278 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4279 /* Set the key after the association just in case association
4280 * cleared the previously configured key. */
4281 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4282 /* No need to timeout authentication since there is no key
4283 * management. */
4284 wpa_supplicant_cancel_auth_timeout(wpa_s);
4285 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4286#ifdef CONFIG_IBSS_RSN
4287 } else if (ssid->mode == WPAS_MODE_IBSS &&
4288 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4289 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4290 /*
4291 * RSN IBSS authentication is per-STA and we can disable the
4292 * per-BSSID authentication.
4293 */
4294 wpa_supplicant_cancel_auth_timeout(wpa_s);
4295#endif /* CONFIG_IBSS_RSN */
4296 } else {
4297 /* Timeout for IEEE 802.11 authentication and association */
4298 int timeout = 60;
4299
4300 if (assoc_failed) {
4301 /* give IBSS a bit more time */
4302 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4303 } else if (wpa_s->conf->ap_scan == 1) {
4304 /* give IBSS a bit more time */
4305 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4306 }
4307 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4308 }
4309
Hai Shalomfdcde762020-04-02 11:19:20 -07004310#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004311 if (wep_keys_set &&
4312 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313 /* Set static WEP keys again */
4314 wpa_set_wep_keys(wpa_s, ssid);
4315 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004316#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317
Sunil8cd6f4d2022-06-28 18:40:46 +00004318 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319 /*
4320 * Do not allow EAP session resumption between different
4321 * network configurations.
4322 */
4323 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4324 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004325
4326 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004327 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004328#ifdef CONFIG_HS20
4329 hs20_configure_frame_filters(wpa_s);
4330#endif /* CONFIG_HS20 */
4331 }
4332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004333 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4334 wpa_supplicant_initiate_eapol(wpa_s);
4335 if (old_ssid != wpa_s->current_ssid)
4336 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004337 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4338 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339}
4340
4341
4342static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4343 const u8 *addr)
4344{
4345 struct wpa_ssid *old_ssid;
4346
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004347 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004350 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004351 wpa_sm_set_config(wpa_s->wpa, NULL);
4352 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4353 if (old_ssid != wpa_s->current_ssid)
4354 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004355
4356 wpas_scs_deinit(wpa_s);
4357 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4359}
4360
4361
4362/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4364 * @wpa_s: Pointer to wpa_supplicant data
4365 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4366 *
4367 * This function is used to request %wpa_supplicant to deauthenticate from the
4368 * current AP.
4369 */
4370void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004371 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004372{
4373 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004374 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004375 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004376
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004377 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004378 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004379 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004380 reason_code, reason2str(reason_code),
4381 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004382
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004383 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4384 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4385 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004386 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004387 else if (!is_zero_ether_addr(wpa_s->bssid))
4388 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004389 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4390 /*
4391 * When using driver-based BSS selection, we may not know the
4392 * BSSID with which we are currently trying to associate. We
4393 * need to notify the driver of this disconnection even in such
4394 * a case, so use the all zeros address here.
4395 */
4396 addr = wpa_s->bssid;
4397 zero_addr = 1;
4398 }
4399
Hai Shalom74f70d42019-02-11 14:42:39 -08004400 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4401 wpa_s->enabled_4addr_mode = 0;
4402
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004403#ifdef CONFIG_TDLS
4404 wpa_tdls_teardown_peers(wpa_s->wpa);
4405#endif /* CONFIG_TDLS */
4406
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004407#ifdef CONFIG_MESH
4408 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004409 struct mesh_conf *mconf;
4410
4411 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004412 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4413 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004414 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4415 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004416 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004417 }
4418#endif /* CONFIG_MESH */
4419
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004420 if (addr) {
4421 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004422 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004423 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004424 event.deauth_info.locally_generated = 1;
4425 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004426 if (zero_addr)
4427 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428 }
4429
4430 wpa_supplicant_clear_connection(wpa_s, addr);
4431}
4432
Hai Shalomfdcde762020-04-02 11:19:20 -07004433
4434void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4435{
4436 wpa_s->own_reconnect_req = 1;
4437 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4438
4439}
4440
4441
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004442static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4443 struct wpa_ssid *ssid)
4444{
4445 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4446 return;
4447
4448 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004449 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004450 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4451 wpas_notify_network_enabled_changed(wpa_s, ssid);
4452
4453 /*
4454 * Try to reassociate since there is no current configuration and a new
4455 * network was made available.
4456 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004457 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004458 wpa_s->reassociate = 1;
4459}
4460
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004461
Roshan Pius950bec92016-07-19 09:49:24 -07004462/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004463 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004464 * @wpa_s: wpa_supplicant structure for a network interface
4465 * Returns: The new network configuration or %NULL if operation failed
4466 *
4467 * This function performs the following operations:
4468 * 1. Adds a new network.
4469 * 2. Send network addition notification.
4470 * 3. Marks the network disabled.
4471 * 4. Set network default parameters.
4472 */
4473struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4474{
4475 struct wpa_ssid *ssid;
4476
4477 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004478 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004479 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004480 wpas_notify_network_added(wpa_s, ssid);
4481 ssid->disabled = 1;
4482 wpa_config_set_network_defaults(ssid);
4483
4484 return ssid;
4485}
4486
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004487
Roshan Pius950bec92016-07-19 09:49:24 -07004488/**
4489 * wpa_supplicant_remove_network - Remove a configured network based on id
4490 * @wpa_s: wpa_supplicant structure for a network interface
4491 * @id: Unique network id to search for
4492 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4493 * could not be removed
4494 *
4495 * This function performs the following operations:
4496 * 1. Removes the network.
4497 * 2. Send network removal notification.
4498 * 3. Update internal state machines.
4499 * 4. Stop any running sched scans.
4500 */
4501int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4502{
Sunil Ravia04bd252022-05-02 22:54:18 -07004503 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004504 int was_disabled;
4505
4506 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004507 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004508 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004509 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004510
Sunil Ravia04bd252022-05-02 22:54:18 -07004511 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004512#ifdef CONFIG_SME
4513 wpa_s->sme.prev_bssid_set = 0;
4514#endif /* CONFIG_SME */
4515 /*
4516 * Invalidate the EAP session cache if the current or
4517 * previously used network is removed.
4518 */
4519 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4520 }
4521
Sunil Ravia04bd252022-05-02 22:54:18 -07004522 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004523 wpa_sm_set_config(wpa_s->wpa, NULL);
4524 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4525
4526 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4527 wpa_s->own_disconnect_req = 1;
4528 wpa_supplicant_deauthenticate(wpa_s,
4529 WLAN_REASON_DEAUTH_LEAVING);
4530 }
4531
4532 was_disabled = ssid->disabled;
4533
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004534 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004535 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004536
4537 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004538 wpa_printf(MSG_DEBUG,
4539 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004540 wpa_supplicant_cancel_sched_scan(wpa_s);
4541 wpa_supplicant_req_scan(wpa_s, 0, 0);
4542 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004543
Roshan Pius950bec92016-07-19 09:49:24 -07004544 return 0;
4545}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004548/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004549 * wpa_supplicant_remove_all_networks - Remove all configured networks
4550 * @wpa_s: wpa_supplicant structure for a network interface
4551 * Returns: 0 on success (errors are currently ignored)
4552 *
4553 * This function performs the following operations:
4554 * 1. Remove all networks.
4555 * 2. Send network removal notifications.
4556 * 3. Update internal state machines.
4557 * 4. Stop any running sched scans.
4558 */
4559int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4560{
4561 struct wpa_ssid *ssid;
4562
4563 if (wpa_s->sched_scanning)
4564 wpa_supplicant_cancel_sched_scan(wpa_s);
4565
4566 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4567 if (wpa_s->current_ssid) {
4568#ifdef CONFIG_SME
4569 wpa_s->sme.prev_bssid_set = 0;
4570#endif /* CONFIG_SME */
4571 wpa_sm_set_config(wpa_s->wpa, NULL);
4572 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4573 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4574 wpa_s->own_disconnect_req = 1;
4575 wpa_supplicant_deauthenticate(
4576 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4577 }
4578 ssid = wpa_s->conf->ssid;
4579 while (ssid) {
4580 struct wpa_ssid *remove_ssid = ssid;
4581 int id;
4582
4583 id = ssid->id;
4584 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004585 wpas_notify_network_removed(wpa_s, remove_ssid);
4586 wpa_config_remove_network(wpa_s->conf, id);
4587 }
4588 return 0;
4589}
4590
4591
4592/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004593 * wpa_supplicant_enable_network - Mark a configured network as enabled
4594 * @wpa_s: wpa_supplicant structure for a network interface
4595 * @ssid: wpa_ssid structure for a configured network or %NULL
4596 *
4597 * Enables the specified network or all networks if no network specified.
4598 */
4599void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4600 struct wpa_ssid *ssid)
4601{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004602 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004603 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4604 wpa_supplicant_enable_one_network(wpa_s, ssid);
4605 } else
4606 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004608 if (wpa_s->reassociate && !wpa_s->disconnected &&
4609 (!wpa_s->current_ssid ||
4610 wpa_s->wpa_state == WPA_DISCONNECTED ||
4611 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004612 if (wpa_s->sched_scanning) {
4613 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4614 "new network to scan filters");
4615 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004616 }
4617
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004618 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4619 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004620 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004621 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004622 }
4623}
4624
4625
4626/**
4627 * wpa_supplicant_disable_network - Mark a configured network as disabled
4628 * @wpa_s: wpa_supplicant structure for a network interface
4629 * @ssid: wpa_ssid structure for a configured network or %NULL
4630 *
4631 * Disables the specified network or all networks if no network specified.
4632 */
4633void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4634 struct wpa_ssid *ssid)
4635{
4636 struct wpa_ssid *other_ssid;
4637 int was_disabled;
4638
4639 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004640 if (wpa_s->sched_scanning)
4641 wpa_supplicant_cancel_sched_scan(wpa_s);
4642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004643 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4644 other_ssid = other_ssid->next) {
4645 was_disabled = other_ssid->disabled;
4646 if (was_disabled == 2)
4647 continue; /* do not change persistent P2P group
4648 * data */
4649
4650 other_ssid->disabled = 1;
4651
4652 if (was_disabled != other_ssid->disabled)
4653 wpas_notify_network_enabled_changed(
4654 wpa_s, other_ssid);
4655 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004656 if (wpa_s->current_ssid) {
4657 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4658 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004659 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004660 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004661 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004662 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004663 if (ssid == wpa_s->current_ssid) {
4664 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4665 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004666 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004668 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669
4670 was_disabled = ssid->disabled;
4671
4672 ssid->disabled = 1;
4673
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004674 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004675 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004676 if (wpa_s->sched_scanning) {
4677 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4678 "to remove network from filters");
4679 wpa_supplicant_cancel_sched_scan(wpa_s);
4680 wpa_supplicant_req_scan(wpa_s, 0, 0);
4681 }
4682 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004683 }
4684}
4685
4686
4687/**
4688 * wpa_supplicant_select_network - Attempt association with a network
4689 * @wpa_s: wpa_supplicant structure for a network interface
4690 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4691 */
4692void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4693 struct wpa_ssid *ssid)
4694{
4695
4696 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004697 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004699 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004700 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4701 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004702 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004704 disconnected = 1;
4705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004706
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004707 if (ssid)
4708 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4709
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710 /*
4711 * Mark all other networks disabled or mark all networks enabled if no
4712 * network specified.
4713 */
4714 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4715 other_ssid = other_ssid->next) {
4716 int was_disabled = other_ssid->disabled;
4717 if (was_disabled == 2)
4718 continue; /* do not change persistent P2P group data */
4719
4720 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004721 if (was_disabled && !other_ssid->disabled)
4722 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004723
4724 if (was_disabled != other_ssid->disabled)
4725 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4726 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004727
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004728 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4729 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004730 /* We are already associated with the selected network */
4731 wpa_printf(MSG_DEBUG, "Already associated with the "
4732 "selected network - do nothing");
4733 return;
4734 }
4735
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004736 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004737 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004738 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004739 wpa_s->connect_without_scan =
4740 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004741
4742 /*
4743 * Don't optimize next scan freqs since a new ESS has been
4744 * selected.
4745 */
4746 os_free(wpa_s->next_scan_freqs);
4747 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004748 } else {
4749 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004750 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004751
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004752 wpa_s->disconnected = 0;
4753 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004754 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004755 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004756 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004757 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004758 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4759 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004760
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004761 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004762 wpa_supplicant_fast_associate(wpa_s) != 1) {
4763 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004764 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004765 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004766 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767
4768 if (ssid)
4769 wpas_notify_network_selected(wpa_s, ssid);
4770}
4771
4772
4773/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004774 * wpas_remove_cred - Remove the specified credential and all the network
4775 * entries created based on the removed credential
4776 * @wpa_s: wpa_supplicant structure for a network interface
4777 * @cred: The credential to remove
4778 * Returns: 0 on success, -1 on failure
4779 */
4780int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4781{
4782 struct wpa_ssid *ssid, *next;
4783 int id;
4784
4785 if (!cred) {
4786 wpa_printf(MSG_DEBUG, "Could not find cred");
4787 return -1;
4788 }
4789
4790 id = cred->id;
4791 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4792 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4793 return -1;
4794 }
4795
4796 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4797
4798 /* Remove any network entry created based on the removed credential */
4799 ssid = wpa_s->conf->ssid;
4800 while (ssid) {
4801 next = ssid->next;
4802
4803 if (ssid->parent_cred == cred) {
4804 wpa_printf(MSG_DEBUG,
4805 "Remove network id %d since it used the removed credential",
4806 ssid->id);
4807 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4808 -1) {
4809 wpa_printf(MSG_DEBUG,
4810 "Could not find network id=%d",
4811 ssid->id);
4812 }
4813 }
4814
4815 ssid = next;
4816 }
4817
4818 return 0;
4819}
4820
4821
4822/**
4823 * wpas_remove_cred - Remove all the Interworking credentials
4824 * @wpa_s: wpa_supplicant structure for a network interface
4825 * Returns: 0 on success, -1 on failure
4826 */
4827int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4828{
4829 int res, ret = 0;
4830 struct wpa_cred *cred, *prev;
4831
4832 cred = wpa_s->conf->cred;
4833 while (cred) {
4834 prev = cred;
4835 cred = cred->next;
4836 res = wpas_remove_cred(wpa_s, prev);
4837 if (res < 0) {
4838 wpa_printf(MSG_DEBUG,
4839 "Removal of all credentials failed - failed to remove credential id=%d",
4840 prev->id);
4841 ret = -1;
4842 }
4843 }
4844
4845 return ret;
4846}
4847
4848
4849/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004850 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4851 * @wpa_s: wpa_supplicant structure for a network interface
4852 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4853 * @pkcs11_module_path: PKCS #11 module path or NULL
4854 * Returns: 0 on success; -1 on failure
4855 *
4856 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4857 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4858 * module path fails the paths will be reset to the default value (NULL).
4859 */
4860int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4861 const char *pkcs11_engine_path,
4862 const char *pkcs11_module_path)
4863{
4864 char *pkcs11_engine_path_copy = NULL;
4865 char *pkcs11_module_path_copy = NULL;
4866
4867 if (pkcs11_engine_path != NULL) {
4868 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4869 if (pkcs11_engine_path_copy == NULL)
4870 return -1;
4871 }
4872 if (pkcs11_module_path != NULL) {
4873 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004874 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004875 os_free(pkcs11_engine_path_copy);
4876 return -1;
4877 }
4878 }
4879
4880 os_free(wpa_s->conf->pkcs11_engine_path);
4881 os_free(wpa_s->conf->pkcs11_module_path);
4882 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4883 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4884
4885 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4886 eapol_sm_deinit(wpa_s->eapol);
4887 wpa_s->eapol = NULL;
4888 if (wpa_supplicant_init_eapol(wpa_s)) {
4889 /* Error -> Reset paths to the default value (NULL) once. */
4890 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4891 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4892 NULL);
4893
4894 return -1;
4895 }
4896 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4897
4898 return 0;
4899}
4900
4901
4902/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004903 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4904 * @wpa_s: wpa_supplicant structure for a network interface
4905 * @ap_scan: AP scan mode
4906 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4907 *
4908 */
4909int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4910{
4911
4912 int old_ap_scan;
4913
4914 if (ap_scan < 0 || ap_scan > 2)
4915 return -1;
4916
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004917 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4918 wpa_printf(MSG_INFO,
4919 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4920 }
4921
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004922#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004923 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4924 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4925 wpa_s->wpa_state < WPA_COMPLETED) {
4926 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4927 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004928 return 0;
4929 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004930#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004932 old_ap_scan = wpa_s->conf->ap_scan;
4933 wpa_s->conf->ap_scan = ap_scan;
4934
4935 if (old_ap_scan != wpa_s->conf->ap_scan)
4936 wpas_notify_ap_scan_changed(wpa_s);
4937
4938 return 0;
4939}
4940
4941
4942/**
4943 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4944 * @wpa_s: wpa_supplicant structure for a network interface
4945 * @expire_age: Expiration age in seconds
4946 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4947 *
4948 */
4949int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4950 unsigned int bss_expire_age)
4951{
4952 if (bss_expire_age < 10) {
4953 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4954 bss_expire_age);
4955 return -1;
4956 }
4957 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4958 bss_expire_age);
4959 wpa_s->conf->bss_expiration_age = bss_expire_age;
4960
4961 return 0;
4962}
4963
4964
4965/**
4966 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4967 * @wpa_s: wpa_supplicant structure for a network interface
4968 * @expire_count: number of scans after which an unseen BSS is reclaimed
4969 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4970 *
4971 */
4972int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4973 unsigned int bss_expire_count)
4974{
4975 if (bss_expire_count < 1) {
4976 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4977 bss_expire_count);
4978 return -1;
4979 }
4980 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4981 bss_expire_count);
4982 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4983
4984 return 0;
4985}
4986
4987
4988/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004989 * wpa_supplicant_set_scan_interval - Set scan interval
4990 * @wpa_s: wpa_supplicant structure for a network interface
4991 * @scan_interval: scan interval in seconds
4992 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4993 *
4994 */
4995int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4996 int scan_interval)
4997{
4998 if (scan_interval < 0) {
4999 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5000 scan_interval);
5001 return -1;
5002 }
5003 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5004 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005005 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005006
5007 return 0;
5008}
5009
5010
5011/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005012 * wpa_supplicant_set_debug_params - Set global debug params
5013 * @global: wpa_global structure
5014 * @debug_level: debug level
5015 * @debug_timestamp: determines if show timestamp in debug data
5016 * @debug_show_keys: determines if show keys in debug data
5017 * Returns: 0 if succeed or -1 if debug_level has wrong value
5018 */
5019int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5020 int debug_timestamp, int debug_show_keys)
5021{
5022
5023 int old_level, old_timestamp, old_show_keys;
5024
5025 /* check for allowed debuglevels */
5026 if (debug_level != MSG_EXCESSIVE &&
5027 debug_level != MSG_MSGDUMP &&
5028 debug_level != MSG_DEBUG &&
5029 debug_level != MSG_INFO &&
5030 debug_level != MSG_WARNING &&
5031 debug_level != MSG_ERROR)
5032 return -1;
5033
5034 old_level = wpa_debug_level;
5035 old_timestamp = wpa_debug_timestamp;
5036 old_show_keys = wpa_debug_show_keys;
5037
5038 wpa_debug_level = debug_level;
5039 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5040 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5041
5042 if (wpa_debug_level != old_level)
5043 wpas_notify_debug_level_changed(global);
5044 if (wpa_debug_timestamp != old_timestamp)
5045 wpas_notify_debug_timestamp_changed(global);
5046 if (wpa_debug_show_keys != old_show_keys)
5047 wpas_notify_debug_show_keys_changed(global);
5048
5049 return 0;
5050}
5051
5052
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005053#ifdef CONFIG_OWE
5054static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5055 const u8 *entry_ssid, size_t entry_ssid_len)
5056{
5057 const u8 *owe, *pos, *end;
5058 u8 ssid_len;
5059 struct wpa_bss *bss;
5060
5061 /* Check network profile SSID aganst the SSID in the
5062 * OWE Transition Mode element. */
5063
5064 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5065 if (!bss)
5066 return 0;
5067
5068 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5069 if (!owe)
5070 return 0;
5071
5072 pos = owe + 6;
5073 end = owe + 2 + owe[1];
5074
5075 if (end - pos < ETH_ALEN + 1)
5076 return 0;
5077 pos += ETH_ALEN;
5078 ssid_len = *pos++;
5079 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5080 return 0;
5081
5082 return entry_ssid_len == ssid_len &&
5083 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5084}
5085#endif /* CONFIG_OWE */
5086
5087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005088/**
5089 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5090 * @wpa_s: Pointer to wpa_supplicant data
5091 * Returns: A pointer to the current network structure or %NULL on failure
5092 */
5093struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5094{
5095 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005096 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005097 int res;
5098 size_t ssid_len;
5099 u8 bssid[ETH_ALEN];
5100 int wired;
5101
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005102 res = wpa_drv_get_ssid(wpa_s, ssid);
5103 if (res < 0) {
5104 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5105 "driver");
5106 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005108 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005109
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005110 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5112 "driver");
5113 return NULL;
5114 }
5115
5116 wired = wpa_s->conf->ap_scan == 0 &&
5117 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5118
5119 entry = wpa_s->conf->ssid;
5120 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005121 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005123 (!entry->ssid ||
5124 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5125 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005126 (!entry->bssid_set ||
5127 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5128 return entry;
5129#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005130 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005131 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5132 (entry->ssid == NULL || entry->ssid_len == 0) &&
5133 (!entry->bssid_set ||
5134 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5135 return entry;
5136#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005137
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005138#ifdef CONFIG_OWE
5139 if (!wpas_network_disabled(wpa_s, entry) &&
5140 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5141 entry->ssid_len) &&
5142 (!entry->bssid_set ||
5143 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5144 return entry;
5145#endif /* CONFIG_OWE */
5146
Dmitry Shmidt04949592012-07-19 12:16:46 -07005147 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005148 entry->ssid_len == 0 &&
5149 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5150 return entry;
5151
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005152 entry = entry->next;
5153 }
5154
5155 return NULL;
5156}
5157
5158
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005159static int select_driver(struct wpa_supplicant *wpa_s, int i)
5160{
5161 struct wpa_global *global = wpa_s->global;
5162
5163 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005164 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005165 if (global->drv_priv[i] == NULL) {
5166 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5167 "'%s'", wpa_drivers[i]->name);
5168 return -1;
5169 }
5170 }
5171
5172 wpa_s->driver = wpa_drivers[i];
5173 wpa_s->global_drv_priv = global->drv_priv[i];
5174
5175 return 0;
5176}
5177
5178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005179static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5180 const char *name)
5181{
5182 int i;
5183 size_t len;
5184 const char *pos, *driver = name;
5185
5186 if (wpa_s == NULL)
5187 return -1;
5188
5189 if (wpa_drivers[0] == NULL) {
5190 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5191 "wpa_supplicant");
5192 return -1;
5193 }
5194
5195 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005196 /* Default to first successful driver in the list */
5197 for (i = 0; wpa_drivers[i]; i++) {
5198 if (select_driver(wpa_s, i) == 0)
5199 return 0;
5200 }
5201 /* Drivers have each reported failure, so no wpa_msg() here. */
5202 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203 }
5204
5205 do {
5206 pos = os_strchr(driver, ',');
5207 if (pos)
5208 len = pos - driver;
5209 else
5210 len = os_strlen(driver);
5211
5212 for (i = 0; wpa_drivers[i]; i++) {
5213 if (os_strlen(wpa_drivers[i]->name) == len &&
5214 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005215 0) {
5216 /* First driver that succeeds wins */
5217 if (select_driver(wpa_s, i) == 0)
5218 return 0;
5219 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220 }
5221
5222 driver = pos + 1;
5223 } while (pos);
5224
5225 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5226 return -1;
5227}
5228
5229
5230/**
5231 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5232 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5233 * with struct wpa_driver_ops::init()
5234 * @src_addr: Source address of the EAPOL frame
5235 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5236 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005237 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238 *
5239 * This function is called for each received EAPOL frame. Most driver
5240 * interfaces rely on more generic OS mechanism for receiving frames through
5241 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5242 * take care of received EAPOL frames and deliver them to the core supplicant
5243 * code by calling this function.
5244 */
5245void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005246 const u8 *buf, size_t len,
5247 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005248{
5249 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005250 const u8 *connected_addr = wpa_s->valid_links ?
5251 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005252
Sunil8cd6f4d2022-06-28 18:40:46 +00005253 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5254 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005255 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5256
Hai Shalomc1a21442022-02-04 13:43:00 -08005257 if (wpa_s->own_disconnect_req) {
5258 wpa_printf(MSG_DEBUG,
5259 "Drop received EAPOL frame as we are disconnecting");
5260 return;
5261 }
5262
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005263#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005264 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5265 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005266 if (wpa_s->ignore_auth_resp) {
5267 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5268 return;
5269 }
5270#endif /* CONFIG_TESTING_OPTIONS */
5271
Jouni Malinena05074c2012-12-21 21:35:35 +02005272 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5273 (wpa_s->last_eapol_matches_bssid &&
5274#ifdef CONFIG_AP
5275 !wpa_s->ap_iface &&
5276#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005277 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005278 /*
5279 * There is possible race condition between receiving the
5280 * association event and the EAPOL frame since they are coming
5281 * through different paths from the driver. In order to avoid
5282 * issues in trying to process the EAPOL frame before receiving
5283 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005284 * the association event is received. This may also be needed in
5285 * driver-based roaming case, so also use src_addr != BSSID as a
5286 * trigger if we have previously confirmed that the
5287 * Authenticator uses BSSID as the src_addr (which is not the
5288 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005289 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005290 wpa_dbg(wpa_s, MSG_DEBUG,
5291 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5292 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005293 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005294 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005295 wpabuf_free(wpa_s->pending_eapol_rx);
5296 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5297 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005298 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005299 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5300 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005301 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005302 }
5303 return;
5304 }
5305
Jouni Malinena05074c2012-12-21 21:35:35 +02005306 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005307 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005309#ifdef CONFIG_AP
5310 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005311 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5312 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005313 return;
5314 }
5315#endif /* CONFIG_AP */
5316
5317 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5318 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5319 "no key management is configured");
5320 return;
5321 }
5322
5323 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005324 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005325 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5326 wpa_s->wpa_state != WPA_COMPLETED) &&
5327 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005328 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005330 int timeout = 10;
5331
5332 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5333 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5334 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5335 /* Use longer timeout for IEEE 802.1X/EAP */
5336 timeout = 70;
5337 }
5338
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005339#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005340 if (wpa_s->current_ssid && wpa_s->current_bss &&
5341 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5342 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5343 /*
5344 * Use shorter timeout if going through WPS AP iteration
5345 * for PIN config method with an AP that does not
5346 * advertise Selected Registrar.
5347 */
5348 struct wpabuf *wps_ie;
5349
5350 wps_ie = wpa_bss_get_vendor_ie_multi(
5351 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5352 if (wps_ie &&
5353 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5354 timeout = 10;
5355 wpabuf_free(wps_ie);
5356 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005357#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005358
5359 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 }
5361 wpa_s->eapol_received++;
5362
5363 if (wpa_s->countermeasures) {
5364 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5365 "EAPOL packet");
5366 return;
5367 }
5368
5369#ifdef CONFIG_IBSS_RSN
5370 if (wpa_s->current_ssid &&
5371 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005372 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5373 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005374 return;
5375 }
5376#endif /* CONFIG_IBSS_RSN */
5377
5378 /* Source address of the incoming EAPOL frame could be compared to the
5379 * current BSSID. However, it is possible that a centralized
5380 * Authenticator could be using another MAC address than the BSSID of
5381 * an AP, so just allow any address to be used for now. The replies are
5382 * still sent to the current BSSID (if available), though. */
5383
5384 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5385 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005386 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5387 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005388 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5389 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005390 return;
5391 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005392 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005393 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005394 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5395 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005396 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005397 * handshake processing which would normally set portValid. We
5398 * need this to allow the EAPOL state machines to be completed
5399 * without going through EAPOL-Key handshake.
5400 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005401 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005402 }
5403}
5404
5405
Sunil8cd6f4d2022-06-28 18:40:46 +00005406static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5407 const u8 *buf, size_t len)
5408{
5409 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5410 FRAME_ENCRYPTION_UNKNOWN);
5411}
5412
5413
Hai Shalomb755a2a2020-04-23 21:49:02 -07005414static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5415{
5416 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5417 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5418}
5419
5420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005421int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005422{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005423 u8 prev_mac_addr[ETH_ALEN];
5424
5425 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5426
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005427 if ((!wpa_s->p2p_mgmt ||
5428 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5429 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005430 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5432 wpa_drv_get_mac_addr(wpa_s),
5433 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005434 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005435 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005436 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005437 if (wpa_s->l2 == NULL)
5438 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005439
5440 if (l2_packet_set_packet_filter(wpa_s->l2,
5441 L2_PACKET_FILTER_PKTTYPE))
5442 wpa_dbg(wpa_s, MSG_DEBUG,
5443 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005444
5445 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5446 wpa_msg(wpa_s, MSG_ERROR,
5447 "Failed to get own L2 address");
5448 return -1;
5449 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005450 } else {
5451 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5452 if (addr)
5453 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5454 }
5455
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005456 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005457 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005458
Hai Shalomc3565922019-10-28 11:58:20 -07005459#ifdef CONFIG_FST
5460 if (wpa_s->fst)
5461 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5462#endif /* CONFIG_FST */
5463
Sunil Ravi77d572f2023-01-17 23:58:31 +00005464 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5465 wpas_notify_mac_address_changed(wpa_s);
5466
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005467 return 0;
5468}
5469
5470
Dmitry Shmidt04949592012-07-19 12:16:46 -07005471static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5472 const u8 *buf, size_t len)
5473{
5474 struct wpa_supplicant *wpa_s = ctx;
5475 const struct l2_ethhdr *eth;
5476
5477 if (len < sizeof(*eth))
5478 return;
5479 eth = (const struct l2_ethhdr *) buf;
5480
5481 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5482 !(eth->h_dest[0] & 0x01)) {
5483 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5484 " (bridge - not for this interface - ignore)",
5485 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5486 return;
5487 }
5488
5489 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5490 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5491 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005492 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005493}
5494
5495
Hai Shalom899fcc72020-10-19 14:38:18 -07005496int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5497 const char *bridge_ifname)
5498{
5499 if (wpa_s->wpa_state > WPA_SCANNING)
5500 return -EBUSY;
5501
5502 if (bridge_ifname &&
5503 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5504 return -EINVAL;
5505
5506 if (!bridge_ifname)
5507 bridge_ifname = "";
5508
5509 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5510 return 0;
5511
5512 if (wpa_s->l2_br) {
5513 l2_packet_deinit(wpa_s->l2_br);
5514 wpa_s->l2_br = NULL;
5515 }
5516
5517 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5518 sizeof(wpa_s->bridge_ifname));
5519
5520 if (wpa_s->bridge_ifname[0]) {
5521 wpa_dbg(wpa_s, MSG_DEBUG,
5522 "Receiving packets from bridge interface '%s'",
5523 wpa_s->bridge_ifname);
5524 wpa_s->l2_br = l2_packet_init_bridge(
5525 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5526 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5527 if (!wpa_s->l2_br) {
5528 wpa_msg(wpa_s, MSG_ERROR,
5529 "Failed to open l2_packet connection for the bridge interface '%s'",
5530 wpa_s->bridge_ifname);
5531 goto fail;
5532 }
5533 }
5534
5535#ifdef CONFIG_TDLS
5536 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5537 goto fail;
5538#endif /* CONFIG_TDLS */
5539
5540 return 0;
5541fail:
5542 wpa_s->bridge_ifname[0] = 0;
5543 if (wpa_s->l2_br) {
5544 l2_packet_deinit(wpa_s->l2_br);
5545 wpa_s->l2_br = NULL;
5546 }
5547#ifdef CONFIG_TDLS
5548 if (!wpa_s->p2p_mgmt)
5549 wpa_tdls_init(wpa_s->wpa);
5550#endif /* CONFIG_TDLS */
5551 return -EIO;
5552}
5553
5554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005555/**
5556 * wpa_supplicant_driver_init - Initialize driver interface parameters
5557 * @wpa_s: Pointer to wpa_supplicant data
5558 * Returns: 0 on success, -1 on failure
5559 *
5560 * This function is called to initialize driver interface parameters.
5561 * wpa_drv_init() must have been called before this function to initialize the
5562 * driver interface.
5563 */
5564int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5565{
5566 static int interface_count = 0;
5567
5568 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5569 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005570
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005571 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5572 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005573 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005574 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5575
Hai Shalomb755a2a2020-04-23 21:49:02 -07005576 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005577 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5578 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005579 wpa_s->l2_br = l2_packet_init_bridge(
5580 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5581 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005582 if (wpa_s->l2_br == NULL) {
5583 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5584 "connection for the bridge interface '%s'",
5585 wpa_s->bridge_ifname);
5586 return -1;
5587 }
5588 }
5589
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005590 if (wpa_s->conf->ap_scan == 2 &&
5591 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5592 wpa_printf(MSG_INFO,
5593 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5594 }
5595
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005596 wpa_clear_keys(wpa_s, NULL);
5597
5598 /* Make sure that TKIP countermeasures are not left enabled (could
5599 * happen if wpa_supplicant is killed during countermeasures. */
5600 wpa_drv_set_countermeasures(wpa_s, 0);
5601
5602 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5603 wpa_drv_flush_pmkid(wpa_s);
5604
5605 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005606 wpa_s->prev_scan_wildcard = 0;
5607
Dmitry Shmidt04949592012-07-19 12:16:46 -07005608 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005609 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5610 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5611 interface_count = 0;
5612 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005613#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005614 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005615 wpa_supplicant_delayed_sched_scan(wpa_s,
5616 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005617 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005618 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005619 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005620#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005621 interface_count++;
5622 } else
5623 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5624
5625 return 0;
5626}
5627
5628
5629static int wpa_supplicant_daemon(const char *pid_file)
5630{
5631 wpa_printf(MSG_DEBUG, "Daemonize..");
5632 return os_daemonize(pid_file);
5633}
5634
5635
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005636static struct wpa_supplicant *
5637wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005638{
5639 struct wpa_supplicant *wpa_s;
5640
5641 wpa_s = os_zalloc(sizeof(*wpa_s));
5642 if (wpa_s == NULL)
5643 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005644 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645 wpa_s->scan_interval = 5;
5646 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005647 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005648 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005649 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005650 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005651
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005652 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005653 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005654#ifdef CONFIG_TESTING_OPTIONS
5655 dl_list_init(&wpa_s->drv_signal_override);
5656#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005657 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005659 return wpa_s;
5660}
5661
5662
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005663#ifdef CONFIG_HT_OVERRIDES
5664
5665static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5666 struct ieee80211_ht_capabilities *htcaps,
5667 struct ieee80211_ht_capabilities *htcaps_mask,
5668 const char *ht_mcs)
5669{
5670 /* parse ht_mcs into hex array */
5671 int i;
5672 const char *tmp = ht_mcs;
5673 char *end = NULL;
5674
5675 /* If ht_mcs is null, do not set anything */
5676 if (!ht_mcs)
5677 return 0;
5678
5679 /* This is what we are setting in the kernel */
5680 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5681
5682 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5683
5684 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005685 long v;
5686
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005687 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005688 v = strtol(tmp, &end, 16);
5689
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005690 if (errno == 0) {
5691 wpa_msg(wpa_s, MSG_DEBUG,
5692 "htcap value[%i]: %ld end: %p tmp: %p",
5693 i, v, end, tmp);
5694 if (end == tmp)
5695 break;
5696
5697 htcaps->supported_mcs_set[i] = v;
5698 tmp = end;
5699 } else {
5700 wpa_msg(wpa_s, MSG_ERROR,
5701 "Failed to parse ht-mcs: %s, error: %s\n",
5702 ht_mcs, strerror(errno));
5703 return -1;
5704 }
5705 }
5706
5707 /*
5708 * If we were able to parse any values, then set mask for the MCS set.
5709 */
5710 if (i) {
5711 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5712 IEEE80211_HT_MCS_MASK_LEN - 1);
5713 /* skip the 3 reserved bits */
5714 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5715 0x1f;
5716 }
5717
5718 return 0;
5719}
5720
5721
5722static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5723 struct ieee80211_ht_capabilities *htcaps,
5724 struct ieee80211_ht_capabilities *htcaps_mask,
5725 int disabled)
5726{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005727 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005728
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005729 if (disabled == -1)
5730 return 0;
5731
Hai Shalom74f70d42019-02-11 14:42:39 -08005732 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5733
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005734 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5735 htcaps_mask->ht_capabilities_info |= msk;
5736 if (disabled)
5737 htcaps->ht_capabilities_info &= msk;
5738 else
5739 htcaps->ht_capabilities_info |= msk;
5740
5741 return 0;
5742}
5743
5744
5745static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5746 struct ieee80211_ht_capabilities *htcaps,
5747 struct ieee80211_ht_capabilities *htcaps_mask,
5748 int factor)
5749{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005750 if (factor == -1)
5751 return 0;
5752
Hai Shalom74f70d42019-02-11 14:42:39 -08005753 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5754
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005755 if (factor < 0 || factor > 3) {
5756 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5757 "Must be 0-3 or -1", factor);
5758 return -EINVAL;
5759 }
5760
5761 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5762 htcaps->a_mpdu_params &= ~0x3;
5763 htcaps->a_mpdu_params |= factor & 0x3;
5764
5765 return 0;
5766}
5767
5768
5769static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5770 struct ieee80211_ht_capabilities *htcaps,
5771 struct ieee80211_ht_capabilities *htcaps_mask,
5772 int density)
5773{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005774 if (density == -1)
5775 return 0;
5776
Hai Shalom74f70d42019-02-11 14:42:39 -08005777 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5778
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005779 if (density < 0 || density > 7) {
5780 wpa_msg(wpa_s, MSG_ERROR,
5781 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5782 density);
5783 return -EINVAL;
5784 }
5785
5786 htcaps_mask->a_mpdu_params |= 0x1C;
5787 htcaps->a_mpdu_params &= ~(0x1C);
5788 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5789
5790 return 0;
5791}
5792
5793
5794static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5795 struct ieee80211_ht_capabilities *htcaps,
5796 struct ieee80211_ht_capabilities *htcaps_mask,
5797 int disabled)
5798{
Hai Shalom74f70d42019-02-11 14:42:39 -08005799 if (disabled)
5800 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005801
Paul Stewart092955c2017-02-06 09:13:09 -08005802 set_disable_ht40(htcaps, disabled);
5803 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005804
5805 return 0;
5806}
5807
5808
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005809static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5810 struct ieee80211_ht_capabilities *htcaps,
5811 struct ieee80211_ht_capabilities *htcaps_mask,
5812 int disabled)
5813{
5814 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005815 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5816 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005817
Hai Shalom74f70d42019-02-11 14:42:39 -08005818 if (disabled)
5819 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005820
5821 if (disabled)
5822 htcaps->ht_capabilities_info &= ~msk;
5823 else
5824 htcaps->ht_capabilities_info |= msk;
5825
5826 htcaps_mask->ht_capabilities_info |= msk;
5827
5828 return 0;
5829}
5830
5831
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005832static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5833 struct ieee80211_ht_capabilities *htcaps,
5834 struct ieee80211_ht_capabilities *htcaps_mask,
5835 int disabled)
5836{
5837 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005838 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005839
Hai Shalom74f70d42019-02-11 14:42:39 -08005840 if (disabled)
5841 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005842
5843 if (disabled)
5844 htcaps->ht_capabilities_info &= ~msk;
5845 else
5846 htcaps->ht_capabilities_info |= msk;
5847
5848 htcaps_mask->ht_capabilities_info |= msk;
5849
5850 return 0;
5851}
5852
5853
Hai Shalom74f70d42019-02-11 14:42:39 -08005854static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5855 struct ieee80211_ht_capabilities *htcaps,
5856 struct ieee80211_ht_capabilities *htcaps_mask,
5857 int tx_stbc)
5858{
5859 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5860
5861 if (tx_stbc == -1)
5862 return 0;
5863
5864 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5865
5866 if (tx_stbc < 0 || tx_stbc > 1) {
5867 wpa_msg(wpa_s, MSG_ERROR,
5868 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5869 return -EINVAL;
5870 }
5871
5872 htcaps_mask->ht_capabilities_info |= msk;
5873 htcaps->ht_capabilities_info &= ~msk;
5874 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5875
5876 return 0;
5877}
5878
5879
5880static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5881 struct ieee80211_ht_capabilities *htcaps,
5882 struct ieee80211_ht_capabilities *htcaps_mask,
5883 int rx_stbc)
5884{
5885 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5886
5887 if (rx_stbc == -1)
5888 return 0;
5889
5890 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5891
5892 if (rx_stbc < 0 || rx_stbc > 3) {
5893 wpa_msg(wpa_s, MSG_ERROR,
5894 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5895 return -EINVAL;
5896 }
5897
5898 htcaps_mask->ht_capabilities_info |= msk;
5899 htcaps->ht_capabilities_info &= ~msk;
5900 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5901
5902 return 0;
5903}
5904
5905
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005906void wpa_supplicant_apply_ht_overrides(
5907 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5908 struct wpa_driver_associate_params *params)
5909{
5910 struct ieee80211_ht_capabilities *htcaps;
5911 struct ieee80211_ht_capabilities *htcaps_mask;
5912
5913 if (!ssid)
5914 return;
5915
5916 params->disable_ht = ssid->disable_ht;
5917 if (!params->htcaps || !params->htcaps_mask)
5918 return;
5919
5920 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5921 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5922 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5923 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5924 ssid->disable_max_amsdu);
5925 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5926 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5927 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005928 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005929 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005930 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5931 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005932
5933 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005934 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005935 htcaps->ht_capabilities_info |= bit;
5936 htcaps_mask->ht_capabilities_info |= bit;
5937 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005938}
5939
5940#endif /* CONFIG_HT_OVERRIDES */
5941
5942
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005943#ifdef CONFIG_VHT_OVERRIDES
5944void wpa_supplicant_apply_vht_overrides(
5945 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5946 struct wpa_driver_associate_params *params)
5947{
5948 struct ieee80211_vht_capabilities *vhtcaps;
5949 struct ieee80211_vht_capabilities *vhtcaps_mask;
5950
5951 if (!ssid)
5952 return;
5953
5954 params->disable_vht = ssid->disable_vht;
5955
5956 vhtcaps = (void *) params->vhtcaps;
5957 vhtcaps_mask = (void *) params->vhtcaps_mask;
5958
5959 if (!vhtcaps || !vhtcaps_mask)
5960 return;
5961
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005962 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5963 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005964
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005965#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005966 if (ssid->disable_sgi) {
5967 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5968 VHT_CAP_SHORT_GI_160);
5969 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5970 VHT_CAP_SHORT_GI_160);
5971 wpa_msg(wpa_s, MSG_DEBUG,
5972 "disable-sgi override specified, vht-caps: 0x%x",
5973 vhtcaps->vht_capabilities_info);
5974 }
5975
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005976 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005977 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5978 int max_ampdu;
5979
5980 max_ampdu = (ssid->vht_capa &
5981 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5982 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005983
5984 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5985 wpa_set_ampdu_factor(wpa_s,
5986 (void *) params->htcaps,
5987 (void *) params->htcaps_mask,
5988 max_ampdu);
5989 }
5990#endif /* CONFIG_HT_OVERRIDES */
5991
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005992#define OVERRIDE_MCS(i) \
5993 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5994 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005995 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005996 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005997 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5998 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005999 } \
6000 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6001 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006002 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006003 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006004 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6005 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006006 }
6007
6008 OVERRIDE_MCS(1);
6009 OVERRIDE_MCS(2);
6010 OVERRIDE_MCS(3);
6011 OVERRIDE_MCS(4);
6012 OVERRIDE_MCS(5);
6013 OVERRIDE_MCS(6);
6014 OVERRIDE_MCS(7);
6015 OVERRIDE_MCS(8);
6016}
6017#endif /* CONFIG_VHT_OVERRIDES */
6018
6019
Hai Shalomfdcde762020-04-02 11:19:20 -07006020#ifdef CONFIG_HE_OVERRIDES
6021void wpa_supplicant_apply_he_overrides(
6022 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6023 struct wpa_driver_associate_params *params)
6024{
6025 if (!ssid)
6026 return;
6027
6028 params->disable_he = ssid->disable_he;
6029}
6030#endif /* CONFIG_HE_OVERRIDES */
6031
6032
Sunil Ravi77d572f2023-01-17 23:58:31 +00006033void wpa_supplicant_apply_eht_overrides(
6034 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6035 struct wpa_driver_associate_params *params)
6036{
6037 if (!ssid)
6038 return;
6039
6040 params->disable_eht = ssid->disable_eht;
6041}
6042
6043
Dmitry Shmidt04949592012-07-19 12:16:46 -07006044static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6045{
6046#ifdef PCSC_FUNCS
6047 size_t len;
6048
6049 if (!wpa_s->conf->pcsc_reader)
6050 return 0;
6051
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006052 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006053 if (!wpa_s->scard)
6054 return 1;
6055
6056 if (wpa_s->conf->pcsc_pin &&
6057 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6058 scard_deinit(wpa_s->scard);
6059 wpa_s->scard = NULL;
6060 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6061 return -1;
6062 }
6063
6064 len = sizeof(wpa_s->imsi) - 1;
6065 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6066 scard_deinit(wpa_s->scard);
6067 wpa_s->scard = NULL;
6068 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6069 return -1;
6070 }
6071 wpa_s->imsi[len] = '\0';
6072
6073 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6074
6075 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6076 wpa_s->imsi, wpa_s->mnc_len);
6077
6078 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6079 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6080#endif /* PCSC_FUNCS */
6081
6082 return 0;
6083}
6084
6085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006086int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6087{
6088 char *val, *pos;
6089
6090 ext_password_deinit(wpa_s->ext_pw);
6091 wpa_s->ext_pw = NULL;
6092 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6093
6094 if (!wpa_s->conf->ext_password_backend)
6095 return 0;
6096
6097 val = os_strdup(wpa_s->conf->ext_password_backend);
6098 if (val == NULL)
6099 return -1;
6100 pos = os_strchr(val, ':');
6101 if (pos)
6102 *pos++ = '\0';
6103
6104 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6105
6106 wpa_s->ext_pw = ext_password_init(val, pos);
6107 os_free(val);
6108 if (wpa_s->ext_pw == NULL) {
6109 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6110 return -1;
6111 }
6112 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6113
6114 return 0;
6115}
6116
6117
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006118#ifdef CONFIG_FST
6119
6120static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6121{
6122 struct wpa_supplicant *wpa_s = ctx;
6123
6124 return (is_zero_ether_addr(wpa_s->bssid) ||
6125 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6126}
6127
6128
6129static void wpas_fst_get_channel_info_cb(void *ctx,
6130 enum hostapd_hw_mode *hw_mode,
6131 u8 *channel)
6132{
6133 struct wpa_supplicant *wpa_s = ctx;
6134
6135 if (wpa_s->current_bss) {
6136 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6137 channel);
6138 } else if (wpa_s->hw.num_modes) {
6139 *hw_mode = wpa_s->hw.modes[0].mode;
6140 } else {
6141 WPA_ASSERT(0);
6142 *hw_mode = 0;
6143 }
6144}
6145
6146
6147static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6148{
6149 struct wpa_supplicant *wpa_s = ctx;
6150
6151 *modes = wpa_s->hw.modes;
6152 return wpa_s->hw.num_modes;
6153}
6154
6155
6156static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6157{
6158 struct wpa_supplicant *wpa_s = ctx;
6159
6160 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6161 wpa_s->fst_ies = fst_ies;
6162}
6163
6164
6165static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6166{
6167 struct wpa_supplicant *wpa_s = ctx;
6168
Paul Stewart092955c2017-02-06 09:13:09 -08006169 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6170 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6171 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6172 return -1;
6173 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006174 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006175 wpa_s->own_addr, wpa_s->bssid,
6176 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006177 0);
6178}
6179
6180
6181static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6182{
6183 struct wpa_supplicant *wpa_s = ctx;
6184
6185 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6186 return wpa_s->received_mb_ies;
6187}
6188
6189
6190static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6191 const u8 *buf, size_t size)
6192{
6193 struct wpa_supplicant *wpa_s = ctx;
6194 struct mb_ies_info info;
6195
6196 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6197
6198 if (!mb_ies_info_by_ies(&info, buf, size)) {
6199 wpabuf_free(wpa_s->received_mb_ies);
6200 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6201 }
6202}
6203
6204
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006205static const u8 * wpas_fst_get_peer_first(void *ctx,
6206 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006207 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006208{
6209 struct wpa_supplicant *wpa_s = ctx;
6210
6211 *get_ctx = NULL;
6212 if (!is_zero_ether_addr(wpa_s->bssid))
6213 return (wpa_s->received_mb_ies || !mb_only) ?
6214 wpa_s->bssid : NULL;
6215 return NULL;
6216}
6217
6218
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006219static const u8 * wpas_fst_get_peer_next(void *ctx,
6220 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006221 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006222{
6223 return NULL;
6224}
6225
6226void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6227 struct fst_wpa_obj *iface_obj)
6228{
Sunil8cd6f4d2022-06-28 18:40:46 +00006229 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006230 iface_obj->ctx = wpa_s;
6231 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6232 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6233 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6234 iface_obj->set_ies = wpas_fst_set_ies_cb;
6235 iface_obj->send_action = wpas_fst_send_action_cb;
6236 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6237 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6238 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6239 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6240}
6241#endif /* CONFIG_FST */
6242
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006243static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006244 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006245{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006246 struct wowlan_triggers *triggers;
6247 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006248
6249 if (!wpa_s->conf->wowlan_triggers)
6250 return 0;
6251
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006252 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6253 if (triggers) {
6254 ret = wpa_drv_wowlan(wpa_s, triggers);
6255 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006256 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006257 return ret;
6258}
6259
6260
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006261enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006262{
6263 if (freq < 3000)
6264 return BAND_2_4_GHZ;
6265 if (freq > 50000)
6266 return BAND_60_GHZ;
6267 return BAND_5_GHZ;
6268}
6269
6270
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006271unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006272{
6273 int i;
6274 unsigned int band = 0;
6275
6276 if (freqs) {
6277 /* freqs are specified for the radio work */
6278 for (i = 0; freqs[i]; i++)
6279 band |= wpas_freq_to_band(freqs[i]);
6280 } else {
6281 /*
6282 * freqs are not specified, implies all
6283 * the supported freqs by HW
6284 */
6285 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6286 if (wpa_s->hw.modes[i].num_channels != 0) {
6287 if (wpa_s->hw.modes[i].mode ==
6288 HOSTAPD_MODE_IEEE80211B ||
6289 wpa_s->hw.modes[i].mode ==
6290 HOSTAPD_MODE_IEEE80211G)
6291 band |= BAND_2_4_GHZ;
6292 else if (wpa_s->hw.modes[i].mode ==
6293 HOSTAPD_MODE_IEEE80211A)
6294 band |= BAND_5_GHZ;
6295 else if (wpa_s->hw.modes[i].mode ==
6296 HOSTAPD_MODE_IEEE80211AD)
6297 band |= BAND_60_GHZ;
6298 else if (wpa_s->hw.modes[i].mode ==
6299 HOSTAPD_MODE_IEEE80211ANY)
6300 band = BAND_2_4_GHZ | BAND_5_GHZ |
6301 BAND_60_GHZ;
6302 }
6303 }
6304 }
6305
6306 return band;
6307}
6308
6309
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006310static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6311 const char *rn)
6312{
6313 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6314 struct wpa_radio *radio;
6315
6316 while (rn && iface) {
6317 radio = iface->radio;
6318 if (radio && os_strcmp(rn, radio->name) == 0) {
6319 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6320 wpa_s->ifname, rn);
6321 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6322 return radio;
6323 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006324
6325 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006326 }
6327
6328 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6329 wpa_s->ifname, rn ? rn : "N/A");
6330 radio = os_zalloc(sizeof(*radio));
6331 if (radio == NULL)
6332 return NULL;
6333
6334 if (rn)
6335 os_strlcpy(radio->name, rn, sizeof(radio->name));
6336 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006337 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006338 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6339
6340 return radio;
6341}
6342
6343
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006344static void radio_work_free(struct wpa_radio_work *work)
6345{
6346 if (work->wpa_s->scan_work == work) {
6347 /* This should not really happen. */
6348 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6349 work->type, work, work->started);
6350 work->wpa_s->scan_work = NULL;
6351 }
6352
6353#ifdef CONFIG_P2P
6354 if (work->wpa_s->p2p_scan_work == work) {
6355 /* This should not really happen. */
6356 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6357 work->type, work, work->started);
6358 work->wpa_s->p2p_scan_work = NULL;
6359 }
6360#endif /* CONFIG_P2P */
6361
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006362 if (work->started) {
6363 work->wpa_s->radio->num_active_works--;
6364 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006365 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006366 work->type, work,
6367 work->wpa_s->radio->num_active_works);
6368 }
6369
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006370 dl_list_del(&work->list);
6371 os_free(work);
6372}
6373
6374
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006375static int radio_work_is_connect(struct wpa_radio_work *work)
6376{
6377 return os_strcmp(work->type, "sme-connect") == 0 ||
6378 os_strcmp(work->type, "connect") == 0;
6379}
6380
6381
6382static int radio_work_is_scan(struct wpa_radio_work *work)
6383{
6384 return os_strcmp(work->type, "scan") == 0 ||
6385 os_strcmp(work->type, "p2p-scan") == 0;
6386}
6387
6388
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006389static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6390{
6391 struct wpa_radio_work *active_work = NULL;
6392 struct wpa_radio_work *tmp;
6393
6394 /* Get the active work to know the type and band. */
6395 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6396 if (tmp->started) {
6397 active_work = tmp;
6398 break;
6399 }
6400 }
6401
6402 if (!active_work) {
6403 /* No active work, start one */
6404 radio->num_active_works = 0;
6405 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6406 list) {
6407 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006408 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006409 (((struct wpa_driver_scan_params *)
6410 tmp->ctx)->only_new_results ||
6411 tmp->wpa_s->clear_driver_scan_cache))
6412 continue;
6413 return tmp;
6414 }
6415 return NULL;
6416 }
6417
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006418 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006419 /*
6420 * If the active work is either connect or sme-connect,
6421 * do not parallelize them with other radio works.
6422 */
6423 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6424 "Do not parallelize radio work with %s",
6425 active_work->type);
6426 return NULL;
6427 }
6428
6429 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6430 if (tmp->started)
6431 continue;
6432
6433 /*
6434 * If connect or sme-connect are enqueued, parallelize only
6435 * those operations ahead of them in the queue.
6436 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006437 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006438 break;
6439
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006440 /* Serialize parallel scan and p2p_scan operations on the same
6441 * interface since the driver_nl80211 mechanism for tracking
6442 * scan cookies does not yet have support for this. */
6443 if (active_work->wpa_s == tmp->wpa_s &&
6444 radio_work_is_scan(active_work) &&
6445 radio_work_is_scan(tmp)) {
6446 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6447 "Do not start work '%s' when another work '%s' is already scheduled",
6448 tmp->type, active_work->type);
6449 continue;
6450 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006451 /*
6452 * Check that the radio works are distinct and
6453 * on different bands.
6454 */
6455 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6456 (active_work->bands != tmp->bands)) {
6457 /*
6458 * If a scan has to be scheduled through nl80211 scan
6459 * interface and if an external scan is already running,
6460 * do not schedule the scan since it is likely to get
6461 * rejected by kernel.
6462 */
6463 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006464 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006465 (((struct wpa_driver_scan_params *)
6466 tmp->ctx)->only_new_results ||
6467 tmp->wpa_s->clear_driver_scan_cache))
6468 continue;
6469
6470 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6471 "active_work:%s new_work:%s",
6472 active_work->type, tmp->type);
6473 return tmp;
6474 }
6475 }
6476
6477 /* Did not find a radio work to schedule in parallel. */
6478 return NULL;
6479}
6480
6481
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006482static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6483{
6484 struct wpa_radio *radio = eloop_ctx;
6485 struct wpa_radio_work *work;
6486 struct os_reltime now, diff;
6487 struct wpa_supplicant *wpa_s;
6488
6489 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006490 if (work == NULL) {
6491 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006492 return;
6493 }
6494
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006495 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6496 radio_list);
6497
6498 if (!(wpa_s &&
6499 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6500 if (work->started)
6501 return; /* already started and still in progress */
6502
Hai Shalom60840252021-02-19 19:02:11 -08006503 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006504 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6505 return;
6506 }
6507 } else {
6508 work = NULL;
6509 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6510 /* get the work to schedule next */
6511 work = radio_work_get_next_work(radio);
6512 }
6513 if (!work)
6514 return;
6515 }
6516
6517 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006518 os_get_reltime(&now);
6519 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006520 wpa_dbg(wpa_s, MSG_DEBUG,
6521 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006522 work->type, work, diff.sec, diff.usec);
6523 work->started = 1;
6524 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006525 radio->num_active_works++;
6526
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006527 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006528
6529 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6530 radio->num_active_works < MAX_ACTIVE_WORKS)
6531 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006532}
6533
6534
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006535/*
6536 * This function removes both started and pending radio works running on
6537 * the provided interface's radio.
6538 * Prior to the removal of the radio work, its callback (cb) is called with
6539 * deinit set to be 1. Each work's callback is responsible for clearing its
6540 * internal data and restoring to a correct state.
6541 * @wpa_s: wpa_supplicant data
6542 * @type: type of works to be removed
6543 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6544 * this interface's works.
6545 */
6546void radio_remove_works(struct wpa_supplicant *wpa_s,
6547 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006548{
6549 struct wpa_radio_work *work, *tmp;
6550 struct wpa_radio *radio = wpa_s->radio;
6551
6552 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6553 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006554 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006555 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006556
6557 /* skip other ifaces' works */
6558 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006559 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006560
6561 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6562 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006563 work->cb(work, 1);
6564 radio_work_free(work);
6565 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006566
6567 /* in case we removed the started work */
6568 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006569}
6570
6571
Roshan Pius3a1667e2018-07-03 15:17:14 -07006572void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6573{
6574 struct wpa_radio_work *work;
6575 struct wpa_radio *radio = wpa_s->radio;
6576
6577 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6578 if (work->ctx != ctx)
6579 continue;
6580 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6581 work->type, work, work->started ? " (started)" : "");
6582 radio_work_free(work);
6583 break;
6584 }
6585}
6586
6587
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006588static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6589{
6590 struct wpa_radio *radio = wpa_s->radio;
6591
6592 if (!radio)
6593 return;
6594
6595 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6596 wpa_s->ifname, radio->name);
6597 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006598 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006599 /* If the interface that triggered the external scan was removed, the
6600 * external scan is no longer running. */
6601 if (wpa_s == radio->external_scan_req_interface)
6602 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006603 wpa_s->radio = NULL;
6604 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006605 return; /* Interfaces remain for this radio */
6606
6607 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006608 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006609 os_free(radio);
6610}
6611
6612
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006613void radio_work_check_next(struct wpa_supplicant *wpa_s)
6614{
6615 struct wpa_radio *radio = wpa_s->radio;
6616
6617 if (dl_list_empty(&radio->work))
6618 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006619 if (wpa_s->ext_work_in_progress) {
6620 wpa_printf(MSG_DEBUG,
6621 "External radio work in progress - delay start of pending item");
6622 return;
6623 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006624 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6625 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6626}
6627
6628
6629/**
6630 * radio_add_work - Add a radio work item
6631 * @wpa_s: Pointer to wpa_supplicant data
6632 * @freq: Frequency of the offchannel operation in MHz or 0
6633 * @type: Unique identifier for each type of work
6634 * @next: Force as the next work to be executed
6635 * @cb: Callback function for indicating when radio is available
6636 * @ctx: Context pointer for the work (work->ctx in cb())
6637 * Returns: 0 on success, -1 on failure
6638 *
6639 * This function is used to request time for an operation that requires
6640 * exclusive radio control. Once the radio is available, the registered callback
6641 * function will be called. radio_work_done() must be called once the exclusive
6642 * radio operation has been completed, so that the radio is freed for other
6643 * operations. The special case of deinit=1 is used to free the context data
6644 * during interface removal. That does not allow the callback function to start
6645 * the radio operation, i.e., it must free any resources allocated for the radio
6646 * work and return.
6647 *
6648 * The @freq parameter can be used to indicate a single channel on which the
6649 * offchannel operation will occur. This may allow multiple radio work
6650 * operations to be performed in parallel if they apply for the same channel.
6651 * Setting this to 0 indicates that the work item may use multiple channels or
6652 * requires exclusive control of the radio.
6653 */
6654int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6655 const char *type, int next,
6656 void (*cb)(struct wpa_radio_work *work, int deinit),
6657 void *ctx)
6658{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006659 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006660 struct wpa_radio_work *work;
6661 int was_empty;
6662
6663 work = os_zalloc(sizeof(*work));
6664 if (work == NULL)
6665 return -1;
6666 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6667 os_get_reltime(&work->time);
6668 work->freq = freq;
6669 work->type = type;
6670 work->wpa_s = wpa_s;
6671 work->cb = cb;
6672 work->ctx = ctx;
6673
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006674 if (freq)
6675 work->bands = wpas_freq_to_band(freq);
6676 else if (os_strcmp(type, "scan") == 0 ||
6677 os_strcmp(type, "p2p-scan") == 0)
6678 work->bands = wpas_get_bands(wpa_s,
6679 ((struct wpa_driver_scan_params *)
6680 ctx)->freqs);
6681 else
6682 work->bands = wpas_get_bands(wpa_s, NULL);
6683
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006684 was_empty = dl_list_empty(&wpa_s->radio->work);
6685 if (next)
6686 dl_list_add(&wpa_s->radio->work, &work->list);
6687 else
6688 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6689 if (was_empty) {
6690 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6691 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006692 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6693 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6694 wpa_dbg(wpa_s, MSG_DEBUG,
6695 "Try to schedule a radio work (num_active_works=%u)",
6696 radio->num_active_works);
6697 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006698 }
6699
6700 return 0;
6701}
6702
6703
6704/**
6705 * radio_work_done - Indicate that a radio work item has been completed
6706 * @work: Completed work
6707 *
6708 * This function is called once the callback function registered with
6709 * radio_add_work() has completed its work.
6710 */
6711void radio_work_done(struct wpa_radio_work *work)
6712{
6713 struct wpa_supplicant *wpa_s = work->wpa_s;
6714 struct os_reltime now, diff;
6715 unsigned int started = work->started;
6716
6717 os_get_reltime(&now);
6718 os_reltime_sub(&now, &work->time, &diff);
6719 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6720 work->type, work, started ? "done" : "canceled",
6721 diff.sec, diff.usec);
6722 radio_work_free(work);
6723 if (started)
6724 radio_work_check_next(wpa_s);
6725}
6726
6727
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006728struct wpa_radio_work *
6729radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006730{
6731 struct wpa_radio_work *work;
6732 struct wpa_radio *radio = wpa_s->radio;
6733
6734 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6735 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006736 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006737 }
6738
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006739 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006740}
6741
6742
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006743static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006744 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006745{
6746 const char *ifname, *driver, *rn;
6747
6748 driver = iface->driver;
6749next_driver:
6750 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6751 return -1;
6752
6753 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6754 if (wpa_s->drv_priv == NULL) {
6755 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006756 int level = MSG_ERROR;
6757
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006758 pos = driver ? os_strchr(driver, ',') : NULL;
6759 if (pos) {
6760 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6761 "driver interface - try next driver wrapper");
6762 driver = pos + 1;
6763 goto next_driver;
6764 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006765
6766#ifdef CONFIG_MATCH_IFACE
6767 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6768 level = MSG_DEBUG;
6769#endif /* CONFIG_MATCH_IFACE */
6770 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006771 return -1;
6772 }
6773 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6774 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6775 "driver_param '%s'", wpa_s->conf->driver_param);
6776 return -1;
6777 }
6778
6779 ifname = wpa_drv_get_ifname(wpa_s);
6780 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6781 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6782 "interface name with '%s'", ifname);
6783 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6784 }
6785
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006786 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006787 if (rn && rn[0] == '\0')
6788 rn = NULL;
6789
6790 wpa_s->radio = radio_add_interface(wpa_s, rn);
6791 if (wpa_s->radio == NULL)
6792 return -1;
6793
6794 return 0;
6795}
6796
6797
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006798#ifdef CONFIG_GAS_SERVER
6799
6800static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6801 unsigned int freq, const u8 *dst,
6802 const u8 *src, const u8 *bssid,
6803 const u8 *data, size_t data_len,
6804 enum offchannel_send_action_result result)
6805{
6806 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6807 " result=%s",
6808 freq, MAC2STR(dst),
6809 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6810 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6811 "FAILED"));
6812 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6813 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6814}
6815
6816
6817static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6818 struct wpabuf *buf, unsigned int wait_time)
6819{
6820 struct wpa_supplicant *wpa_s = ctx;
6821 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6822
6823 if (wait_time > wpa_s->max_remain_on_chan)
6824 wait_time = wpa_s->max_remain_on_chan;
6825
6826 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6827 wpabuf_head(buf), wpabuf_len(buf),
6828 wait_time, wpas_gas_server_tx_status, 0);
6829}
6830
6831#endif /* CONFIG_GAS_SERVER */
6832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006833static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006834 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006835{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006836 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006837 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006838 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006839
6840 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6841 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6842 iface->confname ? iface->confname : "N/A",
6843 iface->driver ? iface->driver : "default",
6844 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6845 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6846
6847 if (iface->confname) {
6848#ifdef CONFIG_BACKEND_FILE
6849 wpa_s->confname = os_rel2abs_path(iface->confname);
6850 if (wpa_s->confname == NULL) {
6851 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6852 "for configuration file '%s'.",
6853 iface->confname);
6854 return -1;
6855 }
6856 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6857 iface->confname, wpa_s->confname);
6858#else /* CONFIG_BACKEND_FILE */
6859 wpa_s->confname = os_strdup(iface->confname);
6860#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00006861 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006862 if (wpa_s->conf == NULL) {
6863 wpa_printf(MSG_ERROR, "Failed to read or parse "
6864 "configuration '%s'.", wpa_s->confname);
6865 return -1;
6866 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006867 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006868 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00006869 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006870 wpa_printf(MSG_ERROR,
6871 "Failed to read or parse configuration '%s'.",
6872 wpa_s->confanother);
6873 return -1;
6874 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875
6876 /*
6877 * Override ctrl_interface and driver_param if set on command
6878 * line.
6879 */
6880 if (iface->ctrl_interface) {
6881 os_free(wpa_s->conf->ctrl_interface);
6882 wpa_s->conf->ctrl_interface =
6883 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006884 if (!wpa_s->conf->ctrl_interface) {
6885 wpa_printf(MSG_ERROR,
6886 "Failed to duplicate control interface '%s'.",
6887 iface->ctrl_interface);
6888 return -1;
6889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006890 }
6891
6892 if (iface->driver_param) {
6893 os_free(wpa_s->conf->driver_param);
6894 wpa_s->conf->driver_param =
6895 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006896 if (!wpa_s->conf->driver_param) {
6897 wpa_printf(MSG_ERROR,
6898 "Failed to duplicate driver param '%s'.",
6899 iface->driver_param);
6900 return -1;
6901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006902 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006903
6904 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6905 os_free(wpa_s->conf->ctrl_interface);
6906 wpa_s->conf->ctrl_interface = NULL;
6907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006908 } else
6909 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6910 iface->driver_param);
6911
6912 if (wpa_s->conf == NULL) {
6913 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6914 return -1;
6915 }
6916
6917 if (iface->ifname == NULL) {
6918 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6919 return -1;
6920 }
6921 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6922 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6923 iface->ifname);
6924 return -1;
6925 }
6926 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006927#ifdef CONFIG_MATCH_IFACE
6928 wpa_s->matched = iface->matched;
6929#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006930
6931 if (iface->bridge_ifname) {
6932 if (os_strlen(iface->bridge_ifname) >=
6933 sizeof(wpa_s->bridge_ifname)) {
6934 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6935 "name '%s'.", iface->bridge_ifname);
6936 return -1;
6937 }
6938 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6939 sizeof(wpa_s->bridge_ifname));
6940 }
6941
6942 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006943 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6944 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006945
6946 /* Initialize driver interface and register driver event handler before
6947 * L2 receive handler so that association events are processed before
6948 * EAPOL-Key packets if both become available for the same select()
6949 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006950 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006951 return -1;
6952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006953 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6954 return -1;
6955
6956 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6957 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6958 NULL);
6959 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6960
6961 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6962 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6963 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6964 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6965 "dot11RSNAConfigPMKLifetime");
6966 return -1;
6967 }
6968
6969 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6970 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6971 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6972 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6973 "dot11RSNAConfigPMKReauthThreshold");
6974 return -1;
6975 }
6976
6977 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6978 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6979 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6980 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6981 "dot11RSNAConfigSATimeout");
6982 return -1;
6983 }
6984
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006985 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6986 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006987 &wpa_s->hw.flags,
6988 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006989 if (wpa_s->hw.modes) {
6990 u16 i;
6991
6992 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6993 if (wpa_s->hw.modes[i].vht_capab) {
6994 wpa_s->hw_capab = CAPAB_VHT;
6995 break;
6996 }
6997
6998 if (wpa_s->hw.modes[i].ht_capab &
6999 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7000 wpa_s->hw_capab = CAPAB_HT40;
7001 else if (wpa_s->hw.modes[i].ht_capab &&
7002 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7003 wpa_s->hw_capab = CAPAB_HT;
7004 }
7005 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007006
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007007 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7008 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007009 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007010 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007011 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007012 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007013 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007014 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007015 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007016 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007017 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007018 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7019 wpa_s->max_sched_scan_plan_interval =
7020 capa.max_sched_scan_plan_interval;
7021 wpa_s->max_sched_scan_plan_iterations =
7022 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007023 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7024 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007025 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7026 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007027 wpa_s->extended_capa = capa.extended_capa;
7028 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7029 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007030 wpa_s->num_multichan_concurrent =
7031 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007032 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007033 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007034
7035 if (capa.mac_addr_rand_scan_supported)
7036 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7037 if (wpa_s->sched_scan_supported &&
7038 capa.mac_addr_rand_sched_scan_supported)
7039 wpa_s->mac_addr_rand_supported |=
7040 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007041
7042 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7043 if (wpa_s->extended_capa &&
7044 wpa_s->extended_capa_len >= 3 &&
7045 wpa_s->extended_capa[2] & 0x40)
7046 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007048#ifdef CONFIG_PASN
7049 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7050#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007051 if (wpa_s->max_remain_on_chan == 0)
7052 wpa_s->max_remain_on_chan = 1000;
7053
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007054 /*
7055 * Only take p2p_mgmt parameters when P2P Device is supported.
7056 * Doing it here as it determines whether l2_packet_init() will be done
7057 * during wpa_supplicant_driver_init().
7058 */
7059 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7060 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007061
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007062 if (wpa_s->num_multichan_concurrent == 0)
7063 wpa_s->num_multichan_concurrent = 1;
7064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007065 if (wpa_supplicant_driver_init(wpa_s) < 0)
7066 return -1;
7067
7068#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007069 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007070 return -1;
7071#endif /* CONFIG_TDLS */
7072
7073 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7074 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7075 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7076 return -1;
7077 }
7078
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007079#ifdef CONFIG_FST
7080 if (wpa_s->conf->fst_group_id) {
7081 struct fst_iface_cfg cfg;
7082 struct fst_wpa_obj iface_obj;
7083
7084 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7085 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7086 sizeof(cfg.group_id));
7087 cfg.priority = wpa_s->conf->fst_priority;
7088 cfg.llt = wpa_s->conf->fst_llt;
7089
7090 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7091 &iface_obj, &cfg);
7092 if (!wpa_s->fst) {
7093 wpa_msg(wpa_s, MSG_ERROR,
7094 "FST: Cannot attach iface %s to group %s",
7095 wpa_s->ifname, cfg.group_id);
7096 return -1;
7097 }
7098 }
7099#endif /* CONFIG_FST */
7100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007101 if (wpas_wps_init(wpa_s))
7102 return -1;
7103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007104#ifdef CONFIG_GAS_SERVER
7105 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7106 if (!wpa_s->gas_server) {
7107 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7108 return -1;
7109 }
7110#endif /* CONFIG_GAS_SERVER */
7111
7112#ifdef CONFIG_DPP
7113 if (wpas_dpp_init(wpa_s) < 0)
7114 return -1;
7115#endif /* CONFIG_DPP */
7116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007117 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7118 return -1;
7119 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7120
7121 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7122 if (wpa_s->ctrl_iface == NULL) {
7123 wpa_printf(MSG_ERROR,
7124 "Failed to initialize control interface '%s'.\n"
7125 "You may have another wpa_supplicant process "
7126 "already running or the file was\n"
7127 "left by an unclean termination of wpa_supplicant "
7128 "in which case you will need\n"
7129 "to manually remove this file before starting "
7130 "wpa_supplicant again.\n",
7131 wpa_s->conf->ctrl_interface);
7132 return -1;
7133 }
7134
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007135 wpa_s->gas = gas_query_init(wpa_s);
7136 if (wpa_s->gas == NULL) {
7137 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7138 return -1;
7139 }
7140
Roshan Pius3a1667e2018-07-03 15:17:14 -07007141 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7142 wpa_s->p2p_mgmt) &&
7143 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7145 return -1;
7146 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007147
7148 if (wpa_bss_init(wpa_s) < 0)
7149 return -1;
7150
Paul Stewart092955c2017-02-06 09:13:09 -08007151#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7152#ifdef CONFIG_MESH
7153 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7154#endif /* CONFIG_MESH */
7155#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7156
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007157 /*
7158 * Set Wake-on-WLAN triggers, if configured.
7159 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7160 * have effect anyway when the interface is down).
7161 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007162 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007163 return -1;
7164
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007165#ifdef CONFIG_EAP_PROXY
7166{
7167 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007168 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7169 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007170 if (wpa_s->mnc_len > 0) {
7171 wpa_s->imsi[len] = '\0';
7172 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7173 wpa_s->imsi, wpa_s->mnc_len);
7174 } else {
7175 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7176 }
7177}
7178#endif /* CONFIG_EAP_PROXY */
7179
Dmitry Shmidt04949592012-07-19 12:16:46 -07007180 if (pcsc_reader_init(wpa_s) < 0)
7181 return -1;
7182
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007183 if (wpas_init_ext_pw(wpa_s) < 0)
7184 return -1;
7185
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007186 wpas_rrm_reset(wpa_s);
7187
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007188 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7189
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007190#ifdef CONFIG_HS20
7191 hs20_init(wpa_s);
7192#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007193#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007194 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007195 if ((wpa_s->conf->oce & OCE_STA) &&
7196 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7197 wpa_s->enable_oce = OCE_STA;
7198 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7199 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7200 /* TODO: Need to add STA-CFON support */
7201 wpa_printf(MSG_ERROR,
7202 "OCE STA-CFON feature is not yet supported");
7203 }
7204 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007205 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7206#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007207
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007208 wpa_supplicant_set_default_scan_ies(wpa_s);
7209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210 return 0;
7211}
7212
7213
7214static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007215 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007216{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007217 struct wpa_global *global = wpa_s->global;
7218 struct wpa_supplicant *iface, *prev;
7219
Jimmy Chen0e73c002021-08-18 13:21:30 +08007220 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007221 wpas_p2p_group_remove(wpa_s, "*");
7222
7223 iface = global->ifaces;
7224 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007225 if (iface->p2pdev == wpa_s)
7226 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007227 if (iface == wpa_s || iface->parent != wpa_s) {
7228 iface = iface->next;
7229 continue;
7230 }
7231 wpa_printf(MSG_DEBUG,
7232 "Remove remaining child interface %s from parent %s",
7233 iface->ifname, wpa_s->ifname);
7234 prev = iface;
7235 iface = iface->next;
7236 wpa_supplicant_remove_iface(global, prev, terminate);
7237 }
7238
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007239 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007240 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007241 /*
7242 * Don't deauthenticate if WoWLAN is enable and not explicitly
7243 * been configured to disconnect.
7244 */
7245 if (!wpa_drv_get_wowlan(wpa_s) ||
7246 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007247 wpa_supplicant_deauthenticate(
7248 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007249
Hai Shalomfdcde762020-04-02 11:19:20 -07007250 wpa_drv_set_countermeasures(wpa_s, 0);
7251 wpa_clear_keys(wpa_s, NULL);
7252 } else {
7253 wpa_msg(wpa_s, MSG_INFO,
7254 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7255 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007256 }
7257
7258 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007259 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007260
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007261 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007262 radio_remove_interface(wpa_s);
7263
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007264#ifdef CONFIG_FST
7265 if (wpa_s->fst) {
7266 fst_detach(wpa_s->fst);
7267 wpa_s->fst = NULL;
7268 }
7269 if (wpa_s->received_mb_ies) {
7270 wpabuf_free(wpa_s->received_mb_ies);
7271 wpa_s->received_mb_ies = NULL;
7272 }
7273#endif /* CONFIG_FST */
7274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007275 if (wpa_s->drv_priv)
7276 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007277
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007278 if (notify)
7279 wpas_notify_iface_removed(wpa_s);
7280
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007281 if (terminate)
7282 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007283
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007284 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7285 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007286
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007287#ifdef CONFIG_MESH
7288 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007289 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007290 wpa_s->ifmsh = NULL;
7291 }
7292#endif /* CONFIG_MESH */
7293
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007294 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007295 wpa_config_free(wpa_s->conf);
7296 wpa_s->conf = NULL;
7297 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007298
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007299 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007300 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007301
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007302 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007303}
7304
7305
Dmitry Shmidte4663042016-04-04 10:07:49 -07007306#ifdef CONFIG_MATCH_IFACE
7307
7308/**
7309 * wpa_supplicant_match_iface - Match an interface description to a name
7310 * @global: Pointer to global data from wpa_supplicant_init()
7311 * @ifname: Name of the interface to match
7312 * Returns: Pointer to the created interface description or %NULL on failure
7313 */
7314struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7315 const char *ifname)
7316{
7317 int i;
7318 struct wpa_interface *iface, *miface;
7319
7320 for (i = 0; i < global->params.match_iface_count; i++) {
7321 miface = &global->params.match_ifaces[i];
7322 if (!miface->ifname ||
7323 fnmatch(miface->ifname, ifname, 0) == 0) {
7324 iface = os_zalloc(sizeof(*iface));
7325 if (!iface)
7326 return NULL;
7327 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007328 if (!miface->ifname)
7329 iface->matched = WPA_IFACE_MATCHED_NULL;
7330 else
7331 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007332 iface->ifname = ifname;
7333 return iface;
7334 }
7335 }
7336
7337 return NULL;
7338}
7339
7340
7341/**
7342 * wpa_supplicant_match_existing - Match existing interfaces
7343 * @global: Pointer to global data from wpa_supplicant_init()
7344 * Returns: 0 on success, -1 on failure
7345 */
7346static int wpa_supplicant_match_existing(struct wpa_global *global)
7347{
7348 struct if_nameindex *ifi, *ifp;
7349 struct wpa_supplicant *wpa_s;
7350 struct wpa_interface *iface;
7351
7352 ifp = if_nameindex();
7353 if (!ifp) {
7354 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7355 return -1;
7356 }
7357
7358 for (ifi = ifp; ifi->if_name; ifi++) {
7359 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7360 if (wpa_s)
7361 continue;
7362 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7363 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007364 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007365 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007366 }
7367 }
7368
7369 if_freenameindex(ifp);
7370 return 0;
7371}
7372
7373#endif /* CONFIG_MATCH_IFACE */
7374
7375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007376/**
7377 * wpa_supplicant_add_iface - Add a new network interface
7378 * @global: Pointer to global data from wpa_supplicant_init()
7379 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007380 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007381 * Returns: Pointer to the created interface or %NULL on failure
7382 *
7383 * This function is used to add new network interfaces for %wpa_supplicant.
7384 * This can be called before wpa_supplicant_run() to add interfaces before the
7385 * main event loop has been started. In addition, new interfaces can be added
7386 * dynamically while %wpa_supplicant is already running. This could happen,
7387 * e.g., when a hotplug network adapter is inserted.
7388 */
7389struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007390 struct wpa_interface *iface,
7391 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007392{
7393 struct wpa_supplicant *wpa_s;
7394 struct wpa_interface t_iface;
7395 struct wpa_ssid *ssid;
7396
7397 if (global == NULL || iface == NULL)
7398 return NULL;
7399
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007400 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007401 if (wpa_s == NULL)
7402 return NULL;
7403
7404 wpa_s->global = global;
7405
7406 t_iface = *iface;
7407 if (global->params.override_driver) {
7408 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7409 "('%s' -> '%s')",
7410 iface->driver, global->params.override_driver);
7411 t_iface.driver = global->params.override_driver;
7412 }
7413 if (global->params.override_ctrl_interface) {
7414 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7415 "ctrl_interface ('%s' -> '%s')",
7416 iface->ctrl_interface,
7417 global->params.override_ctrl_interface);
7418 t_iface.ctrl_interface =
7419 global->params.override_ctrl_interface;
7420 }
7421 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7422 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7423 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007424 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007425 return NULL;
7426 }
7427
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007428 /* Notify the control interfaces about new iface */
7429 if (wpas_notify_iface_added(wpa_s)) {
7430 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7431 return NULL;
7432 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007433
Jimmy Chene2206be2022-07-10 10:25:21 +08007434 /* Notify the control interfaces about new networks */
7435 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7436 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007437 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007438 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7439 && os_strncmp((const char *) ssid->ssid,
7440 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7441 wpas_notify_persistent_group_added(wpa_s, ssid);
7442 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007443 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007444
7445 wpa_s->next = global->ifaces;
7446 global->ifaces = wpa_s;
7447
7448 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007449 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007450
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007451#ifdef CONFIG_P2P
7452 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007453 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007454 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007455 wpas_p2p_add_p2pdev_interface(
7456 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007457 wpa_printf(MSG_INFO,
7458 "P2P: Failed to enable P2P Device interface");
7459 /* Try to continue without. P2P will be disabled. */
7460 }
7461#endif /* CONFIG_P2P */
7462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007463 return wpa_s;
7464}
7465
7466
7467/**
7468 * wpa_supplicant_remove_iface - Remove a network interface
7469 * @global: Pointer to global data from wpa_supplicant_init()
7470 * @wpa_s: Pointer to the network interface to be removed
7471 * Returns: 0 if interface was removed, -1 if interface was not found
7472 *
7473 * This function can be used to dynamically remove network interfaces from
7474 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7475 * addition, this function is used to remove all remaining interfaces when
7476 * %wpa_supplicant is terminated.
7477 */
7478int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007479 struct wpa_supplicant *wpa_s,
7480 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481{
7482 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007483#ifdef CONFIG_MESH
7484 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7485 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007486 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007487#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007488
7489 /* Remove interface from the global list of interfaces */
7490 prev = global->ifaces;
7491 if (prev == wpa_s) {
7492 global->ifaces = wpa_s->next;
7493 } else {
7494 while (prev && prev->next != wpa_s)
7495 prev = prev->next;
7496 if (prev == NULL)
7497 return -1;
7498 prev->next = wpa_s->next;
7499 }
7500
7501 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7502
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007503#ifdef CONFIG_MESH
7504 if (mesh_if_created) {
7505 ifname = os_strdup(wpa_s->ifname);
7506 if (ifname == NULL) {
7507 wpa_dbg(wpa_s, MSG_ERROR,
7508 "mesh: Failed to malloc ifname");
7509 return -1;
7510 }
7511 }
7512#endif /* CONFIG_MESH */
7513
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007514 if (global->p2p_group_formation == wpa_s)
7515 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007516 if (global->p2p_invite_group == wpa_s)
7517 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007518 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007519
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007520#ifdef CONFIG_MESH
7521 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007522 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007523 os_free(ifname);
7524 }
7525#endif /* CONFIG_MESH */
7526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007527 return 0;
7528}
7529
7530
7531/**
7532 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7533 * @wpa_s: Pointer to the network interface
7534 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7535 */
7536const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7537{
7538 const char *eapol_method;
7539
7540 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7541 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7542 return "NO-EAP";
7543 }
7544
7545 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7546 if (eapol_method == NULL)
7547 return "UNKNOWN-EAP";
7548
7549 return eapol_method;
7550}
7551
7552
7553/**
7554 * wpa_supplicant_get_iface - Get a new network interface
7555 * @global: Pointer to global data from wpa_supplicant_init()
7556 * @ifname: Interface name
7557 * Returns: Pointer to the interface or %NULL if not found
7558 */
7559struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7560 const char *ifname)
7561{
7562 struct wpa_supplicant *wpa_s;
7563
7564 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7565 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7566 return wpa_s;
7567 }
7568 return NULL;
7569}
7570
7571
7572#ifndef CONFIG_NO_WPA_MSG
7573static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7574{
7575 struct wpa_supplicant *wpa_s = ctx;
7576 if (wpa_s == NULL)
7577 return NULL;
7578 return wpa_s->ifname;
7579}
7580#endif /* CONFIG_NO_WPA_MSG */
7581
7582
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007583#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7584#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7585#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7586
7587/* Periodic cleanup tasks */
7588static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7589{
7590 struct wpa_global *global = eloop_ctx;
7591 struct wpa_supplicant *wpa_s;
7592
7593 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7594 wpas_periodic, global, NULL);
7595
7596#ifdef CONFIG_P2P
7597 if (global->p2p)
7598 p2p_expire_peers(global->p2p);
7599#endif /* CONFIG_P2P */
7600
7601 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7602 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7603#ifdef CONFIG_AP
7604 ap_periodic(wpa_s);
7605#endif /* CONFIG_AP */
7606 }
7607}
7608
7609
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007610/**
7611 * wpa_supplicant_init - Initialize %wpa_supplicant
7612 * @params: Parameters for %wpa_supplicant
7613 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7614 *
7615 * This function is used to initialize %wpa_supplicant. After successful
7616 * initialization, the returned data pointer can be used to add and remove
7617 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7618 */
7619struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7620{
7621 struct wpa_global *global;
7622 int ret, i;
7623
7624 if (params == NULL)
7625 return NULL;
7626
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007627#ifdef CONFIG_DRIVER_NDIS
7628 {
7629 void driver_ndis_init_ops(void);
7630 driver_ndis_init_ops();
7631 }
7632#endif /* CONFIG_DRIVER_NDIS */
7633
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007634#ifndef CONFIG_NO_WPA_MSG
7635 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7636#endif /* CONFIG_NO_WPA_MSG */
7637
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007638 if (params->wpa_debug_file_path)
7639 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007640 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007641 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007642 if (params->wpa_debug_syslog)
7643 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007644 if (params->wpa_debug_tracing) {
7645 ret = wpa_debug_open_linux_tracing();
7646 if (ret) {
7647 wpa_printf(MSG_ERROR,
7648 "Failed to enable trace logging");
7649 return NULL;
7650 }
7651 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007652
7653 ret = eap_register_methods();
7654 if (ret) {
7655 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7656 if (ret == -2)
7657 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7658 "the same EAP type.");
7659 return NULL;
7660 }
7661
7662 global = os_zalloc(sizeof(*global));
7663 if (global == NULL)
7664 return NULL;
7665 dl_list_init(&global->p2p_srv_bonjour);
7666 dl_list_init(&global->p2p_srv_upnp);
7667 global->params.daemonize = params->daemonize;
7668 global->params.wait_for_monitor = params->wait_for_monitor;
7669 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007670
7671 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007672 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007673 if (!global->params.pid_file) {
7674 wpa_supplicant_deinit(global);
7675 return NULL;
7676 }
7677 }
7678
7679 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007680 global->params.ctrl_interface =
7681 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007682 if (!global->params.ctrl_interface) {
7683 wpa_supplicant_deinit(global);
7684 return NULL;
7685 }
7686 }
7687
7688 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007689 global->params.ctrl_interface_group =
7690 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007691 if (!global->params.ctrl_interface_group) {
7692 wpa_supplicant_deinit(global);
7693 return NULL;
7694 }
7695 }
7696
7697 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007698 global->params.override_driver =
7699 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007700 if (!global->params.override_driver) {
7701 wpa_supplicant_deinit(global);
7702 return NULL;
7703 }
7704 }
7705
7706 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007707 global->params.override_ctrl_interface =
7708 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007709 if (!global->params.override_ctrl_interface) {
7710 wpa_supplicant_deinit(global);
7711 return NULL;
7712 }
7713 }
7714
Dmitry Shmidte4663042016-04-04 10:07:49 -07007715#ifdef CONFIG_MATCH_IFACE
7716 global->params.match_iface_count = params->match_iface_count;
7717 if (params->match_iface_count) {
7718 global->params.match_ifaces =
7719 os_calloc(params->match_iface_count,
7720 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007721 if (!global->params.match_ifaces) {
7722 wpa_printf(MSG_ERROR,
7723 "Failed to allocate match interfaces");
7724 wpa_supplicant_deinit(global);
7725 return NULL;
7726 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007727 os_memcpy(global->params.match_ifaces,
7728 params->match_ifaces,
7729 params->match_iface_count *
7730 sizeof(struct wpa_interface));
7731 }
7732#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007733#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007734 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007735 global->params.conf_p2p_dev =
7736 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007737 if (!global->params.conf_p2p_dev) {
7738 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7739 wpa_supplicant_deinit(global);
7740 return NULL;
7741 }
7742 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007743#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007744 wpa_debug_level = global->params.wpa_debug_level =
7745 params->wpa_debug_level;
7746 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7747 params->wpa_debug_show_keys;
7748 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7749 params->wpa_debug_timestamp;
7750
Hai Shalomfdcde762020-04-02 11:19:20 -07007751 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007752
7753 if (eloop_init()) {
7754 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7755 wpa_supplicant_deinit(global);
7756 return NULL;
7757 }
7758
Jouni Malinen75ecf522011-06-27 15:19:46 -07007759 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007760
7761 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7762 if (global->ctrl_iface == NULL) {
7763 wpa_supplicant_deinit(global);
7764 return NULL;
7765 }
7766
7767 if (wpas_notify_supplicant_initialized(global)) {
7768 wpa_supplicant_deinit(global);
7769 return NULL;
7770 }
7771
7772 for (i = 0; wpa_drivers[i]; i++)
7773 global->drv_count++;
7774 if (global->drv_count == 0) {
7775 wpa_printf(MSG_ERROR, "No drivers enabled");
7776 wpa_supplicant_deinit(global);
7777 return NULL;
7778 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007779 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007780 if (global->drv_priv == NULL) {
7781 wpa_supplicant_deinit(global);
7782 return NULL;
7783 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007784
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007785#ifdef CONFIG_WIFI_DISPLAY
7786 if (wifi_display_init(global) < 0) {
7787 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7788 wpa_supplicant_deinit(global);
7789 return NULL;
7790 }
7791#endif /* CONFIG_WIFI_DISPLAY */
7792
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007793 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7794 wpas_periodic, global, NULL);
7795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007796 return global;
7797}
7798
7799
7800/**
7801 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7802 * @global: Pointer to global data from wpa_supplicant_init()
7803 * Returns: 0 after successful event loop run, -1 on failure
7804 *
7805 * This function starts the main event loop and continues running as long as
7806 * there are any remaining events. In most cases, this function is running as
7807 * long as the %wpa_supplicant process in still in use.
7808 */
7809int wpa_supplicant_run(struct wpa_global *global)
7810{
7811 struct wpa_supplicant *wpa_s;
7812
7813 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007814 (wpa_supplicant_daemon(global->params.pid_file) ||
7815 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007816 return -1;
7817
Dmitry Shmidte4663042016-04-04 10:07:49 -07007818#ifdef CONFIG_MATCH_IFACE
7819 if (wpa_supplicant_match_existing(global))
7820 return -1;
7821#endif
7822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007823 if (global->params.wait_for_monitor) {
7824 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007825 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007826 wpa_supplicant_ctrl_iface_wait(
7827 wpa_s->ctrl_iface);
7828 }
7829
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07007830#ifdef CONFIG_AIDL
7831 global->aidl = wpas_aidl_init(global);
7832 if (!global->aidl)
7833 return -1;
7834#endif /* CONFIG_AIDL */
7835
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007836 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7837 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7838
7839 eloop_run();
7840
7841 return 0;
7842}
7843
7844
7845/**
7846 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7847 * @global: Pointer to global data from wpa_supplicant_init()
7848 *
7849 * This function is called to deinitialize %wpa_supplicant and to free all
7850 * allocated resources. Remaining network interfaces will also be removed.
7851 */
7852void wpa_supplicant_deinit(struct wpa_global *global)
7853{
7854 int i;
7855
7856 if (global == NULL)
7857 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007858
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007859 eloop_cancel_timeout(wpas_periodic, global, NULL);
7860
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007861#ifdef CONFIG_WIFI_DISPLAY
7862 wifi_display_deinit(global);
7863#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007864
7865 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007866 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007867
7868 if (global->ctrl_iface)
7869 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7870
7871 wpas_notify_supplicant_deinitialized(global);
7872
7873 eap_peer_unregister_methods();
7874#ifdef CONFIG_AP
7875 eap_server_unregister_methods();
7876#endif /* CONFIG_AP */
7877
7878 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7879 if (!global->drv_priv[i])
7880 continue;
7881 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7882 }
7883 os_free(global->drv_priv);
7884
7885 random_deinit();
7886
7887 eloop_destroy();
7888
7889 if (global->params.pid_file) {
7890 os_daemonize_terminate(global->params.pid_file);
7891 os_free(global->params.pid_file);
7892 }
7893 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007894 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007895 os_free(global->params.override_driver);
7896 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007897#ifdef CONFIG_MATCH_IFACE
7898 os_free(global->params.match_ifaces);
7899#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007900#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007901 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007902#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007903
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007904 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007905 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007906 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007907
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 os_free(global);
7909 wpa_debug_close_syslog();
7910 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007911 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007912}
7913
7914
7915void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7916{
7917 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7918 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7919 char country[3];
7920 country[0] = wpa_s->conf->country[0];
7921 country[1] = wpa_s->conf->country[1];
7922 country[2] = '\0';
7923 if (wpa_drv_set_country(wpa_s, country) < 0) {
7924 wpa_printf(MSG_ERROR, "Failed to set country code "
7925 "'%s'", country);
7926 }
7927 }
7928
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007929 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7930 wpas_init_ext_pw(wpa_s);
7931
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007932 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7933 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7934
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007935 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7936 struct wpa_driver_capa capa;
7937 int res = wpa_drv_get_capa(wpa_s, &capa);
7938
7939 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7940 wpa_printf(MSG_ERROR,
7941 "Failed to update wowlan_triggers to '%s'",
7942 wpa_s->conf->wowlan_triggers);
7943 }
7944
Hai Shalom81f62d82019-07-22 12:10:00 -07007945 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7946 wpa_supplicant_set_default_scan_ies(wpa_s);
7947
Hai Shalom899fcc72020-10-19 14:38:18 -07007948#ifdef CONFIG_BGSCAN
7949 /*
7950 * We default to global bgscan parameters only when per-network bgscan
7951 * parameters aren't set. Only bother resetting bgscan parameters if
7952 * this is the case.
7953 */
7954 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7955 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7956 wpa_s->wpa_state == WPA_COMPLETED)
7957 wpa_supplicant_reset_bgscan(wpa_s);
7958#endif /* CONFIG_BGSCAN */
7959
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007960#ifdef CONFIG_WPS
7961 wpas_wps_update_config(wpa_s);
7962#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007963 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007964 wpa_s->conf->changed_parameters = 0;
7965}
7966
7967
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007968void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007969{
7970 int i;
7971
7972 for (i = 0; i < *num_freqs; i++) {
7973 if (freqs[i] == freq)
7974 return;
7975 }
7976
7977 freqs[*num_freqs] = freq;
7978 (*num_freqs)++;
7979}
7980
7981
7982static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7983{
7984 struct wpa_bss *bss, *cbss;
7985 const int max_freqs = 10;
7986 int *freqs;
7987 int num_freqs = 0;
7988
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007989 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007990 if (freqs == NULL)
7991 return NULL;
7992
7993 cbss = wpa_s->current_bss;
7994
7995 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7996 if (bss == cbss)
7997 continue;
7998 if (bss->ssid_len == cbss->ssid_len &&
7999 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008000 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008001 add_freq(freqs, &num_freqs, bss->freq);
8002 if (num_freqs == max_freqs)
8003 break;
8004 }
8005 }
8006
8007 if (num_freqs == 0) {
8008 os_free(freqs);
8009 freqs = NULL;
8010 }
8011
8012 return freqs;
8013}
8014
8015
8016void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8017{
8018 int timeout;
8019 int count;
8020 int *freqs = NULL;
8021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008022 wpas_connect_work_done(wpa_s);
8023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008024 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008025 * Remove possible authentication timeout since the connection failed.
8026 */
8027 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8028
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008029 /*
Hai Shalom60840252021-02-19 19:02:11 -08008030 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008031 * generated based on local request to disconnect.
8032 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008033 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008034 wpa_s->own_disconnect_req = 0;
8035 wpa_dbg(wpa_s, MSG_DEBUG,
8036 "Ignore connection failure due to local request to disconnect");
8037 return;
8038 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008039 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008040 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8041 "indication since interface has been put into "
8042 "disconnected state");
8043 return;
8044 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008045 if (wpa_s->auto_reconnect_disabled) {
8046 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8047 "indication since auto connect is disabled");
8048 return;
8049 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008050
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008051 /*
Hai Shalom60840252021-02-19 19:02:11 -08008052 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008053 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008054 */
Hai Shalom60840252021-02-19 19:02:11 -08008055 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008056 if (count == 1 && wpa_s->current_bss) {
8057 /*
Hai Shalom60840252021-02-19 19:02:11 -08008058 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008059 * another BSS available for the same ESS, we should try that
8060 * next. Otherwise, we may as well try this one once more
8061 * before allowing other, likely worse, ESSes to be considered.
8062 */
8063 freqs = get_bss_freqs_in_ess(wpa_s);
8064 if (freqs) {
8065 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8066 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008067 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008068 /*
8069 * On the next scan, go through only the known channels
8070 * used in this ESS based on previous scans to speed up
8071 * common load balancing use case.
8072 */
8073 os_free(wpa_s->next_scan_freqs);
8074 wpa_s->next_scan_freqs = freqs;
8075 }
8076 }
8077
Hai Shalom899fcc72020-10-19 14:38:18 -07008078 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008079
Hai Shalom899fcc72020-10-19 14:38:18 -07008080 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008081 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8082 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008083 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008084 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008085 /*
8086 * Multiple consecutive connection failures mean that other APs are
8087 * either not available or have already been tried, so we can start
8088 * increasing the delay here to avoid constant scanning.
8089 */
8090 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008091 case 1:
8092 timeout = 100;
8093 break;
8094 case 2:
8095 timeout = 500;
8096 break;
8097 case 3:
8098 timeout = 1000;
8099 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008100 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008101 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008102 break;
8103 default:
8104 timeout = 10000;
8105 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008106 }
8107
Hai Shalom899fcc72020-10-19 14:38:18 -07008108 wpa_dbg(wpa_s, MSG_DEBUG,
8109 "Consecutive connection failures: %d --> request scan in %d ms",
8110 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008111
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008112 /*
8113 * TODO: if more than one possible AP is available in scan results,
8114 * could try the other ones before requesting a new scan.
8115 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008116
8117 /* speed up the connection attempt with normal scan */
8118 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008119 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8120 1000 * (timeout % 1000));
8121}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008122
8123
Hai Shalomce48b4a2018-09-05 11:41:35 -07008124#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008125
8126void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8127{
8128 struct wpa_ssid *ssid = wpa_s->current_ssid;
8129 const u8 *realm, *username, *rrk;
8130 size_t realm_len, username_len, rrk_len;
8131 u16 next_seq_num;
8132
8133 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8134 * Check for ERP keys existing to limit when this can be done since
8135 * the rejection response is not protected and such triggers should
8136 * really not allow internal state to be modified unless required to
8137 * avoid significant issues in functionality. In addition, drop
8138 * externally configure PMKSA entries even without ERP keys since it
8139 * is possible for an external component to add PMKSA entries for FILS
8140 * authentication without restoring previously generated ERP keys.
8141 *
8142 * In this case, this is needed to allow recovery from cases where the
8143 * AP or authentication server has dropped PMKSAs and ERP keys. */
8144 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8145 return;
8146
8147 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8148 &username, &username_len,
8149 &realm, &realm_len, &next_seq_num,
8150 &rrk, &rrk_len) != 0 ||
8151 !realm) {
8152 wpa_dbg(wpa_s, MSG_DEBUG,
8153 "FILS: Drop external PMKSA cache entry");
8154 wpa_sm_aborted_external_cached(wpa_s->wpa);
8155 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8156 return;
8157 }
8158
8159 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8160 wpa_sm_aborted_cached(wpa_s->wpa);
8161 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8162}
8163
8164
Hai Shalomce48b4a2018-09-05 11:41:35 -07008165void fils_connection_failure(struct wpa_supplicant *wpa_s)
8166{
8167 struct wpa_ssid *ssid = wpa_s->current_ssid;
8168 const u8 *realm, *username, *rrk;
8169 size_t realm_len, username_len, rrk_len;
8170 u16 next_seq_num;
8171
8172 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8173 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8174 &username, &username_len,
8175 &realm, &realm_len, &next_seq_num,
8176 &rrk, &rrk_len) != 0 ||
8177 !realm)
8178 return;
8179
8180 wpa_hexdump_ascii(MSG_DEBUG,
8181 "FILS: Store last connection failure realm",
8182 realm, realm_len);
8183 os_free(wpa_s->last_con_fail_realm);
8184 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8185 if (wpa_s->last_con_fail_realm) {
8186 wpa_s->last_con_fail_realm_len = realm_len;
8187 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8188 }
8189}
8190#endif /* CONFIG_FILS */
8191
8192
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008193int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8194{
8195 return wpa_s->conf->ap_scan == 2 ||
8196 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8197}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008198
Dmitry Shmidt04949592012-07-19 12:16:46 -07008199
Gabriel Biren57ededa2021-09-03 16:08:50 +00008200#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008201int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8202 struct wpa_ssid *ssid,
8203 const char *field,
8204 const char *value)
8205{
8206#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008207 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008208
8209 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8210 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8211 (const u8 *) value, os_strlen(value));
8212
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008213 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008214 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008215#else /* IEEE8021X_EAPOL */
8216 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8217 return -1;
8218#endif /* IEEE8021X_EAPOL */
8219}
8220
8221int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8222 struct wpa_ssid *ssid,
8223 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008224 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008225{
8226#ifdef IEEE8021X_EAPOL
8227 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008228 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008229
8230 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008231 case WPA_CTRL_REQ_EAP_IDENTITY:
8232 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008233 os_free(eap->imsi_identity);
8234 if (value == NULL)
8235 return -1;
8236 identity = os_strchr(value, ':');
8237 if (identity == NULL) {
8238 /* plain identity */
8239 eap->identity = (u8 *)os_strdup(value);
8240 eap->identity_len = os_strlen(value);
8241 } else {
8242 /* have both plain identity and encrypted identity */
8243 imsi_identity = value;
8244 *identity++ = '\0';
8245 /* plain identity */
8246 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8247 eap->imsi_identity_len = strlen(imsi_identity);
8248 /* encrypted identity */
8249 eap->identity = (u8 *)dup_binstr(identity,
8250 value_len - strlen(imsi_identity) - 1);
8251 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8252 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008253 eap->pending_req_identity = 0;
8254 if (ssid == wpa_s->current_ssid)
8255 wpa_s->reassociate = 1;
8256 break;
8257 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008258 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008259 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008260 if (!eap->password)
8261 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008262 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008263 eap->pending_req_password = 0;
8264 if (ssid == wpa_s->current_ssid)
8265 wpa_s->reassociate = 1;
8266 break;
8267 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008268 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008269 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008270 if (!eap->new_password)
8271 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008272 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008273 eap->pending_req_new_password = 0;
8274 if (ssid == wpa_s->current_ssid)
8275 wpa_s->reassociate = 1;
8276 break;
8277 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008278 str_clear_free(eap->cert.pin);
8279 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008280 if (!eap->cert.pin)
8281 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008282 eap->pending_req_pin = 0;
8283 if (ssid == wpa_s->current_ssid)
8284 wpa_s->reassociate = 1;
8285 break;
8286 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008287 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008288 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008289 if (!eap->otp)
8290 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008291 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008292 os_free(eap->pending_req_otp);
8293 eap->pending_req_otp = NULL;
8294 eap->pending_req_otp_len = 0;
8295 break;
8296 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008297 str_clear_free(eap->cert.private_key_passwd);
8298 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008299 if (!eap->cert.private_key_passwd)
8300 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008301 eap->pending_req_passphrase = 0;
8302 if (ssid == wpa_s->current_ssid)
8303 wpa_s->reassociate = 1;
8304 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008305 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008306 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008307 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008308 if (!eap->external_sim_resp)
8309 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008310 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008311 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008312 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8313 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8314 return -1;
8315 ssid->mem_only_psk = 1;
8316 if (ssid->passphrase)
8317 wpa_config_update_psk(ssid);
8318 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8319 wpa_supplicant_req_scan(wpa_s, 0, 0);
8320 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008321 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8322 if (eap->pending_ext_cert_check != PENDING_CHECK)
8323 return -1;
8324 if (os_strcmp(value, "good") == 0)
8325 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8326 else if (os_strcmp(value, "bad") == 0)
8327 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8328 else
8329 return -1;
8330 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008331 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008332 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008333 return -1;
8334 }
8335
8336 return 0;
8337#else /* IEEE8021X_EAPOL */
8338 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8339 return -1;
8340#endif /* IEEE8021X_EAPOL */
8341}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008342#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008343
8344
8345int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8346{
Hai Shalomfdcde762020-04-02 11:19:20 -07008347#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008348 int i;
8349 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008350#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008351
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008352 if (wpa_s->p2p_mgmt)
8353 return 1; /* no normal network profiles on p2p_mgmt interface */
8354
Dmitry Shmidt04949592012-07-19 12:16:46 -07008355 if (ssid == NULL)
8356 return 1;
8357
8358 if (ssid->disabled)
8359 return 1;
8360
Hai Shalomfdcde762020-04-02 11:19:20 -07008361#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008362 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008363 drv_enc = wpa_s->drv_enc;
8364 else
8365 drv_enc = (unsigned int) -1;
8366
8367 for (i = 0; i < NUM_WEP_KEYS; i++) {
8368 size_t len = ssid->wep_key_len[i];
8369 if (len == 0)
8370 continue;
8371 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8372 continue;
8373 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8374 continue;
8375 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8376 continue;
8377 return 1; /* invalid WEP key */
8378 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008379#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008380
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008381 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008382 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008383 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008384 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008385 return 1;
8386
Sunil Ravi89eba102022-09-13 21:04:37 -07008387#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008388#ifdef CRYPTO_RSA_OAEP_SHA256
8389 if (ssid->eap.imsi_privacy_cert) {
8390 struct crypto_rsa_key *key;
8391 bool failed = false;
8392
8393 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8394 if (!key)
8395 failed = true;
8396 crypto_rsa_key_free(key);
8397 if (failed) {
8398 wpa_printf(MSG_DEBUG,
8399 "Invalid imsi_privacy_cert (%s) - disable network",
8400 ssid->eap.imsi_privacy_cert);
8401 return 1;
8402 }
8403 }
8404#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008405#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008406
Dmitry Shmidt04949592012-07-19 12:16:46 -07008407 return 0;
8408}
8409
8410
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008411int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8412{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008413 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8414 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8415 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8416 /*
8417 * Driver does not support BIP -- ignore pmf=1 default
8418 * since the connection with PMF would fail and the
8419 * configuration does not require PMF to be enabled.
8420 */
8421 return NO_MGMT_FRAME_PROTECTION;
8422 }
8423
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008424 if (ssid &&
8425 (ssid->key_mgmt &
8426 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8427 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8428 /*
8429 * Do not use the default PMF value for non-RSN networks
8430 * since PMF is available only with RSN and pmf=2
8431 * configuration would otherwise prevent connections to
8432 * all open networks.
8433 */
8434 return NO_MGMT_FRAME_PROTECTION;
8435 }
8436
Sunil Ravi77d572f2023-01-17 23:58:31 +00008437#ifdef CONFIG_OCV
8438 /* Enable PMF if OCV is being enabled */
8439 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8440 ssid && ssid->ocv)
8441 return MGMT_FRAME_PROTECTION_OPTIONAL;
8442#endif /* CONFIG_OCV */
8443
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008444 return wpa_s->conf->pmf;
8445 }
8446
8447 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008448}
8449
8450
Sunil Ravi77d572f2023-01-17 23:58:31 +00008451#ifdef CONFIG_SAE
8452bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8453 struct wpa_ssid *ssid,
8454 const struct wpa_ie_data *ie)
8455{
8456 return wpa_s->conf->sae_check_mfp &&
8457 (!(ie->capabilities &
8458 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8459 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8460}
8461#endif /* CONFIG_SAE */
8462
8463
Hai Shalomc1a21442022-02-04 13:43:00 -08008464int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8465{
8466 if (wpa_s->current_ssid == NULL ||
8467 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8468 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8469 return 0;
8470 return wpa_sm_pmf_enabled(wpa_s->wpa);
8471}
8472
8473
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008474int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008475{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008476 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008477 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008478 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008479 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008480 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008481}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008482
8483
Sunil Ravi77d572f2023-01-17 23:58:31 +00008484void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8485 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008486{
8487 struct wpa_ssid *ssid = wpa_s->current_ssid;
8488 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008489 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008490
8491 if (ssid == NULL) {
8492 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8493 "SSID block");
8494 return;
8495 }
8496
8497 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8498 return;
8499
8500 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008501
8502#ifdef CONFIG_P2P
8503 if (ssid->p2p_group &&
8504 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8505 /*
8506 * Skip the wait time since there is a short timeout on the
8507 * connection to a P2P group.
8508 */
8509 return;
8510 }
8511#endif /* CONFIG_P2P */
8512
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008513 if (ssid->auth_failures > 50)
8514 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008515 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008516 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008517 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008518 dur = 90;
8519 else if (ssid->auth_failures > 3)
8520 dur = 60;
8521 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008522 dur = 30;
8523 else if (ssid->auth_failures > 1)
8524 dur = 20;
8525 else
8526 dur = 10;
8527
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008528 if (ssid->auth_failures > 1 &&
8529 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8530 dur += os_random() % (ssid->auth_failures * 10);
8531
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008532 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008533 if (now.sec + dur <= ssid->disabled_until.sec)
8534 return;
8535
8536 ssid->disabled_until.sec = now.sec + dur;
8537
8538 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008539 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008540 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008541 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008542
8543 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8544 int msg_len = snprintf(NULL, 0, format_str,
8545 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8546 ssid->auth_failures, dur, reason) + 1;
8547 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308548 if (!msg)
8549 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008550 snprintf(msg, msg_len, format_str,
8551 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8552 ssid->auth_failures, dur, reason);
8553 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8554 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008555
8556 if (bssid)
8557 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008558}
8559
8560
8561void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8562 struct wpa_ssid *ssid, int clear_failures)
8563{
8564 if (ssid == NULL)
8565 return;
8566
8567 if (ssid->disabled_until.sec) {
8568 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8569 "id=%d ssid=\"%s\"",
8570 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8571 }
8572 ssid->disabled_until.sec = 0;
8573 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008574 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008575 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008576 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8577 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8578 " ignored to allow a lower priority BSS, if any, to be tried next",
8579 MAC2STR(ssid->disabled_due_to));
8580 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8581 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8582 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008583}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008584
8585
8586int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8587{
8588 size_t i;
8589
8590 if (wpa_s->disallow_aps_bssid == NULL)
8591 return 0;
8592
8593 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8594 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8595 bssid, ETH_ALEN) == 0)
8596 return 1;
8597 }
8598
8599 return 0;
8600}
8601
8602
8603int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8604 size_t ssid_len)
8605{
8606 size_t i;
8607
8608 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8609 return 0;
8610
8611 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8612 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8613 if (ssid_len == s->ssid_len &&
8614 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8615 return 1;
8616 }
8617
8618 return 0;
8619}
8620
8621
8622/**
8623 * wpas_request_connection - Request a new connection
8624 * @wpa_s: Pointer to the network interface
8625 *
8626 * This function is used to request a new connection to be found. It will mark
8627 * the interface to allow reassociation and request a new scan to find a
8628 * suitable network to connect to.
8629 */
8630void wpas_request_connection(struct wpa_supplicant *wpa_s)
8631{
8632 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008633 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008634 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008635 wpa_s->disconnected = 0;
8636 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008637 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008638
8639 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8640 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008641 else
8642 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008643}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008644
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008645
Roshan Pius02242d72016-08-09 15:31:48 -07008646/**
8647 * wpas_request_disconnection - Request disconnection
8648 * @wpa_s: Pointer to the network interface
8649 *
8650 * This function is used to request disconnection from the currently connected
8651 * network. This will stop any ongoing scans and initiate deauthentication.
8652 */
8653void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8654{
8655#ifdef CONFIG_SME
8656 wpa_s->sme.prev_bssid_set = 0;
8657#endif /* CONFIG_SME */
8658 wpa_s->reassociate = 0;
8659 wpa_s->disconnected = 1;
8660 wpa_supplicant_cancel_sched_scan(wpa_s);
8661 wpa_supplicant_cancel_scan(wpa_s);
8662 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8663 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008664 radio_remove_works(wpa_s, "connect", 0);
8665 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008666 wpa_s->roam_in_progress = false;
8667#ifdef CONFIG_WNM
8668 wpa_s->bss_trans_mgmt_in_progress = false;
8669#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008670}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008671
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008672
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008673void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8674 struct wpa_used_freq_data *freqs_data,
8675 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008676{
8677 unsigned int i;
8678
8679 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8680 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008681 for (i = 0; i < len; i++) {
8682 struct wpa_used_freq_data *cur = &freqs_data[i];
8683 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8684 i, cur->freq, cur->flags);
8685 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008686}
8687
8688
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008689/*
8690 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008691 * are using the same radio as the current interface, and in addition, get
8692 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008693 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008694int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8695 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008696 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008697{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008698 struct wpa_supplicant *ifs;
8699 u8 bssid[ETH_ALEN];
8700 int freq;
8701 unsigned int idx = 0, i;
8702
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008703 wpa_dbg(wpa_s, MSG_DEBUG,
8704 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008705 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008706
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008707 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8708 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008709 if (idx == len)
8710 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008711
Sunil Ravi77d572f2023-01-17 23:58:31 +00008712 if (exclude_current && ifs == wpa_s)
8713 continue;
8714
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008715 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8716 continue;
8717
8718 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008719 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8720 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008721 freq = ifs->current_ssid->frequency;
8722 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8723 freq = ifs->assoc_freq;
8724 else
8725 continue;
8726
8727 /* Hold only distinct freqs */
8728 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008729 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008730 break;
8731
8732 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008733 freqs_data[idx++].freq = freq;
8734
8735 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008736 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008737 WPA_FREQ_USED_BY_P2P_CLIENT :
8738 WPA_FREQ_USED_BY_INFRA_STATION;
8739 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008740 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008741
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008742 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008743 return idx;
8744}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008745
8746
8747/*
8748 * Find the operating frequencies of any of the virtual interfaces that
8749 * are using the same radio as the current interface.
8750 */
8751int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008752 int *freq_array, unsigned int len,
8753 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008754{
8755 struct wpa_used_freq_data *freqs_data;
8756 int num, i;
8757
8758 os_memset(freq_array, 0, sizeof(int) * len);
8759
8760 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8761 if (!freqs_data)
8762 return -1;
8763
Sunil Ravi77d572f2023-01-17 23:58:31 +00008764 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8765 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008766 for (i = 0; i < num; i++)
8767 freq_array[i] = freqs_data[i].freq;
8768
8769 os_free(freqs_data);
8770
8771 return num;
8772}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008773
8774
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008775struct wpa_supplicant *
8776wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8777{
8778 switch (frame) {
8779#ifdef CONFIG_P2P
8780 case VENDOR_ELEM_PROBE_REQ_P2P:
8781 case VENDOR_ELEM_PROBE_RESP_P2P:
8782 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8783 case VENDOR_ELEM_BEACON_P2P_GO:
8784 case VENDOR_ELEM_P2P_PD_REQ:
8785 case VENDOR_ELEM_P2P_PD_RESP:
8786 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8787 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8788 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8789 case VENDOR_ELEM_P2P_INV_REQ:
8790 case VENDOR_ELEM_P2P_INV_RESP:
8791 case VENDOR_ELEM_P2P_ASSOC_REQ:
8792 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008793 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008794#endif /* CONFIG_P2P */
8795 default:
8796 return wpa_s;
8797 }
8798}
8799
8800
8801void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8802{
8803 unsigned int i;
8804 char buf[30];
8805
8806 wpa_printf(MSG_DEBUG, "Update vendor elements");
8807
8808 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8809 if (wpa_s->vendor_elem[i]) {
8810 int res;
8811
8812 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8813 if (!os_snprintf_error(sizeof(buf), res)) {
8814 wpa_hexdump_buf(MSG_DEBUG, buf,
8815 wpa_s->vendor_elem[i]);
8816 }
8817 }
8818 }
8819
8820#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008821 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008822 wpa_s->global->p2p &&
8823 !wpa_s->global->p2p_disabled)
8824 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8825#endif /* CONFIG_P2P */
8826}
8827
8828
8829int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8830 const u8 *elem, size_t len)
8831{
8832 u8 *ie, *end;
8833
8834 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8835 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8836
8837 for (; ie + 1 < end; ie += 2 + ie[1]) {
8838 if (ie + len > end)
8839 break;
8840 if (os_memcmp(ie, elem, len) != 0)
8841 continue;
8842
8843 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8844 wpabuf_free(wpa_s->vendor_elem[frame]);
8845 wpa_s->vendor_elem[frame] = NULL;
8846 } else {
8847 os_memmove(ie, ie + len, end - (ie + len));
8848 wpa_s->vendor_elem[frame]->used -= len;
8849 }
8850 wpas_vendor_elem_update(wpa_s);
8851 return 0;
8852 }
8853
8854 return -1;
8855}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008856
8857
8858struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008859 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008860 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008861{
8862 u16 i;
8863
Hai Shalomc1a21442022-02-04 13:43:00 -08008864 if (!modes)
8865 return NULL;
8866
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008867 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008868 if (modes[i].mode != mode ||
8869 !modes[i].num_channels || !modes[i].channels)
8870 continue;
8871 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8872 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008873 return &modes[i];
8874 }
8875
8876 return NULL;
8877}
8878
8879
Hai Shalomc1a21442022-02-04 13:43:00 -08008880struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8881 u16 num_modes, int freq)
8882{
8883 int i, j;
8884
8885 for (i = 0; i < num_modes; i++) {
8886 for (j = 0; j < modes[i].num_channels; j++) {
8887 if (freq == modes[i].channels[j].freq)
8888 return &modes[i];
8889 }
8890 }
8891
8892 return NULL;
8893}
8894
8895
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008896static struct
8897wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8898 const u8 *bssid)
8899{
8900 struct wpa_bss_tmp_disallowed *bss;
8901
8902 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8903 struct wpa_bss_tmp_disallowed, list) {
8904 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8905 return bss;
8906 }
8907
8908 return NULL;
8909}
8910
8911
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008912static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8913{
8914 struct wpa_bss_tmp_disallowed *tmp;
8915 unsigned int num_bssid = 0;
8916 u8 *bssids;
8917 int ret;
8918
8919 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8920 if (!bssids)
8921 return -1;
8922 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8923 struct wpa_bss_tmp_disallowed, list) {
8924 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8925 ETH_ALEN);
8926 num_bssid++;
8927 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008928 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008929 os_free(bssids);
8930 return ret;
8931}
8932
8933
8934static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8935{
8936 struct wpa_supplicant *wpa_s = eloop_ctx;
8937 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8938
8939 /* Make sure the bss is not already freed */
8940 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8941 struct wpa_bss_tmp_disallowed, list) {
8942 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008943 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008944 wpa_set_driver_tmp_disallow_list(wpa_s);
8945 break;
8946 }
8947 }
8948}
8949
8950
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008951void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008952 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008953{
8954 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008955
8956 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8957 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008958 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008959 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008960 }
8961
8962 bss = os_malloc(sizeof(*bss));
8963 if (!bss) {
8964 wpa_printf(MSG_DEBUG,
8965 "Failed to allocate memory for temp disallow BSS");
8966 return;
8967 }
8968
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008969 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8970 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008971 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008972
8973finish:
8974 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008975 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8976 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008977}
8978
8979
Hai Shalom74f70d42019-02-11 14:42:39 -08008980int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8981 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008982{
Hai Shalom74f70d42019-02-11 14:42:39 -08008983 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008984
8985 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8986 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008987 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8988 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008989 break;
8990 }
8991 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008992 if (!disallowed)
8993 return 0;
8994
8995 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008996 bss->level > disallowed->rssi_threshold) {
8997 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8998 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008999 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009000 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009001
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009002 return 1;
9003}
Hai Shalom81f62d82019-07-22 12:10:00 -07009004
9005
9006int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9007 unsigned int type, const u8 *addr,
9008 const u8 *mask)
9009{
9010 if ((addr && !mask) || (!addr && mask)) {
9011 wpa_printf(MSG_INFO,
9012 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9013 return -1;
9014 }
9015
9016 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9017 wpa_printf(MSG_INFO,
9018 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9019 return -1;
9020 }
9021
9022 if (type & MAC_ADDR_RAND_SCAN) {
9023 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9024 addr, mask))
9025 return -1;
9026 }
9027
9028 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9029 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9030 addr, mask))
9031 return -1;
9032
9033 if (wpa_s->sched_scanning && !wpa_s->pno)
9034 wpas_scan_restart_sched_scan(wpa_s);
9035 }
9036
9037 if (type & MAC_ADDR_RAND_PNO) {
9038 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9039 addr, mask))
9040 return -1;
9041
9042 if (wpa_s->pno) {
9043 wpas_stop_pno(wpa_s);
9044 wpas_start_pno(wpa_s);
9045 }
9046 }
9047
9048 return 0;
9049}
9050
9051
9052int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9053 unsigned int type)
9054{
9055 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9056 if (wpa_s->pno) {
9057 if (type & MAC_ADDR_RAND_PNO) {
9058 wpas_stop_pno(wpa_s);
9059 wpas_start_pno(wpa_s);
9060 }
9061 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9062 wpas_scan_restart_sched_scan(wpa_s);
9063 }
9064
9065 return 0;
9066}
Hai Shalomfdcde762020-04-02 11:19:20 -07009067
9068
9069int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9070 struct wpa_signal_info *si)
9071{
9072 int res;
9073
9074 if (!wpa_s->driver->signal_poll)
9075 return -1;
9076
9077 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9078
9079#ifdef CONFIG_TESTING_OPTIONS
9080 if (res == 0) {
9081 struct driver_signal_override *dso;
9082
9083 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9084 struct driver_signal_override, list) {
9085 if (os_memcmp(wpa_s->bssid, dso->bssid,
9086 ETH_ALEN) != 0)
9087 continue;
9088 wpa_printf(MSG_DEBUG,
9089 "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 +00009090 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009091 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009092 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009093 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009094 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009095 dso->si_avg_beacon_signal,
9096 si->current_noise,
9097 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009098 si->data.signal = dso->si_current_signal;
9099 si->data.avg_signal = dso->si_avg_signal;
9100 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009101 si->current_noise = dso->si_current_noise;
9102 break;
9103 }
9104 }
9105#endif /* CONFIG_TESTING_OPTIONS */
9106
9107 return res;
9108}
9109
9110
9111struct wpa_scan_results *
9112wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9113{
9114 struct wpa_scan_results *scan_res;
9115#ifdef CONFIG_TESTING_OPTIONS
9116 size_t idx;
9117#endif /* CONFIG_TESTING_OPTIONS */
9118
9119 if (!wpa_s->driver->get_scan_results2)
9120 return NULL;
9121
9122 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9123
9124#ifdef CONFIG_TESTING_OPTIONS
9125 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9126 struct driver_signal_override *dso;
9127 struct wpa_scan_res *res = scan_res->res[idx];
9128
9129 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9130 struct driver_signal_override, list) {
9131 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9132 continue;
9133 wpa_printf(MSG_DEBUG,
9134 "Override driver scan signal level %d->%d for "
9135 MACSTR,
9136 res->level, dso->scan_level,
9137 MAC2STR(res->bssid));
9138 res->flags |= WPA_SCAN_QUAL_INVALID;
9139 if (dso->scan_level < 0)
9140 res->flags |= WPA_SCAN_LEVEL_DBM;
9141 else
9142 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9143 res->level = dso->scan_level;
9144 break;
9145 }
9146 }
9147#endif /* CONFIG_TESTING_OPTIONS */
9148
9149 return scan_res;
9150}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009151
9152
9153static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9154{
9155 int i;
9156
9157 if (!wpa_s->valid_links)
9158 return false;
9159
9160 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9161 if (!(wpa_s->valid_links & BIT(i)))
9162 continue;
9163
9164 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9165 return true;
9166 }
9167
9168 return false;
9169}
9170
9171
9172int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9173 unsigned int wait, const u8 *dst, const u8 *src,
9174 const u8 *bssid, const u8 *data, size_t data_len,
9175 int no_cck)
9176{
9177 if (!wpa_s->driver->send_action)
9178 return -1;
9179
9180 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9181 if (wpas_ap_link_address(wpa_s, dst))
9182 dst = wpa_s->ap_mld_addr;
9183
9184 if (wpas_ap_link_address(wpa_s, bssid))
9185 bssid = wpa_s->ap_mld_addr;
9186 }
9187
9188 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9189 bssid, data, data_len, no_cck);
9190}