blob: 99ecef8ded22572d77d4b53c58776b838d48fcab [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 Ravi036cec52023-03-29 11:35:17 -07002342void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2343 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002344{
2345#ifdef CONFIG_SAE
2346 int *groups = conf->sae_groups;
2347 int default_groups[] = { 19, 20, 21, 0 };
2348 const char *password;
2349
2350 if (!groups || groups[0] <= 0)
2351 groups = default_groups;
2352
2353 password = ssid->sae_password;
2354 if (!password)
2355 password = ssid->passphrase;
2356
Hai Shalom899fcc72020-10-19 14:38:18 -07002357 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002358 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002359 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002360 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002361 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002362 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002363 /* PT derivation not needed */
2364 sae_deinit_pt(ssid->pt);
2365 ssid->pt = NULL;
2366 return;
2367 }
2368
2369 if (ssid->pt)
2370 return; /* PT already derived */
2371 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2372 (const u8 *) password, os_strlen(password),
2373 ssid->sae_password_id);
2374#endif /* CONFIG_SAE */
2375}
2376
2377
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002378static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2379{
2380#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2381 os_free(wpa_s->sme.sae_rejected_groups);
2382 wpa_s->sme.sae_rejected_groups = NULL;
2383#ifdef CONFIG_TESTING_OPTIONS
2384 if (wpa_s->extra_sae_rejected_groups) {
2385 int i, *groups = wpa_s->extra_sae_rejected_groups;
2386
2387 for (i = 0; groups[i]; i++) {
2388 wpa_printf(MSG_DEBUG,
2389 "TESTING: Indicate rejection of an extra SAE group %d",
2390 groups[i]);
2391 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2392 groups[i]);
2393 }
2394 }
2395#endif /* CONFIG_TESTING_OPTIONS */
2396#endif /* CONFIG_SAE && CONFIG_SME */
2397}
2398
2399
Hai Shalom60840252021-02-19 19:02:11 -08002400int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2401{
2402 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2403 wpa_msg(wpa_s, MSG_INFO,
2404 "Could not restore permanent MAC address");
2405 return -1;
2406 }
2407 wpa_s->mac_addr_changed = 0;
2408 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2409 wpa_msg(wpa_s, MSG_INFO,
2410 "Could not update MAC address information");
2411 return -1;
2412 }
2413 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2414 return 0;
2415}
2416
2417
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002418static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420/**
2421 * wpa_supplicant_associate - Request association
2422 * @wpa_s: Pointer to wpa_supplicant data
2423 * @bss: Scan results for the selected BSS, or %NULL if not available
2424 * @ssid: Configuration data for the selected network
2425 *
2426 * This function is used to request %wpa_supplicant to associate with a BSS.
2427 */
2428void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2429 struct wpa_bss *bss, struct wpa_ssid *ssid)
2430{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002431 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002432 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002433
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002434 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002435 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002436
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002437 /*
2438 * If we are starting a new connection, any previously pending EAPOL
2439 * RX cannot be valid anymore.
2440 */
2441 wpabuf_free(wpa_s->pending_eapol_rx);
2442 wpa_s->pending_eapol_rx = NULL;
2443
Sunil Ravi77d572f2023-01-17 23:58:31 +00002444 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002445 rand_style = wpa_s->conf->mac_addr;
2446 else
2447 rand_style = ssid->mac_addr;
2448
Sunil Ravia04bd252022-05-02 22:54:18 -07002449 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002450 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002451 wmm_ac_clear_saved_tspecs(wpa_s);
2452 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002453 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002454#ifdef CONFIG_TESTING_OPTIONS
2455 wpa_s->testing_resend_assoc = 0;
2456#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002457
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002458 if (wpa_s->last_ssid == ssid) {
2459 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002460 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002461 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2462 wmm_ac_save_tspecs(wpa_s);
2463 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002464 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2465 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002466 }
Hai Shalomc3565922019-10-28 11:58:20 -07002467 } else {
2468#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002469 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002470#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002471 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002472#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002473 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002474#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002475
Sunil Ravi77d572f2023-01-17 23:58:31 +00002476 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2477 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2478
2479 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002480 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002481 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2482 status > 0) /* MAC changed */
2483 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2484 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2485 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002486 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002487 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002488 }
2489 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490
2491#ifdef CONFIG_IBSS_RSN
2492 ibss_rsn_deinit(wpa_s->ibss_rsn);
2493 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002494#else /* CONFIG_IBSS_RSN */
2495 if (ssid->mode == WPAS_MODE_IBSS &&
2496 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2497 wpa_msg(wpa_s, MSG_INFO,
2498 "IBSS RSN not supported in the build");
2499 return;
2500 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501#endif /* CONFIG_IBSS_RSN */
2502
2503 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2504 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2505#ifdef CONFIG_AP
2506 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2507 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2508 "mode");
2509 return;
2510 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002511 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2512 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002513 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2514 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002515 return;
2516 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 wpa_s->current_bss = bss;
2518#else /* CONFIG_AP */
2519 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2520 "the build");
2521#endif /* CONFIG_AP */
2522 return;
2523 }
2524
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002525 if (ssid->mode == WPAS_MODE_MESH) {
2526#ifdef CONFIG_MESH
2527 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2528 wpa_msg(wpa_s, MSG_INFO,
2529 "Driver does not support mesh mode");
2530 return;
2531 }
2532 if (bss)
2533 ssid->frequency = bss->freq;
2534 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002535 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002536 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2537 return;
2538 }
2539 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002540#else /* CONFIG_MESH */
2541 wpa_msg(wpa_s, MSG_ERROR,
2542 "mesh mode support not included in the build");
2543#endif /* CONFIG_MESH */
2544 return;
2545 }
2546
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002547 /*
2548 * Set WPA state machine configuration to match the selected network now
2549 * so that the information is available before wpas_start_assoc_cb()
2550 * gets called. This is needed at least for RSN pre-authentication where
2551 * candidate APs are added to a list based on scan result processing
2552 * before completion of the first association.
2553 */
2554 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2555
2556#ifdef CONFIG_DPP
2557 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2558 return;
2559#endif /* CONFIG_DPP */
2560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561#ifdef CONFIG_TDLS
2562 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002563 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564#endif /* CONFIG_TDLS */
2565
Hai Shalomc3565922019-10-28 11:58:20 -07002566#ifdef CONFIG_MBO
2567 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2568#endif /* CONFIG_MBO */
2569
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002571 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572 sme_authenticate(wpa_s, bss, ssid);
2573 return;
2574 }
2575
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002576 if (wpa_s->connect_work) {
2577 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2578 return;
2579 }
2580
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002581 if (radio_work_pending(wpa_s, "connect")) {
2582 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2583 return;
2584 }
2585
Dmitry Shmidt29333592017-01-09 12:27:11 -08002586#ifdef CONFIG_SME
2587 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2588 /* Clear possibly set auth_alg, if any, from last attempt. */
2589 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2590 }
2591#endif /* CONFIG_SME */
2592
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002593 wpas_abort_ongoing_scan(wpa_s);
2594
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002595 cwork = os_zalloc(sizeof(*cwork));
2596 if (cwork == NULL)
2597 return;
2598
2599 cwork->bss = bss;
2600 cwork->ssid = ssid;
2601
2602 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2603 wpas_start_assoc_cb, cwork) < 0) {
2604 os_free(cwork);
2605 }
2606}
2607
2608
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002609static int bss_is_ibss(struct wpa_bss *bss)
2610{
2611 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2612 IEEE80211_CAP_IBSS;
2613}
2614
2615
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002616static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2617 const struct wpa_ssid *ssid)
2618{
2619 enum hostapd_hw_mode hw_mode;
2620 struct hostapd_hw_modes *mode = NULL;
2621 u8 channel;
2622 int i;
2623
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002624 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2625 if (hw_mode == NUM_HOSTAPD_MODES)
2626 return 0;
2627 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2628 if (wpa_s->hw.modes[i].mode == hw_mode) {
2629 mode = &wpa_s->hw.modes[i];
2630 break;
2631 }
2632 }
2633
2634 if (!mode)
2635 return 0;
2636
2637 return mode->vht_capab != 0;
2638}
2639
2640
Hai Shalomc1a21442022-02-04 13:43:00 -08002641static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2642{
2643 int i;
2644
2645 for (i = channel; i < channel + 16; i += 4) {
2646 struct hostapd_channel_data *chan;
2647
2648 chan = hw_get_channel_chan(mode, i, NULL);
2649 if (!chan ||
2650 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2651 return false;
2652 }
2653
2654 return true;
2655}
2656
2657
Sunil Ravi036cec52023-03-29 11:35:17 -07002658static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2659 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002660{
Sunil Ravi036cec52023-03-29 11:35:17 -07002661 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002662
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002663 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2664 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2665
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002666 if (!bss_is_ibss(bss))
2667 continue;
2668
2669 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002670 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2671 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002673 return NULL;
2674}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002675
Sunil Ravi036cec52023-03-29 11:35:17 -07002676
2677static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2678 const struct wpa_ssid *ssid,
2679 struct hostapd_hw_modes *mode)
2680{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002681 /* For IBSS check HT_IBSS flag */
2682 if (ssid->mode == WPAS_MODE_IBSS &&
2683 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002684 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002685
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002686 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2687 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2688 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2689 wpa_printf(MSG_DEBUG,
2690 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002691 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002692 }
2693
Sunil Ravi036cec52023-03-29 11:35:17 -07002694 if (!ht_supported(mode))
2695 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002696
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002697#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002698 if (ssid->disable_ht)
2699 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002700#endif /* CONFIG_HT_OVERRIDES */
2701
Sunil Ravi036cec52023-03-29 11:35:17 -07002702 return true;
2703}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002704
Sunil Ravi036cec52023-03-29 11:35:17 -07002705
2706static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2707 const struct wpa_ssid *ssid,
2708 struct hostapd_hw_modes *mode)
2709{
2710 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2711 return false;
2712
2713 if (!drv_supports_vht(wpa_s, ssid))
2714 return false;
2715
2716 /* For IBSS check VHT_IBSS flag */
2717 if (ssid->mode == WPAS_MODE_IBSS &&
2718 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2719 return false;
2720
2721 if (!vht_supported(mode))
2722 return false;
2723
2724#ifdef CONFIG_VHT_OVERRIDES
2725 if (ssid->disable_vht)
2726 return false;
2727#endif /* CONFIG_VHT_OVERRIDES */
2728
2729 return true;
2730}
2731
2732
2733static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2734 const struct wpa_ssid *ssid,
2735 const struct hostapd_hw_modes *mode,
2736 int ieee80211_mode)
2737{
Hai Shalomfdcde762020-04-02 11:19:20 -07002738#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002739 if (ssid->disable_he)
2740 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002741#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002742
Sunil Ravi036cec52023-03-29 11:35:17 -07002743 switch (mode->mode) {
2744 case HOSTAPD_MODE_IEEE80211G:
2745 case HOSTAPD_MODE_IEEE80211B:
2746 case HOSTAPD_MODE_IEEE80211A:
2747 return mode->he_capab[ieee80211_mode].he_supported;
2748 default:
2749 return false;
2750 }
2751}
2752
2753
2754static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2755 const struct wpa_ssid *ssid,
2756 const struct hostapd_hw_modes *mode,
2757 int ieee80211_mode)
2758{
2759 if (ssid->disable_eht)
2760 return false;
2761
2762 switch(mode->mode) {
2763 case HOSTAPD_MODE_IEEE80211G:
2764 case HOSTAPD_MODE_IEEE80211B:
2765 case HOSTAPD_MODE_IEEE80211A:
2766 return mode->eht_capab[ieee80211_mode].eht_supported;
2767 default:
2768 return false;
2769 }
2770}
2771
2772
2773static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2774 const struct wpa_ssid *ssid,
2775 struct hostapd_hw_modes *mode,
2776 struct hostapd_freq_params *freq,
2777 int obss_scan) {
2778 int chan_idx;
2779 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2780 int i, res;
2781 unsigned int j;
2782 static const int ht40plus[] = {
2783 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 165, 173,
2784 184, 192
2785 };
2786 int ht40 = -1;
2787
2788 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002789 return;
2790
2791 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2792 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002793 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002794 break;
2795 pri_chan = NULL;
2796 }
2797 if (!pri_chan)
2798 return;
2799
2800 /* Check primary channel flags */
2801 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2802 return;
2803
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002804#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002805 if (ssid->disable_ht40)
2806 return;
2807#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002808
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002809 /* Check/setup HT40+/HT40- */
2810 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002811 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002812 ht40 = 1;
2813 break;
2814 }
2815 }
2816
2817 /* Find secondary channel */
2818 for (i = 0; i < mode->num_channels; i++) {
2819 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002820 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002821 break;
2822 sec_chan = NULL;
2823 }
2824 if (!sec_chan)
2825 return;
2826
2827 /* Check secondary channel flags */
2828 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2829 return;
2830
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002831 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002832 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2833 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002834 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002835 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2836 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002837 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002838 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002839
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002840 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002841 struct wpa_scan_results *scan_res;
2842
2843 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2844 if (scan_res == NULL) {
2845 /* Back to HT20 */
2846 freq->sec_channel_offset = 0;
2847 return;
2848 }
2849
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002850 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002851 switch (res) {
2852 case 0:
2853 /* Back to HT20 */
2854 freq->sec_channel_offset = 0;
2855 break;
2856 case 1:
2857 /* Configuration allowed */
2858 break;
2859 case 2:
2860 /* Switch pri/sec channels */
2861 freq->freq = hw_get_freq(mode, sec_chan->chan);
2862 freq->sec_channel_offset = -freq->sec_channel_offset;
2863 freq->channel = sec_chan->chan;
2864 break;
2865 default:
2866 freq->sec_channel_offset = 0;
2867 break;
2868 }
2869
2870 wpa_scan_results_free(scan_res);
2871 }
2872
2873 wpa_printf(MSG_DEBUG,
2874 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2875 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002876}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002877
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002878
Sunil Ravi036cec52023-03-29 11:35:17 -07002879static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2880 const struct wpa_ssid *ssid,
2881 struct hostapd_hw_modes *mode,
2882 struct hostapd_freq_params *freq,
2883 int ieee80211_mode, bool is_6ghz) {
2884 static const int bw80[] = {
2885 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2886 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2887 6515, 6595, 6675, 6755, 6835, 6915, 6995
2888 };
2889 static const int bw160[] = {
2890 5955, 6115, 6275, 6435, 6595, 6755, 6915
2891 };
2892 struct hostapd_freq_params vht_freq;
2893 int i;
2894 unsigned int j, k;
2895 int chwidth, seg0, seg1;
2896 u32 vht_caps = 0;
2897 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002898
Sunil Ravi036cec52023-03-29 11:35:17 -07002899 if (!freq->vht_enabled && !freq->he_enabled)
2900 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002901
Hai Shalomc1a21442022-02-04 13:43:00 -08002902 vht_freq = *freq;
2903
Sunil Ravi036cec52023-03-29 11:35:17 -07002904 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2905 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2906 seg1 = 0;
2907 if (freq->sec_channel_offset == 0) {
2908 seg0 = 0;
2909 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2910 if (freq->ht_enabled && !is_6ghz)
2911 goto skip_80mhz;
2912 }
2913 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2914 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002915
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002916 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002917 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2918 if (freq->freq >= bw80[j] &&
2919 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002920 break;
2921 }
2922
Hai Shalomc1a21442022-02-04 13:43:00 -08002923 if (j == ARRAY_SIZE(bw80) ||
2924 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002925 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002926
Sunil Ravi036cec52023-03-29 11:35:17 -07002927 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002928 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002929 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002930
Sunil8cd6f4d2022-06-28 18:40:46 +00002931 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002932 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002933 seg1 = 0;
2934
Sunil Ravi036cec52023-03-29 11:35:17 -07002935 /* In 160 MHz, the initial four 20 MHz channels were validated
2936 * above. If 160 MHz is supported, check the remaining four 20 MHz
2937 * channels for the total of 160 MHz bandwidth for 6 GHz.
2938 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002939 if ((mode->he_capab[ieee80211_mode].phy_cap[
2940 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002941 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2942 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002943 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2944 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002945 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002946 seg0 = channel + 14;
2947 break;
2948 }
2949 }
2950 }
2951
Sunil8cd6f4d2022-06-28 18:40:46 +00002952 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002953 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002954 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002955 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002956 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002957 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002958
2959 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2960 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002961 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08002962
2963 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002964 struct hostapd_channel_data *chan;
2965
2966 chan = hw_get_channel_chan(mode, i, NULL);
2967 if (!chan)
2968 continue;
2969
2970 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2971 HOSTAPD_CHAN_NO_IR |
2972 HOSTAPD_CHAN_RADAR))
2973 continue;
2974
2975 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002976 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002977 if (!is_6ghz)
2978 vht_caps |=
2979 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2980 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002981 }
2982
Sunil8cd6f4d2022-06-28 18:40:46 +00002983 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002984 break;
2985 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002986 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002987 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002988 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002989 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2990 seg0 = 50;
2991 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002992 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002993 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2994 seg0 = 114;
2995 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002996 }
2997
Sunil Ravi036cec52023-03-29 11:35:17 -07002998skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002999 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003000 freq->channel, ssid->enable_edmg,
3001 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003002 freq->vht_enabled, freq->he_enabled,
3003 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003004 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003005 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003006 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003007 &mode->eht_capab[ieee80211_mode]) != 0)
3008 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003009
3010 *freq = vht_freq;
3011
3012 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3013 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003014 return true;
3015}
3016
3017
3018void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3019 const struct wpa_ssid *ssid,
3020 struct hostapd_freq_params *freq)
3021{
3022 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3023 enum hostapd_hw_mode hw_mode;
3024 struct hostapd_hw_modes *mode = NULL;
3025 int i, obss_scan = 1;
3026 u8 channel;
3027 bool is_6ghz;
3028
3029 freq->freq = ssid->frequency;
3030
3031 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3032 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3033
3034 if (bss) {
3035 wpa_printf(MSG_DEBUG,
3036 "IBSS already found in scan results, adjust control freq: %d",
3037 bss->freq);
3038 freq->freq = bss->freq;
3039 obss_scan = 0;
3040 }
3041 }
3042
3043 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3044 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3045 if (wpa_s->hw.modes[i].mode == hw_mode &&
3046 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3047 NULL) != NULL) {
3048 mode = &wpa_s->hw.modes[i];
3049 break;
3050 }
3051 }
3052
3053 if (!mode)
3054 return;
3055
3056 is_6ghz = is_6ghz_freq(freq->freq);
3057
3058 freq->ht_enabled = 0;
3059 freq->vht_enabled = 0;
3060 freq->he_enabled = 0;
3061 freq->eht_enabled = 0;
3062
3063 if (!is_6ghz)
3064 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3065 if (freq->ht_enabled)
3066 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3067 if (freq->vht_enabled || is_6ghz)
3068 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3069 ieee80211_mode);
3070 freq->channel = channel;
3071 /* Setup higher BW only for 5 GHz */
3072 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3073 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3074 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3075 ieee80211_mode, is_6ghz))
3076 freq->he_enabled = freq->vht_enabled = false;
3077 }
3078
3079 if (freq->he_enabled)
3080 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3081 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003082}
3083
3084
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003085#ifdef CONFIG_FILS
3086static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3087 size_t ie_buf_len)
3088{
3089 struct fils_hlp_req *req;
3090 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3091 const u8 *pos;
3092 u8 *buf = ie_buf;
3093
3094 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3095 list) {
3096 rem_len = ie_buf_len - ie_len;
3097 pos = wpabuf_head(req->pkt);
3098 hdr_len = 1 + 2 * ETH_ALEN + 6;
3099 hlp_len = wpabuf_len(req->pkt);
3100
3101 if (rem_len < 2 + hdr_len + hlp_len) {
3102 wpa_printf(MSG_ERROR,
3103 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3104 (unsigned long) rem_len,
3105 (unsigned long) (2 + hdr_len + hlp_len));
3106 break;
3107 }
3108
3109 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3110 /* Element ID */
3111 *buf++ = WLAN_EID_EXTENSION;
3112 /* Length */
3113 *buf++ = len;
3114 /* Element ID Extension */
3115 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3116 /* Destination MAC address */
3117 os_memcpy(buf, req->dst, ETH_ALEN);
3118 buf += ETH_ALEN;
3119 /* Source MAC address */
3120 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3121 buf += ETH_ALEN;
3122 /* LLC/SNAP Header */
3123 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3124 buf += 6;
3125 /* HLP Packet */
3126 os_memcpy(buf, pos, len - hdr_len);
3127 buf += len - hdr_len;
3128 pos += len - hdr_len;
3129
3130 hlp_len -= len - hdr_len;
3131 ie_len += 2 + len;
3132 rem_len -= 2 + len;
3133
3134 while (hlp_len) {
3135 len = (hlp_len > 255) ? 255 : hlp_len;
3136 if (rem_len < 2 + len)
3137 break;
3138 *buf++ = WLAN_EID_FRAGMENT;
3139 *buf++ = len;
3140 os_memcpy(buf, pos, len);
3141 buf += len;
3142 pos += len;
3143
3144 hlp_len -= len;
3145 ie_len += 2 + len;
3146 rem_len -= 2 + len;
3147 }
3148 }
3149
3150 return ie_len;
3151}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003152
3153
3154int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3155{
3156 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3157 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3158 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3159 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3160}
3161
3162
3163int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3164{
3165#ifdef CONFIG_FILS_SK_PFS
3166 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3167 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3168#else /* CONFIG_FILS_SK_PFS */
3169 return 0;
3170#endif /* CONFIG_FILS_SK_PFS */
3171}
3172
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003173#endif /* CONFIG_FILS */
3174
3175
Hai Shalomc1a21442022-02-04 13:43:00 -08003176static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3177 struct wpa_bss *bss,
3178 u8 *wpa_ie, size_t wpa_ie_len,
3179 size_t max_wpa_ie_len)
3180{
3181 struct wpabuf *wfa_ie = NULL;
3182 u8 wfa_capa[1];
3183 size_t wfa_ie_len, buf_len;
3184
3185 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3186 if (wpa_s->enable_dscp_policy_capa)
3187 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3188
3189 if (!wfa_capa[0])
3190 return wpa_ie_len;
3191
3192 /* Wi-Fi Alliance element */
3193 buf_len = 1 + /* Element ID */
3194 1 + /* Length */
3195 3 + /* OUI */
3196 1 + /* OUI Type */
3197 1 + /* Capabilities Length */
3198 sizeof(wfa_capa); /* Capabilities */
3199 wfa_ie = wpabuf_alloc(buf_len);
3200 if (!wfa_ie)
3201 return wpa_ie_len;
3202
3203 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3204 wpabuf_put_u8(wfa_ie, buf_len - 2);
3205 wpabuf_put_be24(wfa_ie, OUI_WFA);
3206 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3207 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3208 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3209
3210 wfa_ie_len = wpabuf_len(wfa_ie);
3211 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3212 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3213 wfa_ie);
3214 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3215 wfa_ie_len);
3216 wpa_ie_len += wfa_ie_len;
3217 }
3218
3219 wpabuf_free(wfa_ie);
3220 return wpa_ie_len;
3221}
3222
3223
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003224static u8 * wpas_populate_assoc_ies(
3225 struct wpa_supplicant *wpa_s,
3226 struct wpa_bss *bss, struct wpa_ssid *ssid,
3227 struct wpa_driver_associate_params *params,
3228 enum wpa_drv_update_connect_params_mask *mask)
3229{
3230 u8 *wpa_ie;
3231 size_t max_wpa_ie_len = 500;
3232 size_t wpa_ie_len;
3233 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003234#ifdef CONFIG_MBO
3235 const u8 *mbo_ie;
3236#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303237#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3238 int pmksa_cached = 0;
3239#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003240#ifdef CONFIG_FILS
3241 const u8 *realm, *username, *rrk;
3242 size_t realm_len, username_len, rrk_len;
3243 u16 next_seq_num;
3244 struct fils_hlp_req *req;
3245
3246 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3247 list) {
3248 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3249 2 + 2 * wpabuf_len(req->pkt) / 255;
3250 }
3251#endif /* CONFIG_FILS */
3252
3253 wpa_ie = os_malloc(max_wpa_ie_len);
3254 if (!wpa_ie) {
3255 wpa_printf(MSG_ERROR,
3256 "Failed to allocate connect IE buffer for %lu bytes",
3257 (unsigned long) max_wpa_ie_len);
3258 return NULL;
3259 }
3260
3261 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3262 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3263 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3264 int try_opportunistic;
3265 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003266 const u8 *addr = bss->bssid;
3267
Sunil Ravi036cec52023-03-29 11:35:17 -07003268 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3269 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3270 !is_zero_ether_addr(bss->mld_addr))
3271 addr = bss->mld_addr;
3272
3273 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3274 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003275 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003276
3277 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3278 wpa_s->conf->okc :
3279 ssid->proactive_key_caching) &&
3280 (ssid->proto & WPA_PROTO_RSN);
3281#ifdef CONFIG_FILS
3282 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3283 cache_id = wpa_bss_get_fils_cache_id(bss);
3284#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003285 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003286 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003287 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303289#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3290 pmksa_cached = 1;
3291#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003292 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003293 wpa_ie_len = max_wpa_ie_len;
3294 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003295 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003296 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3297 "key management and encryption suites");
3298 os_free(wpa_ie);
3299 return NULL;
3300 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003301#ifdef CONFIG_HS20
3302 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3303 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3304 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3305 wpa_ie_len = max_wpa_ie_len;
3306 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003307 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003308 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3309 "key management and encryption suites");
3310 os_free(wpa_ie);
3311 return NULL;
3312 }
3313#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003314 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3315 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3316 /*
3317 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3318 * use non-WPA since the scan results did not indicate that the
3319 * AP is using WPA or WPA2.
3320 */
3321 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3322 wpa_ie_len = 0;
3323 wpa_s->wpa_proto = 0;
3324 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3325 wpa_ie_len = max_wpa_ie_len;
3326 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003327 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003328 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3329 "key management and encryption suites (no "
3330 "scan results)");
3331 os_free(wpa_ie);
3332 return NULL;
3333 }
3334#ifdef CONFIG_WPS
3335 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3336 struct wpabuf *wps_ie;
3337 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3338 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3339 wpa_ie_len = wpabuf_len(wps_ie);
3340 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3341 } else
3342 wpa_ie_len = 0;
3343 wpabuf_free(wps_ie);
3344 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3345 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3346 params->wps = WPS_MODE_PRIVACY;
3347 else
3348 params->wps = WPS_MODE_OPEN;
3349 wpa_s->wpa_proto = 0;
3350#endif /* CONFIG_WPS */
3351 } else {
3352 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3353 wpa_ie_len = 0;
3354 wpa_s->wpa_proto = 0;
3355 }
3356
3357#ifdef IEEE8021X_EAPOL
3358 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3359 if (ssid->leap) {
3360 if (ssid->non_leap == 0)
3361 algs = WPA_AUTH_ALG_LEAP;
3362 else
3363 algs |= WPA_AUTH_ALG_LEAP;
3364 }
3365 }
3366
3367#ifdef CONFIG_FILS
3368 /* Clear FILS association */
3369 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3370
3371 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3372 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3373 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3374 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003375 &next_seq_num, &rrk, &rrk_len) == 0 &&
3376 (!wpa_s->last_con_fail_realm ||
3377 wpa_s->last_con_fail_realm_len != realm_len ||
3378 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003379 algs = WPA_AUTH_ALG_FILS;
3380 params->fils_erp_username = username;
3381 params->fils_erp_username_len = username_len;
3382 params->fils_erp_realm = realm;
3383 params->fils_erp_realm_len = realm_len;
3384 params->fils_erp_next_seq_num = next_seq_num;
3385 params->fils_erp_rrk = rrk;
3386 params->fils_erp_rrk_len = rrk_len;
3387
3388 if (mask)
3389 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303390 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3391 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3392 pmksa_cached) {
3393 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003394 }
3395#endif /* CONFIG_FILS */
3396#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003397#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003398 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003399 algs = WPA_AUTH_ALG_SAE;
3400#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003401
3402 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3403 if (ssid->auth_alg) {
3404 algs = ssid->auth_alg;
3405 wpa_dbg(wpa_s, MSG_DEBUG,
3406 "Overriding auth_alg selection: 0x%x", algs);
3407 }
3408
Hai Shalom5f92bc92019-04-18 11:54:11 -07003409#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303410 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003411 wpa_dbg(wpa_s, MSG_DEBUG,
3412 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3413 algs = WPA_AUTH_ALG_OPEN;
3414 }
3415#endif /* CONFIG_SAE */
3416
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003417#ifdef CONFIG_P2P
3418 if (wpa_s->global->p2p) {
3419 u8 *pos;
3420 size_t len;
3421 int res;
3422 pos = wpa_ie + wpa_ie_len;
3423 len = max_wpa_ie_len - wpa_ie_len;
3424 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3425 ssid->p2p_group);
3426 if (res >= 0)
3427 wpa_ie_len += res;
3428 }
3429
3430 wpa_s->cross_connect_disallowed = 0;
3431 if (bss) {
3432 struct wpabuf *p2p;
3433 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3434 if (p2p) {
3435 wpa_s->cross_connect_disallowed =
3436 p2p_get_cross_connect_disallowed(p2p);
3437 wpabuf_free(p2p);
3438 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3439 "connection",
3440 wpa_s->cross_connect_disallowed ?
3441 "disallows" : "allows");
3442 }
3443 }
3444
3445 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3446#endif /* CONFIG_P2P */
3447
3448 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003449 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 wpa_ie + wpa_ie_len,
3451 max_wpa_ie_len -
3452 wpa_ie_len);
3453 }
3454
3455 /*
3456 * Workaround: Add Extended Capabilities element only if the AP
3457 * included this element in Beacon/Probe Response frames. Some older
3458 * APs seem to have interoperability issues if this element is
3459 * included, so while the standard may require us to include the
3460 * element in all cases, it is justifiable to skip it to avoid
3461 * interoperability issues.
3462 */
3463 if (ssid->p2p_group)
3464 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3465 else
3466 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3467
3468 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3469 u8 ext_capab[18];
3470 int ext_capab_len;
3471 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3472 sizeof(ext_capab));
3473 if (ext_capab_len > 0 &&
3474 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3475 u8 *pos = wpa_ie;
3476 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3477 pos += 2 + pos[1];
3478 os_memmove(pos + ext_capab_len, pos,
3479 wpa_ie_len - (pos - wpa_ie));
3480 wpa_ie_len += ext_capab_len;
3481 os_memcpy(pos, ext_capab, ext_capab_len);
3482 }
3483 }
3484
3485#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003486 if (is_hs20_network(wpa_s, ssid, bss)
3487#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3488 && is_hs20_config(wpa_s)
3489#endif /* ANDROID */
3490 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003491 struct wpabuf *hs20;
3492
Roshan Pius3a1667e2018-07-03 15:17:14 -07003493 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003494 if (hs20) {
3495 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3496 size_t len;
3497
Hai Shalom74f70d42019-02-11 14:42:39 -08003498 wpas_hs20_add_indication(hs20, pps_mo_id,
3499 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003500 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003501 len = max_wpa_ie_len - wpa_ie_len;
3502 if (wpabuf_len(hs20) <= len) {
3503 os_memcpy(wpa_ie + wpa_ie_len,
3504 wpabuf_head(hs20), wpabuf_len(hs20));
3505 wpa_ie_len += wpabuf_len(hs20);
3506 }
3507 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003508 }
3509 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003510 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003511#endif /* CONFIG_HS20 */
3512
3513 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3514 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3515 size_t len;
3516
3517 len = max_wpa_ie_len - wpa_ie_len;
3518 if (wpabuf_len(buf) <= len) {
3519 os_memcpy(wpa_ie + wpa_ie_len,
3520 wpabuf_head(buf), wpabuf_len(buf));
3521 wpa_ie_len += wpabuf_len(buf);
3522 }
3523 }
3524
3525#ifdef CONFIG_FST
3526 if (wpa_s->fst_ies) {
3527 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3528
3529 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3530 os_memcpy(wpa_ie + wpa_ie_len,
3531 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3532 wpa_ie_len += fst_ies_len;
3533 }
3534 }
3535#endif /* CONFIG_FST */
3536
3537#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003538 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003539 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003540 int len;
3541
3542 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003543 max_wpa_ie_len - wpa_ie_len,
3544 !!mbo_attr_from_mbo_ie(mbo_ie,
3545 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003546 if (len >= 0)
3547 wpa_ie_len += len;
3548 }
3549#endif /* CONFIG_MBO */
3550
3551#ifdef CONFIG_FILS
3552 if (algs == WPA_AUTH_ALG_FILS) {
3553 size_t len;
3554
3555 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3556 max_wpa_ie_len - wpa_ie_len);
3557 wpa_ie_len += len;
3558 }
3559#endif /* CONFIG_FILS */
3560
3561#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003562#ifdef CONFIG_TESTING_OPTIONS
3563 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3564 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3565 } else
3566#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003567 if (algs == WPA_AUTH_ALG_OPEN &&
3568 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3569 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003570 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003571
Roshan Pius3a1667e2018-07-03 15:17:14 -07003572 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003573 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003574 } else if (wpa_s->assoc_status_code ==
3575 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003576 if (wpa_s->last_owe_group == 19)
3577 group = 20;
3578 else if (wpa_s->last_owe_group == 20)
3579 group = 21;
3580 else
3581 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003582 } else {
3583 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003584 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003585
Roshan Pius3a1667e2018-07-03 15:17:14 -07003586 wpa_s->last_owe_group = group;
3587 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003588 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3589 if (owe_ie &&
3590 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3591 os_memcpy(wpa_ie + wpa_ie_len,
3592 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3593 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003594 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003595 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003596 }
3597#endif /* CONFIG_OWE */
3598
Hai Shalom021b0b52019-04-10 11:17:58 -07003599#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003600 if (DPP_VERSION > 1 &&
3601 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003602 ssid->dpp_netaccesskey &&
3603 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003604 struct rsn_pmksa_cache_entry *pmksa;
3605
3606 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3607 if (!pmksa || !pmksa->dpp_pfs)
3608 goto pfs_fail;
3609
Hai Shalom021b0b52019-04-10 11:17:58 -07003610 dpp_pfs_free(wpa_s->dpp_pfs);
3611 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3612 ssid->dpp_netaccesskey_len);
3613 if (!wpa_s->dpp_pfs) {
3614 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3615 /* Try to continue without PFS */
3616 goto pfs_fail;
3617 }
3618 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3619 max_wpa_ie_len - wpa_ie_len) {
3620 os_memcpy(wpa_ie + wpa_ie_len,
3621 wpabuf_head(wpa_s->dpp_pfs->ie),
3622 wpabuf_len(wpa_s->dpp_pfs->ie));
3623 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3624 }
3625 }
3626pfs_fail:
3627#endif /* CONFIG_DPP2 */
3628
Roshan Pius3a1667e2018-07-03 15:17:14 -07003629#ifdef CONFIG_IEEE80211R
3630 /*
3631 * Add MDIE under these conditions: the network profile allows FT,
3632 * the AP supports FT, and the mobility domain ID matches.
3633 */
3634 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3635 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3636
3637 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3638 size_t len = 0;
3639 const u8 *md = mdie + 2;
3640 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3641
3642 if (os_memcmp(md, wpa_md,
3643 MOBILITY_DOMAIN_ID_LEN) == 0) {
3644 /* Add mobility domain IE */
3645 len = wpa_ft_add_mdie(
3646 wpa_s->wpa, wpa_ie + wpa_ie_len,
3647 max_wpa_ie_len - wpa_ie_len, mdie);
3648 wpa_ie_len += len;
3649 }
3650#ifdef CONFIG_SME
3651 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003652 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003653 wpa_dbg(wpa_s, MSG_DEBUG,
3654 "SME: Trying to use FT over-the-air");
3655 algs |= WPA_AUTH_ALG_FT;
3656 }
3657#endif /* CONFIG_SME */
3658 }
3659 }
3660#endif /* CONFIG_IEEE80211R */
3661
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003662#ifdef CONFIG_TESTING_OPTIONS
3663 if (wpa_s->rsnxe_override_assoc &&
3664 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3665 max_wpa_ie_len - wpa_ie_len) {
3666 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3667 os_memcpy(wpa_ie + wpa_ie_len,
3668 wpabuf_head(wpa_s->rsnxe_override_assoc),
3669 wpabuf_len(wpa_s->rsnxe_override_assoc));
3670 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3671 } else
3672#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003673 if (wpa_s->rsnxe_len > 0 &&
3674 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3675 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3676 wpa_ie_len += wpa_s->rsnxe_len;
3677 }
3678
Hai Shalomc1a21442022-02-04 13:43:00 -08003679#ifdef CONFIG_TESTING_OPTIONS
3680 if (wpa_s->disable_mscs_support)
3681 goto mscs_end;
3682#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003683 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3684 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003685 struct wpabuf *mscs_ie;
3686 size_t mscs_ie_len, buf_len;
3687
Hai Shalom899fcc72020-10-19 14:38:18 -07003688 buf_len = 3 + /* MSCS descriptor IE header */
3689 1 + /* Request type */
3690 2 + /* User priority control */
3691 4 + /* Stream timeout */
3692 3 + /* TCLAS Mask IE header */
3693 wpa_s->robust_av.frame_classifier_len;
3694 mscs_ie = wpabuf_alloc(buf_len);
3695 if (!mscs_ie) {
3696 wpa_printf(MSG_INFO,
3697 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003698 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003699 }
3700
3701 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3702 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3703 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3704 mscs_ie_len = wpabuf_len(mscs_ie);
3705 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3706 mscs_ie_len);
3707 wpa_ie_len += mscs_ie_len;
3708 }
3709
3710 wpabuf_free(mscs_ie);
3711 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003712mscs_end:
3713
3714 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3715 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003716
Hai Shalom74f70d42019-02-11 14:42:39 -08003717 if (ssid->multi_ap_backhaul_sta) {
3718 size_t multi_ap_ie_len;
3719
3720 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3721 max_wpa_ie_len - wpa_ie_len,
3722 MULTI_AP_BACKHAUL_STA);
3723 if (multi_ap_ie_len == 0) {
3724 wpa_printf(MSG_ERROR,
3725 "Multi-AP: Failed to build Multi-AP IE");
3726 os_free(wpa_ie);
3727 return NULL;
3728 }
3729 wpa_ie_len += multi_ap_ie_len;
3730 }
3731
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003732 params->wpa_ie = wpa_ie;
3733 params->wpa_ie_len = wpa_ie_len;
3734 params->auth_alg = algs;
3735 if (mask)
3736 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3737
3738 return wpa_ie;
3739}
3740
3741
Hai Shalomc3565922019-10-28 11:58:20 -07003742#ifdef CONFIG_OWE
3743static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3744{
3745 struct wpa_driver_associate_params params;
3746 u8 *wpa_ie;
3747
3748 os_memset(&params, 0, sizeof(params));
3749 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3750 wpa_s->current_ssid, &params, NULL);
3751 if (!wpa_ie)
3752 return;
3753
3754 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3755 os_free(wpa_ie);
3756}
3757#endif /* CONFIG_OWE */
3758
3759
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003760#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3761static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3762{
3763 struct wpa_driver_associate_params params;
3764 enum wpa_drv_update_connect_params_mask mask = 0;
3765 u8 *wpa_ie;
3766
3767 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3768 return; /* nothing to do */
3769
3770 os_memset(&params, 0, sizeof(params));
3771 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3772 wpa_s->current_ssid, &params, &mask);
3773 if (!wpa_ie)
3774 return;
3775
Hai Shalomc1a21442022-02-04 13:43:00 -08003776 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3777 wpa_s->auth_alg = params.auth_alg;
3778 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003779 }
3780
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003781 os_free(wpa_ie);
3782}
3783#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3784
3785
Hai Shalomc3565922019-10-28 11:58:20 -07003786static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3787{
3788 if (!edmg_ie || edmg_ie[1] < 6)
3789 return 0;
3790 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3791}
3792
3793
3794static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3795{
3796 if (!edmg_ie || edmg_ie[1] < 6)
3797 return 0;
3798 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3799}
3800
3801
3802/* Returns the intersection of two EDMG configurations.
3803 * Note: The current implementation is limited to CB2 only (CB1 included),
3804 * i.e., the implementation supports up to 2 contiguous channels.
3805 * For supporting non-contiguous (aggregated) channels and for supporting
3806 * CB3 and above, this function will need to be extended.
3807 */
3808static struct ieee80211_edmg_config
3809get_edmg_intersection(struct ieee80211_edmg_config a,
3810 struct ieee80211_edmg_config b,
3811 u8 primary_channel)
3812{
3813 struct ieee80211_edmg_config result;
3814 int i, contiguous = 0;
3815 int max_contiguous = 0;
3816
3817 result.channels = b.channels & a.channels;
3818 if (!result.channels) {
3819 wpa_printf(MSG_DEBUG,
3820 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3821 a.channels, b.channels);
3822 goto fail;
3823 }
3824
3825 if (!(result.channels & BIT(primary_channel - 1))) {
3826 wpa_printf(MSG_DEBUG,
3827 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3828 primary_channel, result.channels);
3829 goto fail;
3830 }
3831
3832 /* Find max contiguous channels */
3833 for (i = 0; i < 6; i++) {
3834 if (result.channels & BIT(i))
3835 contiguous++;
3836 else
3837 contiguous = 0;
3838
3839 if (contiguous > max_contiguous)
3840 max_contiguous = contiguous;
3841 }
3842
3843 /* Assuming AP and STA supports ONLY contiguous channels,
3844 * bw configuration can have value between 4-7.
3845 */
3846 if ((b.bw_config < a.bw_config))
3847 result.bw_config = b.bw_config;
3848 else
3849 result.bw_config = a.bw_config;
3850
3851 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3852 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3853 wpa_printf(MSG_DEBUG,
3854 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3855 max_contiguous);
3856 goto fail;
3857 }
3858
3859 return result;
3860
3861fail:
3862 result.channels = 0;
3863 result.bw_config = 0;
3864 return result;
3865}
3866
3867
3868static struct ieee80211_edmg_config
3869get_supported_edmg(struct wpa_supplicant *wpa_s,
3870 struct hostapd_freq_params *freq,
3871 struct ieee80211_edmg_config request_edmg)
3872{
3873 enum hostapd_hw_mode hw_mode;
3874 struct hostapd_hw_modes *mode = NULL;
3875 u8 primary_channel;
3876
3877 if (!wpa_s->hw.modes)
3878 goto fail;
3879
3880 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3881 if (hw_mode == NUM_HOSTAPD_MODES)
3882 goto fail;
3883
Hai Shalom60840252021-02-19 19:02:11 -08003884 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003885 if (!mode)
3886 goto fail;
3887
3888 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3889
3890fail:
3891 request_edmg.channels = 0;
3892 request_edmg.bw_config = 0;
3893 return request_edmg;
3894}
3895
3896
Hai Shalom021b0b52019-04-10 11:17:58 -07003897#ifdef CONFIG_MBO
3898void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3899{
3900 struct wpa_driver_associate_params params;
3901 u8 *wpa_ie;
3902
3903 /*
3904 * Update MBO connect params only in case of change of MBO attributes
3905 * when connected, if the AP support MBO.
3906 */
3907
3908 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3909 !wpa_s->current_bss ||
3910 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3911 return;
3912
3913 os_memset(&params, 0, sizeof(params));
3914 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3915 wpa_s->current_ssid, &params, NULL);
3916 if (!wpa_ie)
3917 return;
3918
3919 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3920 os_free(wpa_ie);
3921}
3922#endif /* CONFIG_MBO */
3923
3924
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003925static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3926{
3927 struct wpa_connect_work *cwork = work->ctx;
3928 struct wpa_bss *bss = cwork->bss;
3929 struct wpa_ssid *ssid = cwork->ssid;
3930 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003931 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003932 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003933 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003934 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003935 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003936 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003937#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003938 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003939#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003940 int assoc_failed = 0;
3941 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003942 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003943#ifdef CONFIG_HT_OVERRIDES
3944 struct ieee80211_ht_capabilities htcaps;
3945 struct ieee80211_ht_capabilities htcaps_mask;
3946#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003947#ifdef CONFIG_VHT_OVERRIDES
3948 struct ieee80211_vht_capabilities vhtcaps;
3949 struct ieee80211_vht_capabilities vhtcaps_mask;
3950#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003951
Hai Shalomc1a21442022-02-04 13:43:00 -08003952 wpa_s->roam_in_progress = false;
3953#ifdef CONFIG_WNM
3954 wpa_s->bss_trans_mgmt_in_progress = false;
3955#endif /* CONFIG_WNM */
3956
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003957 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003958 if (work->started) {
3959 wpa_s->connect_work = NULL;
3960
3961 /* cancel possible auth. timeout */
3962 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3963 NULL);
3964 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003965 wpas_connect_work_free(cwork);
3966 return;
3967 }
3968
3969 wpa_s->connect_work = work;
3970
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003971 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3972 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003973 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3974 wpas_connect_work_done(wpa_s);
3975 return;
3976 }
3977
Dmitry Shmidte4663042016-04-04 10:07:49 -07003978 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003979 os_memset(&params, 0, sizeof(params));
3980 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003981 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003982
3983 /* Starting new association, so clear the possibly used WPA IE from the
3984 * previous association. */
3985 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3986 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3987 wpa_s->rsnxe_len = 0;
3988 wpa_s->mscs_setup_done = false;
3989
3990 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3991 if (!wpa_ie) {
3992 wpas_connect_work_done(wpa_s);
3993 return;
3994 }
3995
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003996 if (bss &&
3997 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998#ifdef CONFIG_IEEE80211R
3999 const u8 *ie, *md = NULL;
4000#endif /* CONFIG_IEEE80211R */
4001 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4002 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4003 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4004 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4005 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4006 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4007 if (bssid_changed)
4008 wpas_notify_bssid_changed(wpa_s);
4009#ifdef CONFIG_IEEE80211R
4010 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4011 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4012 md = ie + 2;
4013 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4014 if (md) {
4015 /* Prepare for the next transition */
4016 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4017 }
4018#endif /* CONFIG_IEEE80211R */
4019#ifdef CONFIG_WPS
4020 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4021 wpa_s->conf->ap_scan == 2 &&
4022 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4023 /* Use ap_scan==1 style network selection to find the network
4024 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004025 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004026 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004027 wpa_s->reassociate = 1;
4028 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004029 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004030 return;
4031#endif /* CONFIG_WPS */
4032 } else {
4033 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4034 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004035 if (bss)
4036 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4037 else
4038 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004039 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004040 if (!wpa_s->pno)
4041 wpa_supplicant_cancel_sched_scan(wpa_s);
4042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004043 wpa_supplicant_cancel_scan(wpa_s);
4044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4046 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004047 cipher_pairwise = wpa_s->pairwise_cipher;
4048 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004049 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4051 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4052 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4053 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004054#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004055 if (wpa_set_wep_keys(wpa_s, ssid)) {
4056 use_crypt = 1;
4057 wep_keys_set = 1;
4058 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004059#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 }
4061 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4062 use_crypt = 0;
4063
4064#ifdef IEEE8021X_EAPOL
4065 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4066 if ((ssid->eapol_flags &
4067 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4068 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4069 !wep_keys_set) {
4070 use_crypt = 0;
4071 } else {
4072 /* Assume that dynamic WEP-104 keys will be used and
4073 * set cipher suites in order for drivers to expect
4074 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004075 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 }
4077 }
4078#endif /* IEEE8021X_EAPOL */
4079
4080 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4081 /* Set the key before (and later after) association */
4082 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4083 }
4084
Sunil8cd6f4d2022-06-28 18:40:46 +00004085 /* Set current_ssid before changing state to ASSOCIATING, so that the
4086 * selected SSID is available to wpas_notify_state_changed(). */
4087 old_ssid = wpa_s->current_ssid;
4088 wpa_s->current_ssid = ssid;
4089
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004090 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4091 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 params.ssid = bss->ssid;
4093 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004094 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4095 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004096 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4097 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004098 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004099 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004100 ssid->bssid_set,
4101 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004102 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004103 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004104 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004105 params.bssid_hint = bss->bssid;
4106 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004107 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004108 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004109 if (ssid->bssid_hint_set)
4110 params.bssid_hint = ssid->bssid_hint;
4111
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 params.ssid = ssid->ssid;
4113 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004114 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004115 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004116
4117 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4118 wpa_s->conf->ap_scan == 2) {
4119 params.bssid = ssid->bssid;
4120 params.fixed_bssid = 1;
4121 }
4122
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004123 /* Initial frequency for IBSS/mesh */
4124 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004125 ssid->frequency > 0 && params.freq.freq == 0)
4126 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004127
4128 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004129 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004130 if (ssid->beacon_int)
4131 params.beacon_int = ssid->beacon_int;
4132 else
4133 params.beacon_int = wpa_s->conf->beacon_int;
4134 }
4135
Hai Shalomc3565922019-10-28 11:58:20 -07004136 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004137 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4138 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004139 else
4140 edmg_ie_oper = NULL;
4141
4142 if (edmg_ie_oper) {
4143 params.freq.edmg.channels =
4144 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4145 params.freq.edmg.bw_config =
4146 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4147 wpa_printf(MSG_DEBUG,
4148 "AP supports EDMG channels 0x%x, bw_config %d",
4149 params.freq.edmg.channels,
4150 params.freq.edmg.bw_config);
4151
4152 /* User may ask for specific EDMG channel for EDMG connection
4153 * (must be supported by AP)
4154 */
4155 if (ssid->edmg_channel) {
4156 struct ieee80211_edmg_config configured_edmg;
4157 enum hostapd_hw_mode hw_mode;
4158 u8 primary_channel;
4159
4160 hw_mode = ieee80211_freq_to_chan(bss->freq,
4161 &primary_channel);
4162 if (hw_mode == NUM_HOSTAPD_MODES)
4163 goto edmg_fail;
4164
4165 hostapd_encode_edmg_chan(ssid->enable_edmg,
4166 ssid->edmg_channel,
4167 primary_channel,
4168 &configured_edmg);
4169
4170 if (ieee802_edmg_is_allowed(params.freq.edmg,
4171 configured_edmg)) {
4172 params.freq.edmg = configured_edmg;
4173 wpa_printf(MSG_DEBUG,
4174 "Use EDMG channel %d for connection",
4175 ssid->edmg_channel);
4176 } else {
4177 edmg_fail:
4178 params.freq.edmg.channels = 0;
4179 params.freq.edmg.bw_config = 0;
4180 wpa_printf(MSG_WARNING,
4181 "EDMG channel %d not supported by AP, fallback to DMG",
4182 ssid->edmg_channel);
4183 }
4184 }
4185
4186 if (params.freq.edmg.channels) {
4187 wpa_printf(MSG_DEBUG,
4188 "EDMG before: channels 0x%x, bw_config %d",
4189 params.freq.edmg.channels,
4190 params.freq.edmg.bw_config);
4191 params.freq.edmg = get_supported_edmg(wpa_s,
4192 &params.freq,
4193 params.freq.edmg);
4194 wpa_printf(MSG_DEBUG,
4195 "EDMG after: channels 0x%x, bw_config %d",
4196 params.freq.edmg.channels,
4197 params.freq.edmg.bw_config);
4198 }
4199 }
4200
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 params.pairwise_suite = cipher_pairwise;
4202 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004203 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004204 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004205 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004206 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004207 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004208 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004209 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004210#ifdef CONFIG_WEP
4211 {
4212 int i;
4213
4214 for (i = 0; i < NUM_WEP_KEYS; i++) {
4215 if (ssid->wep_key_len[i])
4216 params.wep_key[i] = ssid->wep_key[i];
4217 params.wep_key_len[i] = ssid->wep_key_len[i];
4218 }
4219 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004220 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004221#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004222
Hai Shalom74f70d42019-02-11 14:42:39 -08004223 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004224#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004225 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4226 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304227#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004228 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4229 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4230 (params.allowed_key_mgmts &
4231 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004232#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004233 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004234 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4235 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004236 }
4237
Hai Shalom74f70d42019-02-11 14:42:39 -08004238 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4239 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4240 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4241 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4242 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004243 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004244
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004245 if (wpa_s->conf->key_mgmt_offload) {
4246 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4247 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004248 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4249 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004250 params.req_key_mgmt_offload =
4251 ssid->proactive_key_caching < 0 ?
4252 wpa_s->conf->okc : ssid->proactive_key_caching;
4253 else
4254 params.req_key_mgmt_offload = 1;
4255
Winnie Chen4138eec2022-11-10 16:32:53 +08004256#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004257 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004258 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4259 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004260#else
4261 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4262 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004263#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004264 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4265 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004266 }
4267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004268 params.drop_unencrypted = use_crypt;
4269
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004270 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004271 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4273 struct wpa_ie_data ie;
4274 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4275 ie.capabilities &
4276 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4277 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4278 "MFP: require MFP");
4279 params.mgmt_frame_protection =
4280 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004281#ifdef CONFIG_OWE
4282 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4283 !ssid->owe_only) {
4284 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4285#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004286 }
4287 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004289 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004291 if (wpa_s->p2pdev->set_sta_uapsd)
4292 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004293 else
4294 params.uapsd = -1;
4295
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004296#ifdef CONFIG_HT_OVERRIDES
4297 os_memset(&htcaps, 0, sizeof(htcaps));
4298 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4299 params.htcaps = (u8 *) &htcaps;
4300 params.htcaps_mask = (u8 *) &htcaps_mask;
4301 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4302#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004303#ifdef CONFIG_VHT_OVERRIDES
4304 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4305 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4306 params.vhtcaps = &vhtcaps;
4307 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004308 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004309#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004310#ifdef CONFIG_HE_OVERRIDES
4311 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4312#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004313 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004314
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004315#ifdef CONFIG_P2P
4316 /*
4317 * If multi-channel concurrency is not supported, check for any
4318 * frequency conflict. In case of any frequency conflict, remove the
4319 * least prioritized connection.
4320 */
4321 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004322 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004323 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004324 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004325 wpa_printf(MSG_DEBUG,
4326 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004327 freq, params.freq.freq);
4328 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004329 wpa_s, params.freq.freq, ssid) < 0) {
4330 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004331 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004332 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004333 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004334 }
4335 }
4336#endif /* CONFIG_P2P */
4337
Dmitry Shmidte4663042016-04-04 10:07:49 -07004338 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004339 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004340 params.prev_bssid = prev_bssid;
4341
Hai Shalom60840252021-02-19 19:02:11 -08004342#ifdef CONFIG_SAE
4343 params.sae_pwe = wpa_s->conf->sae_pwe;
4344#endif /* CONFIG_SAE */
4345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004346 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004347 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004348 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 if (ret < 0) {
4350 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4351 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004352 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004353 /*
4354 * The driver is known to mean what is saying, so we
4355 * can stop right here; the association will not
4356 * succeed.
4357 */
4358 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004359 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004360 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004361 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4363 return;
4364 }
4365 /* try to continue anyway; new association will be tried again
4366 * after timeout */
4367 assoc_failed = 1;
4368 }
4369
4370 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4371 /* Set the key after the association just in case association
4372 * cleared the previously configured key. */
4373 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4374 /* No need to timeout authentication since there is no key
4375 * management. */
4376 wpa_supplicant_cancel_auth_timeout(wpa_s);
4377 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4378#ifdef CONFIG_IBSS_RSN
4379 } else if (ssid->mode == WPAS_MODE_IBSS &&
4380 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4381 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4382 /*
4383 * RSN IBSS authentication is per-STA and we can disable the
4384 * per-BSSID authentication.
4385 */
4386 wpa_supplicant_cancel_auth_timeout(wpa_s);
4387#endif /* CONFIG_IBSS_RSN */
4388 } else {
4389 /* Timeout for IEEE 802.11 authentication and association */
4390 int timeout = 60;
4391
4392 if (assoc_failed) {
4393 /* give IBSS a bit more time */
4394 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4395 } else if (wpa_s->conf->ap_scan == 1) {
4396 /* give IBSS a bit more time */
4397 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4398 }
4399 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4400 }
4401
Hai Shalomfdcde762020-04-02 11:19:20 -07004402#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004403 if (wep_keys_set &&
4404 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004405 /* Set static WEP keys again */
4406 wpa_set_wep_keys(wpa_s, ssid);
4407 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004408#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004409
Sunil8cd6f4d2022-06-28 18:40:46 +00004410 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004411 /*
4412 * Do not allow EAP session resumption between different
4413 * network configurations.
4414 */
4415 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4416 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004417
4418 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004419 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004420#ifdef CONFIG_HS20
4421 hs20_configure_frame_filters(wpa_s);
4422#endif /* CONFIG_HS20 */
4423 }
4424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004425 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4426 wpa_supplicant_initiate_eapol(wpa_s);
4427 if (old_ssid != wpa_s->current_ssid)
4428 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004429 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4430 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004431}
4432
4433
4434static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4435 const u8 *addr)
4436{
4437 struct wpa_ssid *old_ssid;
4438
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004439 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004440 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004441 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004442 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443 wpa_sm_set_config(wpa_s->wpa, NULL);
4444 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4445 if (old_ssid != wpa_s->current_ssid)
4446 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004447
4448 wpas_scs_deinit(wpa_s);
4449 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004450 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4451}
4452
4453
4454/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004455 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4456 * @wpa_s: Pointer to wpa_supplicant data
4457 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4458 *
4459 * This function is used to request %wpa_supplicant to deauthenticate from the
4460 * current AP.
4461 */
4462void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004463 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464{
4465 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004466 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004467 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004469 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004470 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004471 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004472 reason_code, reason2str(reason_code),
4473 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004474
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004475 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4476 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4477 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004478 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004479 else if (!is_zero_ether_addr(wpa_s->bssid))
4480 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004481 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4482 /*
4483 * When using driver-based BSS selection, we may not know the
4484 * BSSID with which we are currently trying to associate. We
4485 * need to notify the driver of this disconnection even in such
4486 * a case, so use the all zeros address here.
4487 */
4488 addr = wpa_s->bssid;
4489 zero_addr = 1;
4490 }
4491
Hai Shalom74f70d42019-02-11 14:42:39 -08004492 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4493 wpa_s->enabled_4addr_mode = 0;
4494
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004495#ifdef CONFIG_TDLS
4496 wpa_tdls_teardown_peers(wpa_s->wpa);
4497#endif /* CONFIG_TDLS */
4498
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004499#ifdef CONFIG_MESH
4500 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004501 struct mesh_conf *mconf;
4502
4503 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004504 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4505 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004506 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4507 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004508 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004509 }
4510#endif /* CONFIG_MESH */
4511
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004512 if (addr) {
4513 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004514 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004515 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004516 event.deauth_info.locally_generated = 1;
4517 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004518 if (zero_addr)
4519 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004520 }
4521
4522 wpa_supplicant_clear_connection(wpa_s, addr);
4523}
4524
Hai Shalomfdcde762020-04-02 11:19:20 -07004525
4526void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4527{
4528 wpa_s->own_reconnect_req = 1;
4529 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4530
4531}
4532
4533
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004534static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4535 struct wpa_ssid *ssid)
4536{
4537 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4538 return;
4539
4540 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004541 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004542 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4543 wpas_notify_network_enabled_changed(wpa_s, ssid);
4544
4545 /*
4546 * Try to reassociate since there is no current configuration and a new
4547 * network was made available.
4548 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004549 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004550 wpa_s->reassociate = 1;
4551}
4552
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004553
Roshan Pius950bec92016-07-19 09:49:24 -07004554/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004555 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004556 * @wpa_s: wpa_supplicant structure for a network interface
4557 * Returns: The new network configuration or %NULL if operation failed
4558 *
4559 * This function performs the following operations:
4560 * 1. Adds a new network.
4561 * 2. Send network addition notification.
4562 * 3. Marks the network disabled.
4563 * 4. Set network default parameters.
4564 */
4565struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4566{
4567 struct wpa_ssid *ssid;
4568
4569 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004570 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004571 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004572 wpas_notify_network_added(wpa_s, ssid);
4573 ssid->disabled = 1;
4574 wpa_config_set_network_defaults(ssid);
4575
4576 return ssid;
4577}
4578
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004579
Roshan Pius950bec92016-07-19 09:49:24 -07004580/**
4581 * wpa_supplicant_remove_network - Remove a configured network based on id
4582 * @wpa_s: wpa_supplicant structure for a network interface
4583 * @id: Unique network id to search for
4584 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4585 * could not be removed
4586 *
4587 * This function performs the following operations:
4588 * 1. Removes the network.
4589 * 2. Send network removal notification.
4590 * 3. Update internal state machines.
4591 * 4. Stop any running sched scans.
4592 */
4593int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4594{
Sunil Ravia04bd252022-05-02 22:54:18 -07004595 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004596 int was_disabled;
4597
4598 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004599 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004600 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004601 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004602
Sunil Ravia04bd252022-05-02 22:54:18 -07004603 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004604#ifdef CONFIG_SME
4605 wpa_s->sme.prev_bssid_set = 0;
4606#endif /* CONFIG_SME */
4607 /*
4608 * Invalidate the EAP session cache if the current or
4609 * previously used network is removed.
4610 */
4611 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4612 }
4613
Sunil Ravia04bd252022-05-02 22:54:18 -07004614 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004615 wpa_sm_set_config(wpa_s->wpa, NULL);
4616 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4617
4618 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4619 wpa_s->own_disconnect_req = 1;
4620 wpa_supplicant_deauthenticate(wpa_s,
4621 WLAN_REASON_DEAUTH_LEAVING);
4622 }
4623
4624 was_disabled = ssid->disabled;
4625
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004626 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004627 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004628
4629 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004630 wpa_printf(MSG_DEBUG,
4631 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004632 wpa_supplicant_cancel_sched_scan(wpa_s);
4633 wpa_supplicant_req_scan(wpa_s, 0, 0);
4634 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004635
Roshan Pius950bec92016-07-19 09:49:24 -07004636 return 0;
4637}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004638
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004640/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004641 * wpa_supplicant_remove_all_networks - Remove all configured networks
4642 * @wpa_s: wpa_supplicant structure for a network interface
4643 * Returns: 0 on success (errors are currently ignored)
4644 *
4645 * This function performs the following operations:
4646 * 1. Remove all networks.
4647 * 2. Send network removal notifications.
4648 * 3. Update internal state machines.
4649 * 4. Stop any running sched scans.
4650 */
4651int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4652{
4653 struct wpa_ssid *ssid;
4654
4655 if (wpa_s->sched_scanning)
4656 wpa_supplicant_cancel_sched_scan(wpa_s);
4657
4658 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4659 if (wpa_s->current_ssid) {
4660#ifdef CONFIG_SME
4661 wpa_s->sme.prev_bssid_set = 0;
4662#endif /* CONFIG_SME */
4663 wpa_sm_set_config(wpa_s->wpa, NULL);
4664 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4665 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4666 wpa_s->own_disconnect_req = 1;
4667 wpa_supplicant_deauthenticate(
4668 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4669 }
4670 ssid = wpa_s->conf->ssid;
4671 while (ssid) {
4672 struct wpa_ssid *remove_ssid = ssid;
4673 int id;
4674
4675 id = ssid->id;
4676 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004677 wpas_notify_network_removed(wpa_s, remove_ssid);
4678 wpa_config_remove_network(wpa_s->conf, id);
4679 }
4680 return 0;
4681}
4682
4683
4684/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004685 * wpa_supplicant_enable_network - Mark a configured network as enabled
4686 * @wpa_s: wpa_supplicant structure for a network interface
4687 * @ssid: wpa_ssid structure for a configured network or %NULL
4688 *
4689 * Enables the specified network or all networks if no network specified.
4690 */
4691void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4692 struct wpa_ssid *ssid)
4693{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004694 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004695 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4696 wpa_supplicant_enable_one_network(wpa_s, ssid);
4697 } else
4698 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004699
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004700 if (wpa_s->reassociate && !wpa_s->disconnected &&
4701 (!wpa_s->current_ssid ||
4702 wpa_s->wpa_state == WPA_DISCONNECTED ||
4703 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004704 if (wpa_s->sched_scanning) {
4705 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4706 "new network to scan filters");
4707 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004708 }
4709
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004710 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4711 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004712 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004713 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004714 }
4715}
4716
4717
4718/**
4719 * wpa_supplicant_disable_network - Mark a configured network as disabled
4720 * @wpa_s: wpa_supplicant structure for a network interface
4721 * @ssid: wpa_ssid structure for a configured network or %NULL
4722 *
4723 * Disables the specified network or all networks if no network specified.
4724 */
4725void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4726 struct wpa_ssid *ssid)
4727{
4728 struct wpa_ssid *other_ssid;
4729 int was_disabled;
4730
4731 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004732 if (wpa_s->sched_scanning)
4733 wpa_supplicant_cancel_sched_scan(wpa_s);
4734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4736 other_ssid = other_ssid->next) {
4737 was_disabled = other_ssid->disabled;
4738 if (was_disabled == 2)
4739 continue; /* do not change persistent P2P group
4740 * data */
4741
4742 other_ssid->disabled = 1;
4743
4744 if (was_disabled != other_ssid->disabled)
4745 wpas_notify_network_enabled_changed(
4746 wpa_s, other_ssid);
4747 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004748 if (wpa_s->current_ssid) {
4749 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4750 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004751 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004752 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004753 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004755 if (ssid == wpa_s->current_ssid) {
4756 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4757 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004758 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004760 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761
4762 was_disabled = ssid->disabled;
4763
4764 ssid->disabled = 1;
4765
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004766 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004768 if (wpa_s->sched_scanning) {
4769 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4770 "to remove network from filters");
4771 wpa_supplicant_cancel_sched_scan(wpa_s);
4772 wpa_supplicant_req_scan(wpa_s, 0, 0);
4773 }
4774 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004775 }
4776}
4777
4778
4779/**
4780 * wpa_supplicant_select_network - Attempt association with a network
4781 * @wpa_s: wpa_supplicant structure for a network interface
4782 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4783 */
4784void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4785 struct wpa_ssid *ssid)
4786{
4787
4788 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004789 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004790
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004791 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004792 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4793 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004794 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004796 disconnected = 1;
4797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004798
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004799 if (ssid)
4800 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4801
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004802 /*
4803 * Mark all other networks disabled or mark all networks enabled if no
4804 * network specified.
4805 */
4806 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4807 other_ssid = other_ssid->next) {
4808 int was_disabled = other_ssid->disabled;
4809 if (was_disabled == 2)
4810 continue; /* do not change persistent P2P group data */
4811
4812 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004813 if (was_disabled && !other_ssid->disabled)
4814 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815
4816 if (was_disabled != other_ssid->disabled)
4817 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4818 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004819
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004820 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4821 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004822 /* We are already associated with the selected network */
4823 wpa_printf(MSG_DEBUG, "Already associated with the "
4824 "selected network - do nothing");
4825 return;
4826 }
4827
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004828 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004829 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004830 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004831 wpa_s->connect_without_scan =
4832 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004833
4834 /*
4835 * Don't optimize next scan freqs since a new ESS has been
4836 * selected.
4837 */
4838 os_free(wpa_s->next_scan_freqs);
4839 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004840 } else {
4841 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004842 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004843
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004844 wpa_s->disconnected = 0;
4845 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004846 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004847 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004848 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004849 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004850 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004851 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004852
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004853 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004854 wpa_supplicant_fast_associate(wpa_s) != 1) {
4855 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004856 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004857 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004858 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859
4860 if (ssid)
4861 wpas_notify_network_selected(wpa_s, ssid);
4862}
4863
4864
4865/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004866 * wpas_remove_cred - Remove the specified credential and all the network
4867 * entries created based on the removed credential
4868 * @wpa_s: wpa_supplicant structure for a network interface
4869 * @cred: The credential to remove
4870 * Returns: 0 on success, -1 on failure
4871 */
4872int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4873{
4874 struct wpa_ssid *ssid, *next;
4875 int id;
4876
4877 if (!cred) {
4878 wpa_printf(MSG_DEBUG, "Could not find cred");
4879 return -1;
4880 }
4881
4882 id = cred->id;
4883 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4884 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4885 return -1;
4886 }
4887
4888 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4889
4890 /* Remove any network entry created based on the removed credential */
4891 ssid = wpa_s->conf->ssid;
4892 while (ssid) {
4893 next = ssid->next;
4894
4895 if (ssid->parent_cred == cred) {
4896 wpa_printf(MSG_DEBUG,
4897 "Remove network id %d since it used the removed credential",
4898 ssid->id);
4899 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4900 -1) {
4901 wpa_printf(MSG_DEBUG,
4902 "Could not find network id=%d",
4903 ssid->id);
4904 }
4905 }
4906
4907 ssid = next;
4908 }
4909
4910 return 0;
4911}
4912
4913
4914/**
4915 * wpas_remove_cred - Remove all the Interworking credentials
4916 * @wpa_s: wpa_supplicant structure for a network interface
4917 * Returns: 0 on success, -1 on failure
4918 */
4919int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4920{
4921 int res, ret = 0;
4922 struct wpa_cred *cred, *prev;
4923
4924 cred = wpa_s->conf->cred;
4925 while (cred) {
4926 prev = cred;
4927 cred = cred->next;
4928 res = wpas_remove_cred(wpa_s, prev);
4929 if (res < 0) {
4930 wpa_printf(MSG_DEBUG,
4931 "Removal of all credentials failed - failed to remove credential id=%d",
4932 prev->id);
4933 ret = -1;
4934 }
4935 }
4936
4937 return ret;
4938}
4939
4940
4941/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004942 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4943 * @wpa_s: wpa_supplicant structure for a network interface
4944 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4945 * @pkcs11_module_path: PKCS #11 module path or NULL
4946 * Returns: 0 on success; -1 on failure
4947 *
4948 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4949 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4950 * module path fails the paths will be reset to the default value (NULL).
4951 */
4952int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4953 const char *pkcs11_engine_path,
4954 const char *pkcs11_module_path)
4955{
4956 char *pkcs11_engine_path_copy = NULL;
4957 char *pkcs11_module_path_copy = NULL;
4958
4959 if (pkcs11_engine_path != NULL) {
4960 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4961 if (pkcs11_engine_path_copy == NULL)
4962 return -1;
4963 }
4964 if (pkcs11_module_path != NULL) {
4965 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004966 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004967 os_free(pkcs11_engine_path_copy);
4968 return -1;
4969 }
4970 }
4971
4972 os_free(wpa_s->conf->pkcs11_engine_path);
4973 os_free(wpa_s->conf->pkcs11_module_path);
4974 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4975 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4976
4977 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4978 eapol_sm_deinit(wpa_s->eapol);
4979 wpa_s->eapol = NULL;
4980 if (wpa_supplicant_init_eapol(wpa_s)) {
4981 /* Error -> Reset paths to the default value (NULL) once. */
4982 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4983 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4984 NULL);
4985
4986 return -1;
4987 }
4988 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4989
4990 return 0;
4991}
4992
4993
4994/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004995 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4996 * @wpa_s: wpa_supplicant structure for a network interface
4997 * @ap_scan: AP scan mode
4998 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4999 *
5000 */
5001int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5002{
5003
5004 int old_ap_scan;
5005
5006 if (ap_scan < 0 || ap_scan > 2)
5007 return -1;
5008
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005009 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5010 wpa_printf(MSG_INFO,
5011 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5012 }
5013
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005014#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005015 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5016 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5017 wpa_s->wpa_state < WPA_COMPLETED) {
5018 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5019 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005020 return 0;
5021 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005022#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005024 old_ap_scan = wpa_s->conf->ap_scan;
5025 wpa_s->conf->ap_scan = ap_scan;
5026
5027 if (old_ap_scan != wpa_s->conf->ap_scan)
5028 wpas_notify_ap_scan_changed(wpa_s);
5029
5030 return 0;
5031}
5032
5033
5034/**
5035 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5036 * @wpa_s: wpa_supplicant structure for a network interface
5037 * @expire_age: Expiration age in seconds
5038 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5039 *
5040 */
5041int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5042 unsigned int bss_expire_age)
5043{
5044 if (bss_expire_age < 10) {
5045 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5046 bss_expire_age);
5047 return -1;
5048 }
5049 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5050 bss_expire_age);
5051 wpa_s->conf->bss_expiration_age = bss_expire_age;
5052
5053 return 0;
5054}
5055
5056
5057/**
5058 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5059 * @wpa_s: wpa_supplicant structure for a network interface
5060 * @expire_count: number of scans after which an unseen BSS is reclaimed
5061 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5062 *
5063 */
5064int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5065 unsigned int bss_expire_count)
5066{
5067 if (bss_expire_count < 1) {
5068 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5069 bss_expire_count);
5070 return -1;
5071 }
5072 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5073 bss_expire_count);
5074 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5075
5076 return 0;
5077}
5078
5079
5080/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005081 * wpa_supplicant_set_scan_interval - Set scan interval
5082 * @wpa_s: wpa_supplicant structure for a network interface
5083 * @scan_interval: scan interval in seconds
5084 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5085 *
5086 */
5087int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5088 int scan_interval)
5089{
5090 if (scan_interval < 0) {
5091 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5092 scan_interval);
5093 return -1;
5094 }
5095 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5096 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005097 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005098
5099 return 0;
5100}
5101
5102
5103/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005104 * wpa_supplicant_set_debug_params - Set global debug params
5105 * @global: wpa_global structure
5106 * @debug_level: debug level
5107 * @debug_timestamp: determines if show timestamp in debug data
5108 * @debug_show_keys: determines if show keys in debug data
5109 * Returns: 0 if succeed or -1 if debug_level has wrong value
5110 */
5111int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5112 int debug_timestamp, int debug_show_keys)
5113{
5114
5115 int old_level, old_timestamp, old_show_keys;
5116
5117 /* check for allowed debuglevels */
5118 if (debug_level != MSG_EXCESSIVE &&
5119 debug_level != MSG_MSGDUMP &&
5120 debug_level != MSG_DEBUG &&
5121 debug_level != MSG_INFO &&
5122 debug_level != MSG_WARNING &&
5123 debug_level != MSG_ERROR)
5124 return -1;
5125
5126 old_level = wpa_debug_level;
5127 old_timestamp = wpa_debug_timestamp;
5128 old_show_keys = wpa_debug_show_keys;
5129
5130 wpa_debug_level = debug_level;
5131 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5132 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5133
5134 if (wpa_debug_level != old_level)
5135 wpas_notify_debug_level_changed(global);
5136 if (wpa_debug_timestamp != old_timestamp)
5137 wpas_notify_debug_timestamp_changed(global);
5138 if (wpa_debug_show_keys != old_show_keys)
5139 wpas_notify_debug_show_keys_changed(global);
5140
5141 return 0;
5142}
5143
5144
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005145#ifdef CONFIG_OWE
5146static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5147 const u8 *entry_ssid, size_t entry_ssid_len)
5148{
5149 const u8 *owe, *pos, *end;
5150 u8 ssid_len;
5151 struct wpa_bss *bss;
5152
5153 /* Check network profile SSID aganst the SSID in the
5154 * OWE Transition Mode element. */
5155
5156 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5157 if (!bss)
5158 return 0;
5159
5160 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5161 if (!owe)
5162 return 0;
5163
5164 pos = owe + 6;
5165 end = owe + 2 + owe[1];
5166
5167 if (end - pos < ETH_ALEN + 1)
5168 return 0;
5169 pos += ETH_ALEN;
5170 ssid_len = *pos++;
5171 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5172 return 0;
5173
5174 return entry_ssid_len == ssid_len &&
5175 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5176}
5177#endif /* CONFIG_OWE */
5178
5179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005180/**
5181 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5182 * @wpa_s: Pointer to wpa_supplicant data
5183 * Returns: A pointer to the current network structure or %NULL on failure
5184 */
5185struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5186{
5187 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005188 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189 int res;
5190 size_t ssid_len;
5191 u8 bssid[ETH_ALEN];
5192 int wired;
5193
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005194 res = wpa_drv_get_ssid(wpa_s, ssid);
5195 if (res < 0) {
5196 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5197 "driver");
5198 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005200 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005201
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005202 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5204 "driver");
5205 return NULL;
5206 }
5207
5208 wired = wpa_s->conf->ap_scan == 0 &&
5209 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5210
5211 entry = wpa_s->conf->ssid;
5212 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005213 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005214 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005215 (!entry->ssid ||
5216 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5217 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005218 (!entry->bssid_set ||
5219 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5220 return entry;
5221#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005222 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005223 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5224 (entry->ssid == NULL || entry->ssid_len == 0) &&
5225 (!entry->bssid_set ||
5226 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5227 return entry;
5228#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005229
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005230#ifdef CONFIG_OWE
5231 if (!wpas_network_disabled(wpa_s, entry) &&
5232 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5233 entry->ssid_len) &&
5234 (!entry->bssid_set ||
5235 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5236 return entry;
5237#endif /* CONFIG_OWE */
5238
Dmitry Shmidt04949592012-07-19 12:16:46 -07005239 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005240 entry->ssid_len == 0 &&
5241 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5242 return entry;
5243
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005244 entry = entry->next;
5245 }
5246
5247 return NULL;
5248}
5249
5250
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005251static int select_driver(struct wpa_supplicant *wpa_s, int i)
5252{
5253 struct wpa_global *global = wpa_s->global;
5254
5255 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005256 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005257 if (global->drv_priv[i] == NULL) {
5258 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5259 "'%s'", wpa_drivers[i]->name);
5260 return -1;
5261 }
5262 }
5263
5264 wpa_s->driver = wpa_drivers[i];
5265 wpa_s->global_drv_priv = global->drv_priv[i];
5266
5267 return 0;
5268}
5269
5270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005271static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5272 const char *name)
5273{
5274 int i;
5275 size_t len;
5276 const char *pos, *driver = name;
5277
5278 if (wpa_s == NULL)
5279 return -1;
5280
5281 if (wpa_drivers[0] == NULL) {
5282 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5283 "wpa_supplicant");
5284 return -1;
5285 }
5286
5287 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005288 /* Default to first successful driver in the list */
5289 for (i = 0; wpa_drivers[i]; i++) {
5290 if (select_driver(wpa_s, i) == 0)
5291 return 0;
5292 }
5293 /* Drivers have each reported failure, so no wpa_msg() here. */
5294 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005295 }
5296
5297 do {
5298 pos = os_strchr(driver, ',');
5299 if (pos)
5300 len = pos - driver;
5301 else
5302 len = os_strlen(driver);
5303
5304 for (i = 0; wpa_drivers[i]; i++) {
5305 if (os_strlen(wpa_drivers[i]->name) == len &&
5306 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005307 0) {
5308 /* First driver that succeeds wins */
5309 if (select_driver(wpa_s, i) == 0)
5310 return 0;
5311 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005312 }
5313
5314 driver = pos + 1;
5315 } while (pos);
5316
5317 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5318 return -1;
5319}
5320
5321
5322/**
5323 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5324 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5325 * with struct wpa_driver_ops::init()
5326 * @src_addr: Source address of the EAPOL frame
5327 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5328 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005329 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005330 *
5331 * This function is called for each received EAPOL frame. Most driver
5332 * interfaces rely on more generic OS mechanism for receiving frames through
5333 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5334 * take care of received EAPOL frames and deliver them to the core supplicant
5335 * code by calling this function.
5336 */
5337void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005338 const u8 *buf, size_t len,
5339 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005340{
5341 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005342 const u8 *connected_addr = wpa_s->valid_links ?
5343 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005344
Sunil8cd6f4d2022-06-28 18:40:46 +00005345 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5346 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005347 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5348
Hai Shalomc1a21442022-02-04 13:43:00 -08005349 if (wpa_s->own_disconnect_req) {
5350 wpa_printf(MSG_DEBUG,
5351 "Drop received EAPOL frame as we are disconnecting");
5352 return;
5353 }
5354
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005355#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005356 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5357 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005358 if (wpa_s->ignore_auth_resp) {
5359 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5360 return;
5361 }
5362#endif /* CONFIG_TESTING_OPTIONS */
5363
Jouni Malinena05074c2012-12-21 21:35:35 +02005364 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5365 (wpa_s->last_eapol_matches_bssid &&
5366#ifdef CONFIG_AP
5367 !wpa_s->ap_iface &&
5368#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005369 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005370 /*
5371 * There is possible race condition between receiving the
5372 * association event and the EAPOL frame since they are coming
5373 * through different paths from the driver. In order to avoid
5374 * issues in trying to process the EAPOL frame before receiving
5375 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005376 * the association event is received. This may also be needed in
5377 * driver-based roaming case, so also use src_addr != BSSID as a
5378 * trigger if we have previously confirmed that the
5379 * Authenticator uses BSSID as the src_addr (which is not the
5380 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005381 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005382 wpa_dbg(wpa_s, MSG_DEBUG,
5383 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5384 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005385 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005386 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005387 wpabuf_free(wpa_s->pending_eapol_rx);
5388 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5389 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005390 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005391 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5392 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005393 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005394 }
5395 return;
5396 }
5397
Jouni Malinena05074c2012-12-21 21:35:35 +02005398 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005399 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005400
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005401#ifdef CONFIG_AP
5402 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005403 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5404 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005405 return;
5406 }
5407#endif /* CONFIG_AP */
5408
5409 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5410 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5411 "no key management is configured");
5412 return;
5413 }
5414
5415 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005416 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005417 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5418 wpa_s->wpa_state != WPA_COMPLETED) &&
5419 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005420 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005421 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005422 int timeout = 10;
5423
5424 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5425 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5426 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5427 /* Use longer timeout for IEEE 802.1X/EAP */
5428 timeout = 70;
5429 }
5430
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005431#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005432 if (wpa_s->current_ssid && wpa_s->current_bss &&
5433 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5434 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5435 /*
5436 * Use shorter timeout if going through WPS AP iteration
5437 * for PIN config method with an AP that does not
5438 * advertise Selected Registrar.
5439 */
5440 struct wpabuf *wps_ie;
5441
5442 wps_ie = wpa_bss_get_vendor_ie_multi(
5443 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5444 if (wps_ie &&
5445 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5446 timeout = 10;
5447 wpabuf_free(wps_ie);
5448 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005449#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005450
5451 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005452 }
5453 wpa_s->eapol_received++;
5454
5455 if (wpa_s->countermeasures) {
5456 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5457 "EAPOL packet");
5458 return;
5459 }
5460
5461#ifdef CONFIG_IBSS_RSN
5462 if (wpa_s->current_ssid &&
5463 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005464 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5465 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005466 return;
5467 }
5468#endif /* CONFIG_IBSS_RSN */
5469
5470 /* Source address of the incoming EAPOL frame could be compared to the
5471 * current BSSID. However, it is possible that a centralized
5472 * Authenticator could be using another MAC address than the BSSID of
5473 * an AP, so just allow any address to be used for now. The replies are
5474 * still sent to the current BSSID (if available), though. */
5475
5476 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5477 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005478 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5479 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005480 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5481 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005482 return;
5483 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005484 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005485 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005486 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5487 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005488 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005489 * handshake processing which would normally set portValid. We
5490 * need this to allow the EAPOL state machines to be completed
5491 * without going through EAPOL-Key handshake.
5492 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005493 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005494 }
5495}
5496
5497
Sunil8cd6f4d2022-06-28 18:40:46 +00005498static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5499 const u8 *buf, size_t len)
5500{
5501 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5502 FRAME_ENCRYPTION_UNKNOWN);
5503}
5504
5505
Hai Shalomb755a2a2020-04-23 21:49:02 -07005506static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5507{
5508 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5509 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5510}
5511
5512
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005513int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005514{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005515 u8 prev_mac_addr[ETH_ALEN];
5516
5517 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5518
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005519 if ((!wpa_s->p2p_mgmt ||
5520 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5521 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005522 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005523 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5524 wpa_drv_get_mac_addr(wpa_s),
5525 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005526 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005527 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005528 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005529 if (wpa_s->l2 == NULL)
5530 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005531
5532 if (l2_packet_set_packet_filter(wpa_s->l2,
5533 L2_PACKET_FILTER_PKTTYPE))
5534 wpa_dbg(wpa_s, MSG_DEBUG,
5535 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005536
5537 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5538 wpa_msg(wpa_s, MSG_ERROR,
5539 "Failed to get own L2 address");
5540 return -1;
5541 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542 } else {
5543 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5544 if (addr)
5545 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5546 }
5547
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005548 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005549 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005550
Hai Shalomc3565922019-10-28 11:58:20 -07005551#ifdef CONFIG_FST
5552 if (wpa_s->fst)
5553 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5554#endif /* CONFIG_FST */
5555
Sunil Ravi77d572f2023-01-17 23:58:31 +00005556 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5557 wpas_notify_mac_address_changed(wpa_s);
5558
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005559 return 0;
5560}
5561
5562
Dmitry Shmidt04949592012-07-19 12:16:46 -07005563static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5564 const u8 *buf, size_t len)
5565{
5566 struct wpa_supplicant *wpa_s = ctx;
5567 const struct l2_ethhdr *eth;
5568
5569 if (len < sizeof(*eth))
5570 return;
5571 eth = (const struct l2_ethhdr *) buf;
5572
5573 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5574 !(eth->h_dest[0] & 0x01)) {
5575 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5576 " (bridge - not for this interface - ignore)",
5577 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5578 return;
5579 }
5580
5581 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5582 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5583 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005584 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005585}
5586
5587
Hai Shalom899fcc72020-10-19 14:38:18 -07005588int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5589 const char *bridge_ifname)
5590{
5591 if (wpa_s->wpa_state > WPA_SCANNING)
5592 return -EBUSY;
5593
5594 if (bridge_ifname &&
5595 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5596 return -EINVAL;
5597
5598 if (!bridge_ifname)
5599 bridge_ifname = "";
5600
5601 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5602 return 0;
5603
5604 if (wpa_s->l2_br) {
5605 l2_packet_deinit(wpa_s->l2_br);
5606 wpa_s->l2_br = NULL;
5607 }
5608
5609 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5610 sizeof(wpa_s->bridge_ifname));
5611
5612 if (wpa_s->bridge_ifname[0]) {
5613 wpa_dbg(wpa_s, MSG_DEBUG,
5614 "Receiving packets from bridge interface '%s'",
5615 wpa_s->bridge_ifname);
5616 wpa_s->l2_br = l2_packet_init_bridge(
5617 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5618 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5619 if (!wpa_s->l2_br) {
5620 wpa_msg(wpa_s, MSG_ERROR,
5621 "Failed to open l2_packet connection for the bridge interface '%s'",
5622 wpa_s->bridge_ifname);
5623 goto fail;
5624 }
5625 }
5626
5627#ifdef CONFIG_TDLS
5628 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5629 goto fail;
5630#endif /* CONFIG_TDLS */
5631
5632 return 0;
5633fail:
5634 wpa_s->bridge_ifname[0] = 0;
5635 if (wpa_s->l2_br) {
5636 l2_packet_deinit(wpa_s->l2_br);
5637 wpa_s->l2_br = NULL;
5638 }
5639#ifdef CONFIG_TDLS
5640 if (!wpa_s->p2p_mgmt)
5641 wpa_tdls_init(wpa_s->wpa);
5642#endif /* CONFIG_TDLS */
5643 return -EIO;
5644}
5645
5646
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005647/**
5648 * wpa_supplicant_driver_init - Initialize driver interface parameters
5649 * @wpa_s: Pointer to wpa_supplicant data
5650 * Returns: 0 on success, -1 on failure
5651 *
5652 * This function is called to initialize driver interface parameters.
5653 * wpa_drv_init() must have been called before this function to initialize the
5654 * driver interface.
5655 */
5656int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5657{
5658 static int interface_count = 0;
5659
5660 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5661 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005662
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005663 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5664 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005665 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005666 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5667
Hai Shalomb755a2a2020-04-23 21:49:02 -07005668 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005669 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5670 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005671 wpa_s->l2_br = l2_packet_init_bridge(
5672 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5673 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005674 if (wpa_s->l2_br == NULL) {
5675 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5676 "connection for the bridge interface '%s'",
5677 wpa_s->bridge_ifname);
5678 return -1;
5679 }
5680 }
5681
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005682 if (wpa_s->conf->ap_scan == 2 &&
5683 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5684 wpa_printf(MSG_INFO,
5685 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5686 }
5687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005688 wpa_clear_keys(wpa_s, NULL);
5689
5690 /* Make sure that TKIP countermeasures are not left enabled (could
5691 * happen if wpa_supplicant is killed during countermeasures. */
5692 wpa_drv_set_countermeasures(wpa_s, 0);
5693
5694 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5695 wpa_drv_flush_pmkid(wpa_s);
5696
5697 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005698 wpa_s->prev_scan_wildcard = 0;
5699
Dmitry Shmidt04949592012-07-19 12:16:46 -07005700 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005701 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5702 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5703 interface_count = 0;
5704 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005705#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005706 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005707 wpa_supplicant_delayed_sched_scan(wpa_s,
5708 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005709 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005710 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005711 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005712#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713 interface_count++;
5714 } else
5715 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5716
5717 return 0;
5718}
5719
5720
5721static int wpa_supplicant_daemon(const char *pid_file)
5722{
5723 wpa_printf(MSG_DEBUG, "Daemonize..");
5724 return os_daemonize(pid_file);
5725}
5726
5727
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005728static struct wpa_supplicant *
5729wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005730{
5731 struct wpa_supplicant *wpa_s;
5732
5733 wpa_s = os_zalloc(sizeof(*wpa_s));
5734 if (wpa_s == NULL)
5735 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005736 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005737 wpa_s->scan_interval = 5;
5738 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005739 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005740 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005741 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005742 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005744 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005745 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005746#ifdef CONFIG_TESTING_OPTIONS
5747 dl_list_init(&wpa_s->drv_signal_override);
5748#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005749 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 return wpa_s;
5752}
5753
5754
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005755#ifdef CONFIG_HT_OVERRIDES
5756
5757static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5758 struct ieee80211_ht_capabilities *htcaps,
5759 struct ieee80211_ht_capabilities *htcaps_mask,
5760 const char *ht_mcs)
5761{
5762 /* parse ht_mcs into hex array */
5763 int i;
5764 const char *tmp = ht_mcs;
5765 char *end = NULL;
5766
5767 /* If ht_mcs is null, do not set anything */
5768 if (!ht_mcs)
5769 return 0;
5770
5771 /* This is what we are setting in the kernel */
5772 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5773
5774 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5775
5776 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005777 long v;
5778
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005779 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005780 v = strtol(tmp, &end, 16);
5781
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005782 if (errno == 0) {
5783 wpa_msg(wpa_s, MSG_DEBUG,
5784 "htcap value[%i]: %ld end: %p tmp: %p",
5785 i, v, end, tmp);
5786 if (end == tmp)
5787 break;
5788
5789 htcaps->supported_mcs_set[i] = v;
5790 tmp = end;
5791 } else {
5792 wpa_msg(wpa_s, MSG_ERROR,
5793 "Failed to parse ht-mcs: %s, error: %s\n",
5794 ht_mcs, strerror(errno));
5795 return -1;
5796 }
5797 }
5798
5799 /*
5800 * If we were able to parse any values, then set mask for the MCS set.
5801 */
5802 if (i) {
5803 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5804 IEEE80211_HT_MCS_MASK_LEN - 1);
5805 /* skip the 3 reserved bits */
5806 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5807 0x1f;
5808 }
5809
5810 return 0;
5811}
5812
5813
5814static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5815 struct ieee80211_ht_capabilities *htcaps,
5816 struct ieee80211_ht_capabilities *htcaps_mask,
5817 int disabled)
5818{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005819 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005820
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005821 if (disabled == -1)
5822 return 0;
5823
Hai Shalom74f70d42019-02-11 14:42:39 -08005824 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5825
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005826 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5827 htcaps_mask->ht_capabilities_info |= msk;
5828 if (disabled)
5829 htcaps->ht_capabilities_info &= msk;
5830 else
5831 htcaps->ht_capabilities_info |= msk;
5832
5833 return 0;
5834}
5835
5836
5837static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5838 struct ieee80211_ht_capabilities *htcaps,
5839 struct ieee80211_ht_capabilities *htcaps_mask,
5840 int factor)
5841{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005842 if (factor == -1)
5843 return 0;
5844
Hai Shalom74f70d42019-02-11 14:42:39 -08005845 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5846
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005847 if (factor < 0 || factor > 3) {
5848 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5849 "Must be 0-3 or -1", factor);
5850 return -EINVAL;
5851 }
5852
5853 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5854 htcaps->a_mpdu_params &= ~0x3;
5855 htcaps->a_mpdu_params |= factor & 0x3;
5856
5857 return 0;
5858}
5859
5860
5861static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5862 struct ieee80211_ht_capabilities *htcaps,
5863 struct ieee80211_ht_capabilities *htcaps_mask,
5864 int density)
5865{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005866 if (density == -1)
5867 return 0;
5868
Hai Shalom74f70d42019-02-11 14:42:39 -08005869 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5870
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005871 if (density < 0 || density > 7) {
5872 wpa_msg(wpa_s, MSG_ERROR,
5873 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5874 density);
5875 return -EINVAL;
5876 }
5877
5878 htcaps_mask->a_mpdu_params |= 0x1C;
5879 htcaps->a_mpdu_params &= ~(0x1C);
5880 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5881
5882 return 0;
5883}
5884
5885
5886static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5887 struct ieee80211_ht_capabilities *htcaps,
5888 struct ieee80211_ht_capabilities *htcaps_mask,
5889 int disabled)
5890{
Hai Shalom74f70d42019-02-11 14:42:39 -08005891 if (disabled)
5892 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005893
Paul Stewart092955c2017-02-06 09:13:09 -08005894 set_disable_ht40(htcaps, disabled);
5895 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005896
5897 return 0;
5898}
5899
5900
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005901static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5902 struct ieee80211_ht_capabilities *htcaps,
5903 struct ieee80211_ht_capabilities *htcaps_mask,
5904 int disabled)
5905{
5906 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005907 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5908 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005909
Hai Shalom74f70d42019-02-11 14:42:39 -08005910 if (disabled)
5911 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005912
5913 if (disabled)
5914 htcaps->ht_capabilities_info &= ~msk;
5915 else
5916 htcaps->ht_capabilities_info |= msk;
5917
5918 htcaps_mask->ht_capabilities_info |= msk;
5919
5920 return 0;
5921}
5922
5923
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005924static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5925 struct ieee80211_ht_capabilities *htcaps,
5926 struct ieee80211_ht_capabilities *htcaps_mask,
5927 int disabled)
5928{
5929 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005930 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005931
Hai Shalom74f70d42019-02-11 14:42:39 -08005932 if (disabled)
5933 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005934
5935 if (disabled)
5936 htcaps->ht_capabilities_info &= ~msk;
5937 else
5938 htcaps->ht_capabilities_info |= msk;
5939
5940 htcaps_mask->ht_capabilities_info |= msk;
5941
5942 return 0;
5943}
5944
5945
Hai Shalom74f70d42019-02-11 14:42:39 -08005946static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5947 struct ieee80211_ht_capabilities *htcaps,
5948 struct ieee80211_ht_capabilities *htcaps_mask,
5949 int tx_stbc)
5950{
5951 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5952
5953 if (tx_stbc == -1)
5954 return 0;
5955
5956 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5957
5958 if (tx_stbc < 0 || tx_stbc > 1) {
5959 wpa_msg(wpa_s, MSG_ERROR,
5960 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5961 return -EINVAL;
5962 }
5963
5964 htcaps_mask->ht_capabilities_info |= msk;
5965 htcaps->ht_capabilities_info &= ~msk;
5966 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5967
5968 return 0;
5969}
5970
5971
5972static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5973 struct ieee80211_ht_capabilities *htcaps,
5974 struct ieee80211_ht_capabilities *htcaps_mask,
5975 int rx_stbc)
5976{
5977 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5978
5979 if (rx_stbc == -1)
5980 return 0;
5981
5982 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5983
5984 if (rx_stbc < 0 || rx_stbc > 3) {
5985 wpa_msg(wpa_s, MSG_ERROR,
5986 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5987 return -EINVAL;
5988 }
5989
5990 htcaps_mask->ht_capabilities_info |= msk;
5991 htcaps->ht_capabilities_info &= ~msk;
5992 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5993
5994 return 0;
5995}
5996
5997
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005998void wpa_supplicant_apply_ht_overrides(
5999 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6000 struct wpa_driver_associate_params *params)
6001{
6002 struct ieee80211_ht_capabilities *htcaps;
6003 struct ieee80211_ht_capabilities *htcaps_mask;
6004
6005 if (!ssid)
6006 return;
6007
6008 params->disable_ht = ssid->disable_ht;
6009 if (!params->htcaps || !params->htcaps_mask)
6010 return;
6011
6012 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6013 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6014 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6015 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6016 ssid->disable_max_amsdu);
6017 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6018 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6019 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006020 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006021 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006022 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6023 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006024
6025 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006026 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006027 htcaps->ht_capabilities_info |= bit;
6028 htcaps_mask->ht_capabilities_info |= bit;
6029 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006030}
6031
6032#endif /* CONFIG_HT_OVERRIDES */
6033
6034
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006035#ifdef CONFIG_VHT_OVERRIDES
6036void wpa_supplicant_apply_vht_overrides(
6037 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6038 struct wpa_driver_associate_params *params)
6039{
6040 struct ieee80211_vht_capabilities *vhtcaps;
6041 struct ieee80211_vht_capabilities *vhtcaps_mask;
6042
6043 if (!ssid)
6044 return;
6045
6046 params->disable_vht = ssid->disable_vht;
6047
6048 vhtcaps = (void *) params->vhtcaps;
6049 vhtcaps_mask = (void *) params->vhtcaps_mask;
6050
6051 if (!vhtcaps || !vhtcaps_mask)
6052 return;
6053
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006054 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6055 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006056
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006057#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006058 if (ssid->disable_sgi) {
6059 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6060 VHT_CAP_SHORT_GI_160);
6061 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6062 VHT_CAP_SHORT_GI_160);
6063 wpa_msg(wpa_s, MSG_DEBUG,
6064 "disable-sgi override specified, vht-caps: 0x%x",
6065 vhtcaps->vht_capabilities_info);
6066 }
6067
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006068 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006069 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6070 int max_ampdu;
6071
6072 max_ampdu = (ssid->vht_capa &
6073 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6074 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006075
6076 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6077 wpa_set_ampdu_factor(wpa_s,
6078 (void *) params->htcaps,
6079 (void *) params->htcaps_mask,
6080 max_ampdu);
6081 }
6082#endif /* CONFIG_HT_OVERRIDES */
6083
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006084#define OVERRIDE_MCS(i) \
6085 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6086 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006087 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006088 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006089 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6090 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006091 } \
6092 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6093 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006094 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006095 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006096 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6097 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006098 }
6099
6100 OVERRIDE_MCS(1);
6101 OVERRIDE_MCS(2);
6102 OVERRIDE_MCS(3);
6103 OVERRIDE_MCS(4);
6104 OVERRIDE_MCS(5);
6105 OVERRIDE_MCS(6);
6106 OVERRIDE_MCS(7);
6107 OVERRIDE_MCS(8);
6108}
6109#endif /* CONFIG_VHT_OVERRIDES */
6110
6111
Hai Shalomfdcde762020-04-02 11:19:20 -07006112#ifdef CONFIG_HE_OVERRIDES
6113void wpa_supplicant_apply_he_overrides(
6114 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6115 struct wpa_driver_associate_params *params)
6116{
6117 if (!ssid)
6118 return;
6119
6120 params->disable_he = ssid->disable_he;
6121}
6122#endif /* CONFIG_HE_OVERRIDES */
6123
6124
Sunil Ravi77d572f2023-01-17 23:58:31 +00006125void wpa_supplicant_apply_eht_overrides(
6126 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6127 struct wpa_driver_associate_params *params)
6128{
6129 if (!ssid)
6130 return;
6131
6132 params->disable_eht = ssid->disable_eht;
6133}
6134
6135
Dmitry Shmidt04949592012-07-19 12:16:46 -07006136static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6137{
6138#ifdef PCSC_FUNCS
6139 size_t len;
6140
6141 if (!wpa_s->conf->pcsc_reader)
6142 return 0;
6143
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006144 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006145 if (!wpa_s->scard)
6146 return 1;
6147
6148 if (wpa_s->conf->pcsc_pin &&
6149 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6150 scard_deinit(wpa_s->scard);
6151 wpa_s->scard = NULL;
6152 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6153 return -1;
6154 }
6155
6156 len = sizeof(wpa_s->imsi) - 1;
6157 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6158 scard_deinit(wpa_s->scard);
6159 wpa_s->scard = NULL;
6160 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6161 return -1;
6162 }
6163 wpa_s->imsi[len] = '\0';
6164
6165 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6166
6167 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6168 wpa_s->imsi, wpa_s->mnc_len);
6169
6170 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6171 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6172#endif /* PCSC_FUNCS */
6173
6174 return 0;
6175}
6176
6177
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006178int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6179{
6180 char *val, *pos;
6181
6182 ext_password_deinit(wpa_s->ext_pw);
6183 wpa_s->ext_pw = NULL;
6184 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6185
6186 if (!wpa_s->conf->ext_password_backend)
6187 return 0;
6188
6189 val = os_strdup(wpa_s->conf->ext_password_backend);
6190 if (val == NULL)
6191 return -1;
6192 pos = os_strchr(val, ':');
6193 if (pos)
6194 *pos++ = '\0';
6195
6196 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6197
6198 wpa_s->ext_pw = ext_password_init(val, pos);
6199 os_free(val);
6200 if (wpa_s->ext_pw == NULL) {
6201 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6202 return -1;
6203 }
6204 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6205
6206 return 0;
6207}
6208
6209
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006210#ifdef CONFIG_FST
6211
6212static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6213{
6214 struct wpa_supplicant *wpa_s = ctx;
6215
6216 return (is_zero_ether_addr(wpa_s->bssid) ||
6217 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6218}
6219
6220
6221static void wpas_fst_get_channel_info_cb(void *ctx,
6222 enum hostapd_hw_mode *hw_mode,
6223 u8 *channel)
6224{
6225 struct wpa_supplicant *wpa_s = ctx;
6226
6227 if (wpa_s->current_bss) {
6228 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6229 channel);
6230 } else if (wpa_s->hw.num_modes) {
6231 *hw_mode = wpa_s->hw.modes[0].mode;
6232 } else {
6233 WPA_ASSERT(0);
6234 *hw_mode = 0;
6235 }
6236}
6237
6238
6239static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6240{
6241 struct wpa_supplicant *wpa_s = ctx;
6242
6243 *modes = wpa_s->hw.modes;
6244 return wpa_s->hw.num_modes;
6245}
6246
6247
6248static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6249{
6250 struct wpa_supplicant *wpa_s = ctx;
6251
6252 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6253 wpa_s->fst_ies = fst_ies;
6254}
6255
6256
6257static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6258{
6259 struct wpa_supplicant *wpa_s = ctx;
6260
Paul Stewart092955c2017-02-06 09:13:09 -08006261 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6262 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6263 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6264 return -1;
6265 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006266 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006267 wpa_s->own_addr, wpa_s->bssid,
6268 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006269 0);
6270}
6271
6272
6273static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6274{
6275 struct wpa_supplicant *wpa_s = ctx;
6276
6277 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6278 return wpa_s->received_mb_ies;
6279}
6280
6281
6282static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6283 const u8 *buf, size_t size)
6284{
6285 struct wpa_supplicant *wpa_s = ctx;
6286 struct mb_ies_info info;
6287
6288 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6289
6290 if (!mb_ies_info_by_ies(&info, buf, size)) {
6291 wpabuf_free(wpa_s->received_mb_ies);
6292 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6293 }
6294}
6295
6296
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006297static const u8 * wpas_fst_get_peer_first(void *ctx,
6298 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006299 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006300{
6301 struct wpa_supplicant *wpa_s = ctx;
6302
6303 *get_ctx = NULL;
6304 if (!is_zero_ether_addr(wpa_s->bssid))
6305 return (wpa_s->received_mb_ies || !mb_only) ?
6306 wpa_s->bssid : NULL;
6307 return NULL;
6308}
6309
6310
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006311static const u8 * wpas_fst_get_peer_next(void *ctx,
6312 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006313 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006314{
6315 return NULL;
6316}
6317
6318void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6319 struct fst_wpa_obj *iface_obj)
6320{
Sunil8cd6f4d2022-06-28 18:40:46 +00006321 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006322 iface_obj->ctx = wpa_s;
6323 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6324 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6325 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6326 iface_obj->set_ies = wpas_fst_set_ies_cb;
6327 iface_obj->send_action = wpas_fst_send_action_cb;
6328 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6329 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6330 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6331 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6332}
6333#endif /* CONFIG_FST */
6334
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006335static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006336 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006337{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006338 struct wowlan_triggers *triggers;
6339 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006340
6341 if (!wpa_s->conf->wowlan_triggers)
6342 return 0;
6343
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006344 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6345 if (triggers) {
6346 ret = wpa_drv_wowlan(wpa_s, triggers);
6347 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006348 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006349 return ret;
6350}
6351
6352
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006353enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006354{
6355 if (freq < 3000)
6356 return BAND_2_4_GHZ;
6357 if (freq > 50000)
6358 return BAND_60_GHZ;
6359 return BAND_5_GHZ;
6360}
6361
6362
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006363unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006364{
6365 int i;
6366 unsigned int band = 0;
6367
6368 if (freqs) {
6369 /* freqs are specified for the radio work */
6370 for (i = 0; freqs[i]; i++)
6371 band |= wpas_freq_to_band(freqs[i]);
6372 } else {
6373 /*
6374 * freqs are not specified, implies all
6375 * the supported freqs by HW
6376 */
6377 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6378 if (wpa_s->hw.modes[i].num_channels != 0) {
6379 if (wpa_s->hw.modes[i].mode ==
6380 HOSTAPD_MODE_IEEE80211B ||
6381 wpa_s->hw.modes[i].mode ==
6382 HOSTAPD_MODE_IEEE80211G)
6383 band |= BAND_2_4_GHZ;
6384 else if (wpa_s->hw.modes[i].mode ==
6385 HOSTAPD_MODE_IEEE80211A)
6386 band |= BAND_5_GHZ;
6387 else if (wpa_s->hw.modes[i].mode ==
6388 HOSTAPD_MODE_IEEE80211AD)
6389 band |= BAND_60_GHZ;
6390 else if (wpa_s->hw.modes[i].mode ==
6391 HOSTAPD_MODE_IEEE80211ANY)
6392 band = BAND_2_4_GHZ | BAND_5_GHZ |
6393 BAND_60_GHZ;
6394 }
6395 }
6396 }
6397
6398 return band;
6399}
6400
6401
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006402static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6403 const char *rn)
6404{
6405 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6406 struct wpa_radio *radio;
6407
6408 while (rn && iface) {
6409 radio = iface->radio;
6410 if (radio && os_strcmp(rn, radio->name) == 0) {
6411 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6412 wpa_s->ifname, rn);
6413 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6414 return radio;
6415 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006416
6417 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006418 }
6419
6420 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6421 wpa_s->ifname, rn ? rn : "N/A");
6422 radio = os_zalloc(sizeof(*radio));
6423 if (radio == NULL)
6424 return NULL;
6425
6426 if (rn)
6427 os_strlcpy(radio->name, rn, sizeof(radio->name));
6428 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006429 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006430 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6431
6432 return radio;
6433}
6434
6435
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006436static void radio_work_free(struct wpa_radio_work *work)
6437{
6438 if (work->wpa_s->scan_work == work) {
6439 /* This should not really happen. */
6440 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6441 work->type, work, work->started);
6442 work->wpa_s->scan_work = NULL;
6443 }
6444
6445#ifdef CONFIG_P2P
6446 if (work->wpa_s->p2p_scan_work == work) {
6447 /* This should not really happen. */
6448 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6449 work->type, work, work->started);
6450 work->wpa_s->p2p_scan_work = NULL;
6451 }
6452#endif /* CONFIG_P2P */
6453
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006454 if (work->started) {
6455 work->wpa_s->radio->num_active_works--;
6456 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006457 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006458 work->type, work,
6459 work->wpa_s->radio->num_active_works);
6460 }
6461
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006462 dl_list_del(&work->list);
6463 os_free(work);
6464}
6465
6466
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006467static int radio_work_is_connect(struct wpa_radio_work *work)
6468{
6469 return os_strcmp(work->type, "sme-connect") == 0 ||
6470 os_strcmp(work->type, "connect") == 0;
6471}
6472
6473
6474static int radio_work_is_scan(struct wpa_radio_work *work)
6475{
6476 return os_strcmp(work->type, "scan") == 0 ||
6477 os_strcmp(work->type, "p2p-scan") == 0;
6478}
6479
6480
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006481static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6482{
6483 struct wpa_radio_work *active_work = NULL;
6484 struct wpa_radio_work *tmp;
6485
6486 /* Get the active work to know the type and band. */
6487 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6488 if (tmp->started) {
6489 active_work = tmp;
6490 break;
6491 }
6492 }
6493
6494 if (!active_work) {
6495 /* No active work, start one */
6496 radio->num_active_works = 0;
6497 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6498 list) {
6499 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006500 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006501 (((struct wpa_driver_scan_params *)
6502 tmp->ctx)->only_new_results ||
6503 tmp->wpa_s->clear_driver_scan_cache))
6504 continue;
6505 return tmp;
6506 }
6507 return NULL;
6508 }
6509
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006510 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006511 /*
6512 * If the active work is either connect or sme-connect,
6513 * do not parallelize them with other radio works.
6514 */
6515 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6516 "Do not parallelize radio work with %s",
6517 active_work->type);
6518 return NULL;
6519 }
6520
6521 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6522 if (tmp->started)
6523 continue;
6524
6525 /*
6526 * If connect or sme-connect are enqueued, parallelize only
6527 * those operations ahead of them in the queue.
6528 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006529 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006530 break;
6531
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006532 /* Serialize parallel scan and p2p_scan operations on the same
6533 * interface since the driver_nl80211 mechanism for tracking
6534 * scan cookies does not yet have support for this. */
6535 if (active_work->wpa_s == tmp->wpa_s &&
6536 radio_work_is_scan(active_work) &&
6537 radio_work_is_scan(tmp)) {
6538 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6539 "Do not start work '%s' when another work '%s' is already scheduled",
6540 tmp->type, active_work->type);
6541 continue;
6542 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006543 /*
6544 * Check that the radio works are distinct and
6545 * on different bands.
6546 */
6547 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6548 (active_work->bands != tmp->bands)) {
6549 /*
6550 * If a scan has to be scheduled through nl80211 scan
6551 * interface and if an external scan is already running,
6552 * do not schedule the scan since it is likely to get
6553 * rejected by kernel.
6554 */
6555 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006556 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006557 (((struct wpa_driver_scan_params *)
6558 tmp->ctx)->only_new_results ||
6559 tmp->wpa_s->clear_driver_scan_cache))
6560 continue;
6561
6562 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6563 "active_work:%s new_work:%s",
6564 active_work->type, tmp->type);
6565 return tmp;
6566 }
6567 }
6568
6569 /* Did not find a radio work to schedule in parallel. */
6570 return NULL;
6571}
6572
6573
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006574static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6575{
6576 struct wpa_radio *radio = eloop_ctx;
6577 struct wpa_radio_work *work;
6578 struct os_reltime now, diff;
6579 struct wpa_supplicant *wpa_s;
6580
6581 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006582 if (work == NULL) {
6583 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006584 return;
6585 }
6586
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006587 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6588 radio_list);
6589
6590 if (!(wpa_s &&
6591 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6592 if (work->started)
6593 return; /* already started and still in progress */
6594
Hai Shalom60840252021-02-19 19:02:11 -08006595 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006596 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6597 return;
6598 }
6599 } else {
6600 work = NULL;
6601 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6602 /* get the work to schedule next */
6603 work = radio_work_get_next_work(radio);
6604 }
6605 if (!work)
6606 return;
6607 }
6608
6609 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006610 os_get_reltime(&now);
6611 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006612 wpa_dbg(wpa_s, MSG_DEBUG,
6613 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006614 work->type, work, diff.sec, diff.usec);
6615 work->started = 1;
6616 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006617 radio->num_active_works++;
6618
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006619 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006620
6621 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6622 radio->num_active_works < MAX_ACTIVE_WORKS)
6623 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006624}
6625
6626
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006627/*
6628 * This function removes both started and pending radio works running on
6629 * the provided interface's radio.
6630 * Prior to the removal of the radio work, its callback (cb) is called with
6631 * deinit set to be 1. Each work's callback is responsible for clearing its
6632 * internal data and restoring to a correct state.
6633 * @wpa_s: wpa_supplicant data
6634 * @type: type of works to be removed
6635 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6636 * this interface's works.
6637 */
6638void radio_remove_works(struct wpa_supplicant *wpa_s,
6639 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006640{
6641 struct wpa_radio_work *work, *tmp;
6642 struct wpa_radio *radio = wpa_s->radio;
6643
6644 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6645 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006646 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006647 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006648
6649 /* skip other ifaces' works */
6650 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006651 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006652
6653 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6654 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006655 work->cb(work, 1);
6656 radio_work_free(work);
6657 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006658
6659 /* in case we removed the started work */
6660 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006661}
6662
6663
Roshan Pius3a1667e2018-07-03 15:17:14 -07006664void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6665{
6666 struct wpa_radio_work *work;
6667 struct wpa_radio *radio = wpa_s->radio;
6668
6669 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6670 if (work->ctx != ctx)
6671 continue;
6672 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6673 work->type, work, work->started ? " (started)" : "");
6674 radio_work_free(work);
6675 break;
6676 }
6677}
6678
6679
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006680static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6681{
6682 struct wpa_radio *radio = wpa_s->radio;
6683
6684 if (!radio)
6685 return;
6686
6687 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6688 wpa_s->ifname, radio->name);
6689 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006690 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006691 /* If the interface that triggered the external scan was removed, the
6692 * external scan is no longer running. */
6693 if (wpa_s == radio->external_scan_req_interface)
6694 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006695 wpa_s->radio = NULL;
6696 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006697 return; /* Interfaces remain for this radio */
6698
6699 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006700 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006701 os_free(radio);
6702}
6703
6704
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006705void radio_work_check_next(struct wpa_supplicant *wpa_s)
6706{
6707 struct wpa_radio *radio = wpa_s->radio;
6708
6709 if (dl_list_empty(&radio->work))
6710 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006711 if (wpa_s->ext_work_in_progress) {
6712 wpa_printf(MSG_DEBUG,
6713 "External radio work in progress - delay start of pending item");
6714 return;
6715 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006716 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6717 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6718}
6719
6720
6721/**
6722 * radio_add_work - Add a radio work item
6723 * @wpa_s: Pointer to wpa_supplicant data
6724 * @freq: Frequency of the offchannel operation in MHz or 0
6725 * @type: Unique identifier for each type of work
6726 * @next: Force as the next work to be executed
6727 * @cb: Callback function for indicating when radio is available
6728 * @ctx: Context pointer for the work (work->ctx in cb())
6729 * Returns: 0 on success, -1 on failure
6730 *
6731 * This function is used to request time for an operation that requires
6732 * exclusive radio control. Once the radio is available, the registered callback
6733 * function will be called. radio_work_done() must be called once the exclusive
6734 * radio operation has been completed, so that the radio is freed for other
6735 * operations. The special case of deinit=1 is used to free the context data
6736 * during interface removal. That does not allow the callback function to start
6737 * the radio operation, i.e., it must free any resources allocated for the radio
6738 * work and return.
6739 *
6740 * The @freq parameter can be used to indicate a single channel on which the
6741 * offchannel operation will occur. This may allow multiple radio work
6742 * operations to be performed in parallel if they apply for the same channel.
6743 * Setting this to 0 indicates that the work item may use multiple channels or
6744 * requires exclusive control of the radio.
6745 */
6746int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6747 const char *type, int next,
6748 void (*cb)(struct wpa_radio_work *work, int deinit),
6749 void *ctx)
6750{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006751 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006752 struct wpa_radio_work *work;
6753 int was_empty;
6754
6755 work = os_zalloc(sizeof(*work));
6756 if (work == NULL)
6757 return -1;
6758 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6759 os_get_reltime(&work->time);
6760 work->freq = freq;
6761 work->type = type;
6762 work->wpa_s = wpa_s;
6763 work->cb = cb;
6764 work->ctx = ctx;
6765
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006766 if (freq)
6767 work->bands = wpas_freq_to_band(freq);
6768 else if (os_strcmp(type, "scan") == 0 ||
6769 os_strcmp(type, "p2p-scan") == 0)
6770 work->bands = wpas_get_bands(wpa_s,
6771 ((struct wpa_driver_scan_params *)
6772 ctx)->freqs);
6773 else
6774 work->bands = wpas_get_bands(wpa_s, NULL);
6775
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006776 was_empty = dl_list_empty(&wpa_s->radio->work);
6777 if (next)
6778 dl_list_add(&wpa_s->radio->work, &work->list);
6779 else
6780 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6781 if (was_empty) {
6782 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6783 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006784 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6785 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6786 wpa_dbg(wpa_s, MSG_DEBUG,
6787 "Try to schedule a radio work (num_active_works=%u)",
6788 radio->num_active_works);
6789 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006790 }
6791
6792 return 0;
6793}
6794
6795
6796/**
6797 * radio_work_done - Indicate that a radio work item has been completed
6798 * @work: Completed work
6799 *
6800 * This function is called once the callback function registered with
6801 * radio_add_work() has completed its work.
6802 */
6803void radio_work_done(struct wpa_radio_work *work)
6804{
6805 struct wpa_supplicant *wpa_s = work->wpa_s;
6806 struct os_reltime now, diff;
6807 unsigned int started = work->started;
6808
6809 os_get_reltime(&now);
6810 os_reltime_sub(&now, &work->time, &diff);
6811 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6812 work->type, work, started ? "done" : "canceled",
6813 diff.sec, diff.usec);
6814 radio_work_free(work);
6815 if (started)
6816 radio_work_check_next(wpa_s);
6817}
6818
6819
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006820struct wpa_radio_work *
6821radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006822{
6823 struct wpa_radio_work *work;
6824 struct wpa_radio *radio = wpa_s->radio;
6825
6826 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6827 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006828 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006829 }
6830
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006831 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006832}
6833
6834
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006835static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006836 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006837{
6838 const char *ifname, *driver, *rn;
6839
6840 driver = iface->driver;
6841next_driver:
6842 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6843 return -1;
6844
6845 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6846 if (wpa_s->drv_priv == NULL) {
6847 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006848 int level = MSG_ERROR;
6849
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006850 pos = driver ? os_strchr(driver, ',') : NULL;
6851 if (pos) {
6852 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6853 "driver interface - try next driver wrapper");
6854 driver = pos + 1;
6855 goto next_driver;
6856 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006857
6858#ifdef CONFIG_MATCH_IFACE
6859 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6860 level = MSG_DEBUG;
6861#endif /* CONFIG_MATCH_IFACE */
6862 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006863 return -1;
6864 }
6865 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6866 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6867 "driver_param '%s'", wpa_s->conf->driver_param);
6868 return -1;
6869 }
6870
6871 ifname = wpa_drv_get_ifname(wpa_s);
6872 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6873 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6874 "interface name with '%s'", ifname);
6875 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6876 }
6877
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006878 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006879 if (rn && rn[0] == '\0')
6880 rn = NULL;
6881
6882 wpa_s->radio = radio_add_interface(wpa_s, rn);
6883 if (wpa_s->radio == NULL)
6884 return -1;
6885
6886 return 0;
6887}
6888
6889
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006890#ifdef CONFIG_GAS_SERVER
6891
6892static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6893 unsigned int freq, const u8 *dst,
6894 const u8 *src, const u8 *bssid,
6895 const u8 *data, size_t data_len,
6896 enum offchannel_send_action_result result)
6897{
6898 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6899 " result=%s",
6900 freq, MAC2STR(dst),
6901 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6902 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6903 "FAILED"));
6904 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6905 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6906}
6907
6908
6909static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6910 struct wpabuf *buf, unsigned int wait_time)
6911{
6912 struct wpa_supplicant *wpa_s = ctx;
6913 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6914
6915 if (wait_time > wpa_s->max_remain_on_chan)
6916 wait_time = wpa_s->max_remain_on_chan;
6917
6918 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6919 wpabuf_head(buf), wpabuf_len(buf),
6920 wait_time, wpas_gas_server_tx_status, 0);
6921}
6922
6923#endif /* CONFIG_GAS_SERVER */
6924
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006925static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006926 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006927{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006928 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006929 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006930 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006931
6932 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6933 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6934 iface->confname ? iface->confname : "N/A",
6935 iface->driver ? iface->driver : "default",
6936 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6937 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6938
6939 if (iface->confname) {
6940#ifdef CONFIG_BACKEND_FILE
6941 wpa_s->confname = os_rel2abs_path(iface->confname);
6942 if (wpa_s->confname == NULL) {
6943 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6944 "for configuration file '%s'.",
6945 iface->confname);
6946 return -1;
6947 }
6948 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6949 iface->confname, wpa_s->confname);
6950#else /* CONFIG_BACKEND_FILE */
6951 wpa_s->confname = os_strdup(iface->confname);
6952#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00006953 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954 if (wpa_s->conf == NULL) {
6955 wpa_printf(MSG_ERROR, "Failed to read or parse "
6956 "configuration '%s'.", wpa_s->confname);
6957 return -1;
6958 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006959 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006960 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00006961 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006962 wpa_printf(MSG_ERROR,
6963 "Failed to read or parse configuration '%s'.",
6964 wpa_s->confanother);
6965 return -1;
6966 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006967
6968 /*
6969 * Override ctrl_interface and driver_param if set on command
6970 * line.
6971 */
6972 if (iface->ctrl_interface) {
6973 os_free(wpa_s->conf->ctrl_interface);
6974 wpa_s->conf->ctrl_interface =
6975 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006976 if (!wpa_s->conf->ctrl_interface) {
6977 wpa_printf(MSG_ERROR,
6978 "Failed to duplicate control interface '%s'.",
6979 iface->ctrl_interface);
6980 return -1;
6981 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006982 }
6983
6984 if (iface->driver_param) {
6985 os_free(wpa_s->conf->driver_param);
6986 wpa_s->conf->driver_param =
6987 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006988 if (!wpa_s->conf->driver_param) {
6989 wpa_printf(MSG_ERROR,
6990 "Failed to duplicate driver param '%s'.",
6991 iface->driver_param);
6992 return -1;
6993 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006994 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006995
6996 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6997 os_free(wpa_s->conf->ctrl_interface);
6998 wpa_s->conf->ctrl_interface = NULL;
6999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007000 } else
7001 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7002 iface->driver_param);
7003
7004 if (wpa_s->conf == NULL) {
7005 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7006 return -1;
7007 }
7008
7009 if (iface->ifname == NULL) {
7010 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7011 return -1;
7012 }
7013 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7014 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7015 iface->ifname);
7016 return -1;
7017 }
7018 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007019#ifdef CONFIG_MATCH_IFACE
7020 wpa_s->matched = iface->matched;
7021#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007022
7023 if (iface->bridge_ifname) {
7024 if (os_strlen(iface->bridge_ifname) >=
7025 sizeof(wpa_s->bridge_ifname)) {
7026 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7027 "name '%s'.", iface->bridge_ifname);
7028 return -1;
7029 }
7030 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7031 sizeof(wpa_s->bridge_ifname));
7032 }
7033
7034 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007035 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7036 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007037
7038 /* Initialize driver interface and register driver event handler before
7039 * L2 receive handler so that association events are processed before
7040 * EAPOL-Key packets if both become available for the same select()
7041 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007042 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007043 return -1;
7044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007045 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7046 return -1;
7047
7048 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7049 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7050 NULL);
7051 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7052
7053 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7054 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7055 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7056 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7057 "dot11RSNAConfigPMKLifetime");
7058 return -1;
7059 }
7060
7061 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7062 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7063 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7064 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7065 "dot11RSNAConfigPMKReauthThreshold");
7066 return -1;
7067 }
7068
7069 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7070 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7071 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7072 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7073 "dot11RSNAConfigSATimeout");
7074 return -1;
7075 }
7076
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007077 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7078 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007079 &wpa_s->hw.flags,
7080 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007081 if (wpa_s->hw.modes) {
7082 u16 i;
7083
7084 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7085 if (wpa_s->hw.modes[i].vht_capab) {
7086 wpa_s->hw_capab = CAPAB_VHT;
7087 break;
7088 }
7089
7090 if (wpa_s->hw.modes[i].ht_capab &
7091 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7092 wpa_s->hw_capab = CAPAB_HT40;
7093 else if (wpa_s->hw.modes[i].ht_capab &&
7094 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7095 wpa_s->hw_capab = CAPAB_HT;
7096 }
7097 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007098
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007099 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7100 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007101 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007102 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007103 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007104 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007105 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007106 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007107 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007108 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007109 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007110 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7111 wpa_s->max_sched_scan_plan_interval =
7112 capa.max_sched_scan_plan_interval;
7113 wpa_s->max_sched_scan_plan_iterations =
7114 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007115 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7116 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007117 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7118 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007119 wpa_s->extended_capa = capa.extended_capa;
7120 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7121 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007122 wpa_s->num_multichan_concurrent =
7123 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007124 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007125 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007126
7127 if (capa.mac_addr_rand_scan_supported)
7128 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7129 if (wpa_s->sched_scan_supported &&
7130 capa.mac_addr_rand_sched_scan_supported)
7131 wpa_s->mac_addr_rand_supported |=
7132 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007133
7134 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7135 if (wpa_s->extended_capa &&
7136 wpa_s->extended_capa_len >= 3 &&
7137 wpa_s->extended_capa[2] & 0x40)
7138 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007139 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007140#ifdef CONFIG_PASN
7141 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7142#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007143 if (wpa_s->max_remain_on_chan == 0)
7144 wpa_s->max_remain_on_chan = 1000;
7145
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007146 /*
7147 * Only take p2p_mgmt parameters when P2P Device is supported.
7148 * Doing it here as it determines whether l2_packet_init() will be done
7149 * during wpa_supplicant_driver_init().
7150 */
7151 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7152 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007153
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007154 if (wpa_s->num_multichan_concurrent == 0)
7155 wpa_s->num_multichan_concurrent = 1;
7156
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007157 if (wpa_supplicant_driver_init(wpa_s) < 0)
7158 return -1;
7159
7160#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007161 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007162 return -1;
7163#endif /* CONFIG_TDLS */
7164
7165 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7166 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7167 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7168 return -1;
7169 }
7170
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007171#ifdef CONFIG_FST
7172 if (wpa_s->conf->fst_group_id) {
7173 struct fst_iface_cfg cfg;
7174 struct fst_wpa_obj iface_obj;
7175
7176 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7177 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7178 sizeof(cfg.group_id));
7179 cfg.priority = wpa_s->conf->fst_priority;
7180 cfg.llt = wpa_s->conf->fst_llt;
7181
7182 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7183 &iface_obj, &cfg);
7184 if (!wpa_s->fst) {
7185 wpa_msg(wpa_s, MSG_ERROR,
7186 "FST: Cannot attach iface %s to group %s",
7187 wpa_s->ifname, cfg.group_id);
7188 return -1;
7189 }
7190 }
7191#endif /* CONFIG_FST */
7192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007193 if (wpas_wps_init(wpa_s))
7194 return -1;
7195
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007196#ifdef CONFIG_GAS_SERVER
7197 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7198 if (!wpa_s->gas_server) {
7199 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7200 return -1;
7201 }
7202#endif /* CONFIG_GAS_SERVER */
7203
7204#ifdef CONFIG_DPP
7205 if (wpas_dpp_init(wpa_s) < 0)
7206 return -1;
7207#endif /* CONFIG_DPP */
7208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007209 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7210 return -1;
7211 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7212
7213 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7214 if (wpa_s->ctrl_iface == NULL) {
7215 wpa_printf(MSG_ERROR,
7216 "Failed to initialize control interface '%s'.\n"
7217 "You may have another wpa_supplicant process "
7218 "already running or the file was\n"
7219 "left by an unclean termination of wpa_supplicant "
7220 "in which case you will need\n"
7221 "to manually remove this file before starting "
7222 "wpa_supplicant again.\n",
7223 wpa_s->conf->ctrl_interface);
7224 return -1;
7225 }
7226
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007227 wpa_s->gas = gas_query_init(wpa_s);
7228 if (wpa_s->gas == NULL) {
7229 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7230 return -1;
7231 }
7232
Roshan Pius3a1667e2018-07-03 15:17:14 -07007233 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7234 wpa_s->p2p_mgmt) &&
7235 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007236 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7237 return -1;
7238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007239
7240 if (wpa_bss_init(wpa_s) < 0)
7241 return -1;
7242
Paul Stewart092955c2017-02-06 09:13:09 -08007243#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7244#ifdef CONFIG_MESH
7245 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7246#endif /* CONFIG_MESH */
7247#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7248
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007249 /*
7250 * Set Wake-on-WLAN triggers, if configured.
7251 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7252 * have effect anyway when the interface is down).
7253 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007254 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007255 return -1;
7256
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007257#ifdef CONFIG_EAP_PROXY
7258{
7259 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007260 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7261 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007262 if (wpa_s->mnc_len > 0) {
7263 wpa_s->imsi[len] = '\0';
7264 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7265 wpa_s->imsi, wpa_s->mnc_len);
7266 } else {
7267 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7268 }
7269}
7270#endif /* CONFIG_EAP_PROXY */
7271
Dmitry Shmidt04949592012-07-19 12:16:46 -07007272 if (pcsc_reader_init(wpa_s) < 0)
7273 return -1;
7274
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007275 if (wpas_init_ext_pw(wpa_s) < 0)
7276 return -1;
7277
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007278 wpas_rrm_reset(wpa_s);
7279
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007280 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7281
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007282#ifdef CONFIG_HS20
7283 hs20_init(wpa_s);
7284#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007285#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007286 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007287 if ((wpa_s->conf->oce & OCE_STA) &&
7288 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7289 wpa_s->enable_oce = OCE_STA;
7290 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7291 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7292 /* TODO: Need to add STA-CFON support */
7293 wpa_printf(MSG_ERROR,
7294 "OCE STA-CFON feature is not yet supported");
7295 }
7296 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007297 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7298#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007299
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007300 wpa_supplicant_set_default_scan_ies(wpa_s);
7301
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007302 return 0;
7303}
7304
7305
7306static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007307 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007308{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007309 struct wpa_global *global = wpa_s->global;
7310 struct wpa_supplicant *iface, *prev;
7311
Jimmy Chen0e73c002021-08-18 13:21:30 +08007312 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007313 wpas_p2p_group_remove(wpa_s, "*");
7314
7315 iface = global->ifaces;
7316 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007317 if (iface->p2pdev == wpa_s)
7318 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007319 if (iface == wpa_s || iface->parent != wpa_s) {
7320 iface = iface->next;
7321 continue;
7322 }
7323 wpa_printf(MSG_DEBUG,
7324 "Remove remaining child interface %s from parent %s",
7325 iface->ifname, wpa_s->ifname);
7326 prev = iface;
7327 iface = iface->next;
7328 wpa_supplicant_remove_iface(global, prev, terminate);
7329 }
7330
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007331 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007332 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007333 /*
7334 * Don't deauthenticate if WoWLAN is enable and not explicitly
7335 * been configured to disconnect.
7336 */
7337 if (!wpa_drv_get_wowlan(wpa_s) ||
7338 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007339 wpa_supplicant_deauthenticate(
7340 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007341
Hai Shalomfdcde762020-04-02 11:19:20 -07007342 wpa_drv_set_countermeasures(wpa_s, 0);
7343 wpa_clear_keys(wpa_s, NULL);
7344 } else {
7345 wpa_msg(wpa_s, MSG_INFO,
7346 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7347 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007348 }
7349
7350 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007351 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007352
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007353 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007354 radio_remove_interface(wpa_s);
7355
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007356#ifdef CONFIG_FST
7357 if (wpa_s->fst) {
7358 fst_detach(wpa_s->fst);
7359 wpa_s->fst = NULL;
7360 }
7361 if (wpa_s->received_mb_ies) {
7362 wpabuf_free(wpa_s->received_mb_ies);
7363 wpa_s->received_mb_ies = NULL;
7364 }
7365#endif /* CONFIG_FST */
7366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007367 if (wpa_s->drv_priv)
7368 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007369
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007370 if (notify)
7371 wpas_notify_iface_removed(wpa_s);
7372
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007373 if (terminate)
7374 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007375
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007376 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7377 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007378
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007379#ifdef CONFIG_MESH
7380 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007381 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007382 wpa_s->ifmsh = NULL;
7383 }
7384#endif /* CONFIG_MESH */
7385
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007386 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007387 wpa_config_free(wpa_s->conf);
7388 wpa_s->conf = NULL;
7389 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007390
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007391 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007392 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007393
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007394 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007395}
7396
7397
Dmitry Shmidte4663042016-04-04 10:07:49 -07007398#ifdef CONFIG_MATCH_IFACE
7399
7400/**
7401 * wpa_supplicant_match_iface - Match an interface description to a name
7402 * @global: Pointer to global data from wpa_supplicant_init()
7403 * @ifname: Name of the interface to match
7404 * Returns: Pointer to the created interface description or %NULL on failure
7405 */
7406struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7407 const char *ifname)
7408{
7409 int i;
7410 struct wpa_interface *iface, *miface;
7411
7412 for (i = 0; i < global->params.match_iface_count; i++) {
7413 miface = &global->params.match_ifaces[i];
7414 if (!miface->ifname ||
7415 fnmatch(miface->ifname, ifname, 0) == 0) {
7416 iface = os_zalloc(sizeof(*iface));
7417 if (!iface)
7418 return NULL;
7419 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007420 if (!miface->ifname)
7421 iface->matched = WPA_IFACE_MATCHED_NULL;
7422 else
7423 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007424 iface->ifname = ifname;
7425 return iface;
7426 }
7427 }
7428
7429 return NULL;
7430}
7431
7432
7433/**
7434 * wpa_supplicant_match_existing - Match existing interfaces
7435 * @global: Pointer to global data from wpa_supplicant_init()
7436 * Returns: 0 on success, -1 on failure
7437 */
7438static int wpa_supplicant_match_existing(struct wpa_global *global)
7439{
7440 struct if_nameindex *ifi, *ifp;
7441 struct wpa_supplicant *wpa_s;
7442 struct wpa_interface *iface;
7443
7444 ifp = if_nameindex();
7445 if (!ifp) {
7446 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7447 return -1;
7448 }
7449
7450 for (ifi = ifp; ifi->if_name; ifi++) {
7451 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7452 if (wpa_s)
7453 continue;
7454 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7455 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007456 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007457 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007458 }
7459 }
7460
7461 if_freenameindex(ifp);
7462 return 0;
7463}
7464
7465#endif /* CONFIG_MATCH_IFACE */
7466
7467
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007468/**
7469 * wpa_supplicant_add_iface - Add a new network interface
7470 * @global: Pointer to global data from wpa_supplicant_init()
7471 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007472 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007473 * Returns: Pointer to the created interface or %NULL on failure
7474 *
7475 * This function is used to add new network interfaces for %wpa_supplicant.
7476 * This can be called before wpa_supplicant_run() to add interfaces before the
7477 * main event loop has been started. In addition, new interfaces can be added
7478 * dynamically while %wpa_supplicant is already running. This could happen,
7479 * e.g., when a hotplug network adapter is inserted.
7480 */
7481struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007482 struct wpa_interface *iface,
7483 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007484{
7485 struct wpa_supplicant *wpa_s;
7486 struct wpa_interface t_iface;
7487 struct wpa_ssid *ssid;
7488
7489 if (global == NULL || iface == NULL)
7490 return NULL;
7491
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007492 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007493 if (wpa_s == NULL)
7494 return NULL;
7495
7496 wpa_s->global = global;
7497
7498 t_iface = *iface;
7499 if (global->params.override_driver) {
7500 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7501 "('%s' -> '%s')",
7502 iface->driver, global->params.override_driver);
7503 t_iface.driver = global->params.override_driver;
7504 }
7505 if (global->params.override_ctrl_interface) {
7506 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7507 "ctrl_interface ('%s' -> '%s')",
7508 iface->ctrl_interface,
7509 global->params.override_ctrl_interface);
7510 t_iface.ctrl_interface =
7511 global->params.override_ctrl_interface;
7512 }
7513 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7514 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7515 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007516 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007517 return NULL;
7518 }
7519
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007520 /* Notify the control interfaces about new iface */
7521 if (wpas_notify_iface_added(wpa_s)) {
7522 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7523 return NULL;
7524 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007525
Jimmy Chene2206be2022-07-10 10:25:21 +08007526 /* Notify the control interfaces about new networks */
7527 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7528 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007529 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007530 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7531 && os_strncmp((const char *) ssid->ssid,
7532 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7533 wpas_notify_persistent_group_added(wpa_s, ssid);
7534 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007535 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007536
7537 wpa_s->next = global->ifaces;
7538 global->ifaces = wpa_s;
7539
7540 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007541 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007542
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007543#ifdef CONFIG_P2P
7544 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007545 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007546 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007547 wpas_p2p_add_p2pdev_interface(
7548 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007549 wpa_printf(MSG_INFO,
7550 "P2P: Failed to enable P2P Device interface");
7551 /* Try to continue without. P2P will be disabled. */
7552 }
7553#endif /* CONFIG_P2P */
7554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007555 return wpa_s;
7556}
7557
7558
7559/**
7560 * wpa_supplicant_remove_iface - Remove a network interface
7561 * @global: Pointer to global data from wpa_supplicant_init()
7562 * @wpa_s: Pointer to the network interface to be removed
7563 * Returns: 0 if interface was removed, -1 if interface was not found
7564 *
7565 * This function can be used to dynamically remove network interfaces from
7566 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7567 * addition, this function is used to remove all remaining interfaces when
7568 * %wpa_supplicant is terminated.
7569 */
7570int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007571 struct wpa_supplicant *wpa_s,
7572 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007573{
7574 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007575#ifdef CONFIG_MESH
7576 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7577 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007578 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007579#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007580
7581 /* Remove interface from the global list of interfaces */
7582 prev = global->ifaces;
7583 if (prev == wpa_s) {
7584 global->ifaces = wpa_s->next;
7585 } else {
7586 while (prev && prev->next != wpa_s)
7587 prev = prev->next;
7588 if (prev == NULL)
7589 return -1;
7590 prev->next = wpa_s->next;
7591 }
7592
7593 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7594
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007595#ifdef CONFIG_MESH
7596 if (mesh_if_created) {
7597 ifname = os_strdup(wpa_s->ifname);
7598 if (ifname == NULL) {
7599 wpa_dbg(wpa_s, MSG_ERROR,
7600 "mesh: Failed to malloc ifname");
7601 return -1;
7602 }
7603 }
7604#endif /* CONFIG_MESH */
7605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007606 if (global->p2p_group_formation == wpa_s)
7607 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007608 if (global->p2p_invite_group == wpa_s)
7609 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007610 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007611
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007612#ifdef CONFIG_MESH
7613 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007614 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007615 os_free(ifname);
7616 }
7617#endif /* CONFIG_MESH */
7618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007619 return 0;
7620}
7621
7622
7623/**
7624 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7625 * @wpa_s: Pointer to the network interface
7626 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7627 */
7628const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7629{
7630 const char *eapol_method;
7631
7632 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7633 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7634 return "NO-EAP";
7635 }
7636
7637 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7638 if (eapol_method == NULL)
7639 return "UNKNOWN-EAP";
7640
7641 return eapol_method;
7642}
7643
7644
7645/**
7646 * wpa_supplicant_get_iface - Get a new network interface
7647 * @global: Pointer to global data from wpa_supplicant_init()
7648 * @ifname: Interface name
7649 * Returns: Pointer to the interface or %NULL if not found
7650 */
7651struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7652 const char *ifname)
7653{
7654 struct wpa_supplicant *wpa_s;
7655
7656 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7657 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7658 return wpa_s;
7659 }
7660 return NULL;
7661}
7662
7663
7664#ifndef CONFIG_NO_WPA_MSG
7665static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7666{
7667 struct wpa_supplicant *wpa_s = ctx;
7668 if (wpa_s == NULL)
7669 return NULL;
7670 return wpa_s->ifname;
7671}
7672#endif /* CONFIG_NO_WPA_MSG */
7673
7674
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007675#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7676#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7677#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7678
7679/* Periodic cleanup tasks */
7680static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7681{
7682 struct wpa_global *global = eloop_ctx;
7683 struct wpa_supplicant *wpa_s;
7684
7685 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7686 wpas_periodic, global, NULL);
7687
7688#ifdef CONFIG_P2P
7689 if (global->p2p)
7690 p2p_expire_peers(global->p2p);
7691#endif /* CONFIG_P2P */
7692
7693 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7694 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7695#ifdef CONFIG_AP
7696 ap_periodic(wpa_s);
7697#endif /* CONFIG_AP */
7698 }
7699}
7700
7701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007702/**
7703 * wpa_supplicant_init - Initialize %wpa_supplicant
7704 * @params: Parameters for %wpa_supplicant
7705 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7706 *
7707 * This function is used to initialize %wpa_supplicant. After successful
7708 * initialization, the returned data pointer can be used to add and remove
7709 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7710 */
7711struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7712{
7713 struct wpa_global *global;
7714 int ret, i;
7715
7716 if (params == NULL)
7717 return NULL;
7718
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007719#ifdef CONFIG_DRIVER_NDIS
7720 {
7721 void driver_ndis_init_ops(void);
7722 driver_ndis_init_ops();
7723 }
7724#endif /* CONFIG_DRIVER_NDIS */
7725
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007726#ifndef CONFIG_NO_WPA_MSG
7727 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7728#endif /* CONFIG_NO_WPA_MSG */
7729
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007730 if (params->wpa_debug_file_path)
7731 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007732 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007733 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007734 if (params->wpa_debug_syslog)
7735 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007736 if (params->wpa_debug_tracing) {
7737 ret = wpa_debug_open_linux_tracing();
7738 if (ret) {
7739 wpa_printf(MSG_ERROR,
7740 "Failed to enable trace logging");
7741 return NULL;
7742 }
7743 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007744
7745 ret = eap_register_methods();
7746 if (ret) {
7747 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7748 if (ret == -2)
7749 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7750 "the same EAP type.");
7751 return NULL;
7752 }
7753
7754 global = os_zalloc(sizeof(*global));
7755 if (global == NULL)
7756 return NULL;
7757 dl_list_init(&global->p2p_srv_bonjour);
7758 dl_list_init(&global->p2p_srv_upnp);
7759 global->params.daemonize = params->daemonize;
7760 global->params.wait_for_monitor = params->wait_for_monitor;
7761 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007762
7763 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007764 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007765 if (!global->params.pid_file) {
7766 wpa_supplicant_deinit(global);
7767 return NULL;
7768 }
7769 }
7770
7771 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007772 global->params.ctrl_interface =
7773 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007774 if (!global->params.ctrl_interface) {
7775 wpa_supplicant_deinit(global);
7776 return NULL;
7777 }
7778 }
7779
7780 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007781 global->params.ctrl_interface_group =
7782 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007783 if (!global->params.ctrl_interface_group) {
7784 wpa_supplicant_deinit(global);
7785 return NULL;
7786 }
7787 }
7788
7789 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007790 global->params.override_driver =
7791 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007792 if (!global->params.override_driver) {
7793 wpa_supplicant_deinit(global);
7794 return NULL;
7795 }
7796 }
7797
7798 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007799 global->params.override_ctrl_interface =
7800 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007801 if (!global->params.override_ctrl_interface) {
7802 wpa_supplicant_deinit(global);
7803 return NULL;
7804 }
7805 }
7806
Dmitry Shmidte4663042016-04-04 10:07:49 -07007807#ifdef CONFIG_MATCH_IFACE
7808 global->params.match_iface_count = params->match_iface_count;
7809 if (params->match_iface_count) {
7810 global->params.match_ifaces =
7811 os_calloc(params->match_iface_count,
7812 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007813 if (!global->params.match_ifaces) {
7814 wpa_printf(MSG_ERROR,
7815 "Failed to allocate match interfaces");
7816 wpa_supplicant_deinit(global);
7817 return NULL;
7818 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007819 os_memcpy(global->params.match_ifaces,
7820 params->match_ifaces,
7821 params->match_iface_count *
7822 sizeof(struct wpa_interface));
7823 }
7824#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007825#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007826 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007827 global->params.conf_p2p_dev =
7828 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007829 if (!global->params.conf_p2p_dev) {
7830 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7831 wpa_supplicant_deinit(global);
7832 return NULL;
7833 }
7834 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007835#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007836 wpa_debug_level = global->params.wpa_debug_level =
7837 params->wpa_debug_level;
7838 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7839 params->wpa_debug_show_keys;
7840 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7841 params->wpa_debug_timestamp;
7842
Hai Shalomfdcde762020-04-02 11:19:20 -07007843 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007844
7845 if (eloop_init()) {
7846 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7847 wpa_supplicant_deinit(global);
7848 return NULL;
7849 }
7850
Jouni Malinen75ecf522011-06-27 15:19:46 -07007851 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007852
7853 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7854 if (global->ctrl_iface == NULL) {
7855 wpa_supplicant_deinit(global);
7856 return NULL;
7857 }
7858
7859 if (wpas_notify_supplicant_initialized(global)) {
7860 wpa_supplicant_deinit(global);
7861 return NULL;
7862 }
7863
7864 for (i = 0; wpa_drivers[i]; i++)
7865 global->drv_count++;
7866 if (global->drv_count == 0) {
7867 wpa_printf(MSG_ERROR, "No drivers enabled");
7868 wpa_supplicant_deinit(global);
7869 return NULL;
7870 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007871 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007872 if (global->drv_priv == NULL) {
7873 wpa_supplicant_deinit(global);
7874 return NULL;
7875 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007876
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007877#ifdef CONFIG_WIFI_DISPLAY
7878 if (wifi_display_init(global) < 0) {
7879 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7880 wpa_supplicant_deinit(global);
7881 return NULL;
7882 }
7883#endif /* CONFIG_WIFI_DISPLAY */
7884
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007885 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7886 wpas_periodic, global, NULL);
7887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007888 return global;
7889}
7890
7891
7892/**
7893 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7894 * @global: Pointer to global data from wpa_supplicant_init()
7895 * Returns: 0 after successful event loop run, -1 on failure
7896 *
7897 * This function starts the main event loop and continues running as long as
7898 * there are any remaining events. In most cases, this function is running as
7899 * long as the %wpa_supplicant process in still in use.
7900 */
7901int wpa_supplicant_run(struct wpa_global *global)
7902{
7903 struct wpa_supplicant *wpa_s;
7904
7905 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007906 (wpa_supplicant_daemon(global->params.pid_file) ||
7907 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 return -1;
7909
Dmitry Shmidte4663042016-04-04 10:07:49 -07007910#ifdef CONFIG_MATCH_IFACE
7911 if (wpa_supplicant_match_existing(global))
7912 return -1;
7913#endif
7914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007915 if (global->params.wait_for_monitor) {
7916 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007917 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007918 wpa_supplicant_ctrl_iface_wait(
7919 wpa_s->ctrl_iface);
7920 }
7921
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07007922#ifdef CONFIG_AIDL
7923 global->aidl = wpas_aidl_init(global);
7924 if (!global->aidl)
7925 return -1;
7926#endif /* CONFIG_AIDL */
7927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007928 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7929 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7930
7931 eloop_run();
7932
7933 return 0;
7934}
7935
7936
7937/**
7938 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7939 * @global: Pointer to global data from wpa_supplicant_init()
7940 *
7941 * This function is called to deinitialize %wpa_supplicant and to free all
7942 * allocated resources. Remaining network interfaces will also be removed.
7943 */
7944void wpa_supplicant_deinit(struct wpa_global *global)
7945{
7946 int i;
7947
7948 if (global == NULL)
7949 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007950
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007951 eloop_cancel_timeout(wpas_periodic, global, NULL);
7952
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007953#ifdef CONFIG_WIFI_DISPLAY
7954 wifi_display_deinit(global);
7955#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007956
7957 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007958 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007959
7960 if (global->ctrl_iface)
7961 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7962
7963 wpas_notify_supplicant_deinitialized(global);
7964
7965 eap_peer_unregister_methods();
7966#ifdef CONFIG_AP
7967 eap_server_unregister_methods();
7968#endif /* CONFIG_AP */
7969
7970 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7971 if (!global->drv_priv[i])
7972 continue;
7973 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7974 }
7975 os_free(global->drv_priv);
7976
7977 random_deinit();
7978
7979 eloop_destroy();
7980
7981 if (global->params.pid_file) {
7982 os_daemonize_terminate(global->params.pid_file);
7983 os_free(global->params.pid_file);
7984 }
7985 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007986 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007987 os_free(global->params.override_driver);
7988 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007989#ifdef CONFIG_MATCH_IFACE
7990 os_free(global->params.match_ifaces);
7991#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007992#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007993 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007994#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007995
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007996 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007997 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007998 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008000 os_free(global);
8001 wpa_debug_close_syslog();
8002 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008003 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008004}
8005
8006
8007void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8008{
8009 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8010 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8011 char country[3];
8012 country[0] = wpa_s->conf->country[0];
8013 country[1] = wpa_s->conf->country[1];
8014 country[2] = '\0';
8015 if (wpa_drv_set_country(wpa_s, country) < 0) {
8016 wpa_printf(MSG_ERROR, "Failed to set country code "
8017 "'%s'", country);
8018 }
8019 }
8020
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008021 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8022 wpas_init_ext_pw(wpa_s);
8023
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008024 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8025 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8026
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008027 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8028 struct wpa_driver_capa capa;
8029 int res = wpa_drv_get_capa(wpa_s, &capa);
8030
8031 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8032 wpa_printf(MSG_ERROR,
8033 "Failed to update wowlan_triggers to '%s'",
8034 wpa_s->conf->wowlan_triggers);
8035 }
8036
Hai Shalom81f62d82019-07-22 12:10:00 -07008037 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8038 wpa_supplicant_set_default_scan_ies(wpa_s);
8039
Hai Shalom899fcc72020-10-19 14:38:18 -07008040#ifdef CONFIG_BGSCAN
8041 /*
8042 * We default to global bgscan parameters only when per-network bgscan
8043 * parameters aren't set. Only bother resetting bgscan parameters if
8044 * this is the case.
8045 */
8046 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8047 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8048 wpa_s->wpa_state == WPA_COMPLETED)
8049 wpa_supplicant_reset_bgscan(wpa_s);
8050#endif /* CONFIG_BGSCAN */
8051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008052#ifdef CONFIG_WPS
8053 wpas_wps_update_config(wpa_s);
8054#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008055 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008056 wpa_s->conf->changed_parameters = 0;
8057}
8058
8059
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008060void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008061{
8062 int i;
8063
8064 for (i = 0; i < *num_freqs; i++) {
8065 if (freqs[i] == freq)
8066 return;
8067 }
8068
8069 freqs[*num_freqs] = freq;
8070 (*num_freqs)++;
8071}
8072
8073
8074static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8075{
8076 struct wpa_bss *bss, *cbss;
8077 const int max_freqs = 10;
8078 int *freqs;
8079 int num_freqs = 0;
8080
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008081 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008082 if (freqs == NULL)
8083 return NULL;
8084
8085 cbss = wpa_s->current_bss;
8086
8087 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8088 if (bss == cbss)
8089 continue;
8090 if (bss->ssid_len == cbss->ssid_len &&
8091 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008092 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008093 add_freq(freqs, &num_freqs, bss->freq);
8094 if (num_freqs == max_freqs)
8095 break;
8096 }
8097 }
8098
8099 if (num_freqs == 0) {
8100 os_free(freqs);
8101 freqs = NULL;
8102 }
8103
8104 return freqs;
8105}
8106
8107
8108void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8109{
8110 int timeout;
8111 int count;
8112 int *freqs = NULL;
8113
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008114 wpas_connect_work_done(wpa_s);
8115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008116 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008117 * Remove possible authentication timeout since the connection failed.
8118 */
8119 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8120
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008121 /*
Hai Shalom60840252021-02-19 19:02:11 -08008122 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008123 * generated based on local request to disconnect.
8124 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008125 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008126 wpa_s->own_disconnect_req = 0;
8127 wpa_dbg(wpa_s, MSG_DEBUG,
8128 "Ignore connection failure due to local request to disconnect");
8129 return;
8130 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008131 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008132 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8133 "indication since interface has been put into "
8134 "disconnected state");
8135 return;
8136 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008137 if (wpa_s->auto_reconnect_disabled) {
8138 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8139 "indication since auto connect is disabled");
8140 return;
8141 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008142
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008143 /*
Hai Shalom60840252021-02-19 19:02:11 -08008144 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008145 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008146 */
Hai Shalom60840252021-02-19 19:02:11 -08008147 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008148 if (count == 1 && wpa_s->current_bss) {
8149 /*
Hai Shalom60840252021-02-19 19:02:11 -08008150 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008151 * another BSS available for the same ESS, we should try that
8152 * next. Otherwise, we may as well try this one once more
8153 * before allowing other, likely worse, ESSes to be considered.
8154 */
8155 freqs = get_bss_freqs_in_ess(wpa_s);
8156 if (freqs) {
8157 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8158 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008159 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008160 /*
8161 * On the next scan, go through only the known channels
8162 * used in this ESS based on previous scans to speed up
8163 * common load balancing use case.
8164 */
8165 os_free(wpa_s->next_scan_freqs);
8166 wpa_s->next_scan_freqs = freqs;
8167 }
8168 }
8169
Hai Shalom899fcc72020-10-19 14:38:18 -07008170 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008171
Hai Shalom899fcc72020-10-19 14:38:18 -07008172 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008173 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8174 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008175 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008176 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008177 /*
8178 * Multiple consecutive connection failures mean that other APs are
8179 * either not available or have already been tried, so we can start
8180 * increasing the delay here to avoid constant scanning.
8181 */
8182 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008183 case 1:
8184 timeout = 100;
8185 break;
8186 case 2:
8187 timeout = 500;
8188 break;
8189 case 3:
8190 timeout = 1000;
8191 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008192 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008193 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008194 break;
8195 default:
8196 timeout = 10000;
8197 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008198 }
8199
Hai Shalom899fcc72020-10-19 14:38:18 -07008200 wpa_dbg(wpa_s, MSG_DEBUG,
8201 "Consecutive connection failures: %d --> request scan in %d ms",
8202 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008203
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008204 /*
8205 * TODO: if more than one possible AP is available in scan results,
8206 * could try the other ones before requesting a new scan.
8207 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008208
8209 /* speed up the connection attempt with normal scan */
8210 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008211 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8212 1000 * (timeout % 1000));
8213}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008214
8215
Hai Shalomce48b4a2018-09-05 11:41:35 -07008216#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008217
8218void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8219{
8220 struct wpa_ssid *ssid = wpa_s->current_ssid;
8221 const u8 *realm, *username, *rrk;
8222 size_t realm_len, username_len, rrk_len;
8223 u16 next_seq_num;
8224
8225 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8226 * Check for ERP keys existing to limit when this can be done since
8227 * the rejection response is not protected and such triggers should
8228 * really not allow internal state to be modified unless required to
8229 * avoid significant issues in functionality. In addition, drop
8230 * externally configure PMKSA entries even without ERP keys since it
8231 * is possible for an external component to add PMKSA entries for FILS
8232 * authentication without restoring previously generated ERP keys.
8233 *
8234 * In this case, this is needed to allow recovery from cases where the
8235 * AP or authentication server has dropped PMKSAs and ERP keys. */
8236 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8237 return;
8238
8239 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8240 &username, &username_len,
8241 &realm, &realm_len, &next_seq_num,
8242 &rrk, &rrk_len) != 0 ||
8243 !realm) {
8244 wpa_dbg(wpa_s, MSG_DEBUG,
8245 "FILS: Drop external PMKSA cache entry");
8246 wpa_sm_aborted_external_cached(wpa_s->wpa);
8247 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8248 return;
8249 }
8250
8251 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8252 wpa_sm_aborted_cached(wpa_s->wpa);
8253 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8254}
8255
8256
Hai Shalomce48b4a2018-09-05 11:41:35 -07008257void fils_connection_failure(struct wpa_supplicant *wpa_s)
8258{
8259 struct wpa_ssid *ssid = wpa_s->current_ssid;
8260 const u8 *realm, *username, *rrk;
8261 size_t realm_len, username_len, rrk_len;
8262 u16 next_seq_num;
8263
8264 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8265 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8266 &username, &username_len,
8267 &realm, &realm_len, &next_seq_num,
8268 &rrk, &rrk_len) != 0 ||
8269 !realm)
8270 return;
8271
8272 wpa_hexdump_ascii(MSG_DEBUG,
8273 "FILS: Store last connection failure realm",
8274 realm, realm_len);
8275 os_free(wpa_s->last_con_fail_realm);
8276 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8277 if (wpa_s->last_con_fail_realm) {
8278 wpa_s->last_con_fail_realm_len = realm_len;
8279 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8280 }
8281}
8282#endif /* CONFIG_FILS */
8283
8284
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008285int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8286{
8287 return wpa_s->conf->ap_scan == 2 ||
8288 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8289}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008290
Dmitry Shmidt04949592012-07-19 12:16:46 -07008291
Gabriel Biren57ededa2021-09-03 16:08:50 +00008292#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008293int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8294 struct wpa_ssid *ssid,
8295 const char *field,
8296 const char *value)
8297{
8298#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008299 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008300
8301 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8302 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8303 (const u8 *) value, os_strlen(value));
8304
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008305 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008306 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008307#else /* IEEE8021X_EAPOL */
8308 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8309 return -1;
8310#endif /* IEEE8021X_EAPOL */
8311}
8312
8313int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8314 struct wpa_ssid *ssid,
8315 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008316 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008317{
8318#ifdef IEEE8021X_EAPOL
8319 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008320 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008321
8322 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008323 case WPA_CTRL_REQ_EAP_IDENTITY:
8324 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008325 os_free(eap->imsi_identity);
8326 if (value == NULL)
8327 return -1;
8328 identity = os_strchr(value, ':');
8329 if (identity == NULL) {
8330 /* plain identity */
8331 eap->identity = (u8 *)os_strdup(value);
8332 eap->identity_len = os_strlen(value);
8333 } else {
8334 /* have both plain identity and encrypted identity */
8335 imsi_identity = value;
8336 *identity++ = '\0';
8337 /* plain identity */
8338 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8339 eap->imsi_identity_len = strlen(imsi_identity);
8340 /* encrypted identity */
8341 eap->identity = (u8 *)dup_binstr(identity,
8342 value_len - strlen(imsi_identity) - 1);
8343 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8344 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008345 eap->pending_req_identity = 0;
8346 if (ssid == wpa_s->current_ssid)
8347 wpa_s->reassociate = 1;
8348 break;
8349 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008350 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008351 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008352 if (!eap->password)
8353 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008354 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008355 eap->pending_req_password = 0;
8356 if (ssid == wpa_s->current_ssid)
8357 wpa_s->reassociate = 1;
8358 break;
8359 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008360 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008361 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008362 if (!eap->new_password)
8363 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008364 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008365 eap->pending_req_new_password = 0;
8366 if (ssid == wpa_s->current_ssid)
8367 wpa_s->reassociate = 1;
8368 break;
8369 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008370 str_clear_free(eap->cert.pin);
8371 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008372 if (!eap->cert.pin)
8373 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008374 eap->pending_req_pin = 0;
8375 if (ssid == wpa_s->current_ssid)
8376 wpa_s->reassociate = 1;
8377 break;
8378 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008379 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008380 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008381 if (!eap->otp)
8382 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008383 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008384 os_free(eap->pending_req_otp);
8385 eap->pending_req_otp = NULL;
8386 eap->pending_req_otp_len = 0;
8387 break;
8388 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008389 str_clear_free(eap->cert.private_key_passwd);
8390 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008391 if (!eap->cert.private_key_passwd)
8392 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008393 eap->pending_req_passphrase = 0;
8394 if (ssid == wpa_s->current_ssid)
8395 wpa_s->reassociate = 1;
8396 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008397 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008398 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008399 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008400 if (!eap->external_sim_resp)
8401 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008402 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008403 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008404 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8405 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8406 return -1;
8407 ssid->mem_only_psk = 1;
8408 if (ssid->passphrase)
8409 wpa_config_update_psk(ssid);
8410 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8411 wpa_supplicant_req_scan(wpa_s, 0, 0);
8412 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008413 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8414 if (eap->pending_ext_cert_check != PENDING_CHECK)
8415 return -1;
8416 if (os_strcmp(value, "good") == 0)
8417 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8418 else if (os_strcmp(value, "bad") == 0)
8419 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8420 else
8421 return -1;
8422 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008423 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008424 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008425 return -1;
8426 }
8427
8428 return 0;
8429#else /* IEEE8021X_EAPOL */
8430 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8431 return -1;
8432#endif /* IEEE8021X_EAPOL */
8433}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008434#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008435
8436
8437int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8438{
Hai Shalomfdcde762020-04-02 11:19:20 -07008439#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008440 int i;
8441 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008442#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008443
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008444 if (wpa_s->p2p_mgmt)
8445 return 1; /* no normal network profiles on p2p_mgmt interface */
8446
Dmitry Shmidt04949592012-07-19 12:16:46 -07008447 if (ssid == NULL)
8448 return 1;
8449
8450 if (ssid->disabled)
8451 return 1;
8452
Hai Shalomfdcde762020-04-02 11:19:20 -07008453#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008454 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008455 drv_enc = wpa_s->drv_enc;
8456 else
8457 drv_enc = (unsigned int) -1;
8458
8459 for (i = 0; i < NUM_WEP_KEYS; i++) {
8460 size_t len = ssid->wep_key_len[i];
8461 if (len == 0)
8462 continue;
8463 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8464 continue;
8465 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8466 continue;
8467 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8468 continue;
8469 return 1; /* invalid WEP key */
8470 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008471#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008472
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008473 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008474 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008475 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008476 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008477 return 1;
8478
Sunil Ravi89eba102022-09-13 21:04:37 -07008479#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008480#ifdef CRYPTO_RSA_OAEP_SHA256
8481 if (ssid->eap.imsi_privacy_cert) {
8482 struct crypto_rsa_key *key;
8483 bool failed = false;
8484
8485 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8486 if (!key)
8487 failed = true;
8488 crypto_rsa_key_free(key);
8489 if (failed) {
8490 wpa_printf(MSG_DEBUG,
8491 "Invalid imsi_privacy_cert (%s) - disable network",
8492 ssid->eap.imsi_privacy_cert);
8493 return 1;
8494 }
8495 }
8496#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008497#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008498
Dmitry Shmidt04949592012-07-19 12:16:46 -07008499 return 0;
8500}
8501
8502
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008503int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8504{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008505 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8506 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8507 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8508 /*
8509 * Driver does not support BIP -- ignore pmf=1 default
8510 * since the connection with PMF would fail and the
8511 * configuration does not require PMF to be enabled.
8512 */
8513 return NO_MGMT_FRAME_PROTECTION;
8514 }
8515
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008516 if (ssid &&
8517 (ssid->key_mgmt &
8518 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8519 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8520 /*
8521 * Do not use the default PMF value for non-RSN networks
8522 * since PMF is available only with RSN and pmf=2
8523 * configuration would otherwise prevent connections to
8524 * all open networks.
8525 */
8526 return NO_MGMT_FRAME_PROTECTION;
8527 }
8528
Sunil Ravi77d572f2023-01-17 23:58:31 +00008529#ifdef CONFIG_OCV
8530 /* Enable PMF if OCV is being enabled */
8531 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8532 ssid && ssid->ocv)
8533 return MGMT_FRAME_PROTECTION_OPTIONAL;
8534#endif /* CONFIG_OCV */
8535
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008536 return wpa_s->conf->pmf;
8537 }
8538
8539 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008540}
8541
8542
Sunil Ravi77d572f2023-01-17 23:58:31 +00008543#ifdef CONFIG_SAE
8544bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8545 struct wpa_ssid *ssid,
8546 const struct wpa_ie_data *ie)
8547{
8548 return wpa_s->conf->sae_check_mfp &&
8549 (!(ie->capabilities &
8550 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8551 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8552}
8553#endif /* CONFIG_SAE */
8554
8555
Hai Shalomc1a21442022-02-04 13:43:00 -08008556int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8557{
8558 if (wpa_s->current_ssid == NULL ||
8559 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8560 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8561 return 0;
8562 return wpa_sm_pmf_enabled(wpa_s->wpa);
8563}
8564
8565
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008566int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008567{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008568 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008569 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008570 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008571 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008572 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008573}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008574
8575
Sunil Ravi77d572f2023-01-17 23:58:31 +00008576void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8577 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008578{
8579 struct wpa_ssid *ssid = wpa_s->current_ssid;
8580 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008581 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008582
8583 if (ssid == NULL) {
8584 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8585 "SSID block");
8586 return;
8587 }
8588
8589 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8590 return;
8591
8592 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008593
8594#ifdef CONFIG_P2P
8595 if (ssid->p2p_group &&
8596 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8597 /*
8598 * Skip the wait time since there is a short timeout on the
8599 * connection to a P2P group.
8600 */
8601 return;
8602 }
8603#endif /* CONFIG_P2P */
8604
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008605 if (ssid->auth_failures > 50)
8606 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008607 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008608 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008609 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008610 dur = 90;
8611 else if (ssid->auth_failures > 3)
8612 dur = 60;
8613 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008614 dur = 30;
8615 else if (ssid->auth_failures > 1)
8616 dur = 20;
8617 else
8618 dur = 10;
8619
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008620 if (ssid->auth_failures > 1 &&
8621 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8622 dur += os_random() % (ssid->auth_failures * 10);
8623
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008624 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008625 if (now.sec + dur <= ssid->disabled_until.sec)
8626 return;
8627
8628 ssid->disabled_until.sec = now.sec + dur;
8629
8630 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008631 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008632 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008633 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008634
8635 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8636 int msg_len = snprintf(NULL, 0, format_str,
8637 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8638 ssid->auth_failures, dur, reason) + 1;
8639 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308640 if (!msg)
8641 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008642 snprintf(msg, msg_len, format_str,
8643 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8644 ssid->auth_failures, dur, reason);
8645 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8646 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008647
8648 if (bssid)
8649 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008650}
8651
8652
8653void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8654 struct wpa_ssid *ssid, int clear_failures)
8655{
8656 if (ssid == NULL)
8657 return;
8658
8659 if (ssid->disabled_until.sec) {
8660 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8661 "id=%d ssid=\"%s\"",
8662 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8663 }
8664 ssid->disabled_until.sec = 0;
8665 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008666 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008667 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008668 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8669 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8670 " ignored to allow a lower priority BSS, if any, to be tried next",
8671 MAC2STR(ssid->disabled_due_to));
8672 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8673 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8674 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008675}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008676
8677
8678int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8679{
8680 size_t i;
8681
8682 if (wpa_s->disallow_aps_bssid == NULL)
8683 return 0;
8684
8685 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8686 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8687 bssid, ETH_ALEN) == 0)
8688 return 1;
8689 }
8690
8691 return 0;
8692}
8693
8694
8695int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8696 size_t ssid_len)
8697{
8698 size_t i;
8699
8700 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8701 return 0;
8702
8703 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8704 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8705 if (ssid_len == s->ssid_len &&
8706 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8707 return 1;
8708 }
8709
8710 return 0;
8711}
8712
8713
8714/**
8715 * wpas_request_connection - Request a new connection
8716 * @wpa_s: Pointer to the network interface
8717 *
8718 * This function is used to request a new connection to be found. It will mark
8719 * the interface to allow reassociation and request a new scan to find a
8720 * suitable network to connect to.
8721 */
8722void wpas_request_connection(struct wpa_supplicant *wpa_s)
8723{
8724 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008725 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008726 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008727 wpa_s->disconnected = 0;
8728 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008729 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008730
8731 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8732 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008733 else
8734 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008735}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008736
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008737
Roshan Pius02242d72016-08-09 15:31:48 -07008738/**
8739 * wpas_request_disconnection - Request disconnection
8740 * @wpa_s: Pointer to the network interface
8741 *
8742 * This function is used to request disconnection from the currently connected
8743 * network. This will stop any ongoing scans and initiate deauthentication.
8744 */
8745void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8746{
8747#ifdef CONFIG_SME
8748 wpa_s->sme.prev_bssid_set = 0;
8749#endif /* CONFIG_SME */
8750 wpa_s->reassociate = 0;
8751 wpa_s->disconnected = 1;
8752 wpa_supplicant_cancel_sched_scan(wpa_s);
8753 wpa_supplicant_cancel_scan(wpa_s);
8754 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8755 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008756 radio_remove_works(wpa_s, "connect", 0);
8757 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008758 wpa_s->roam_in_progress = false;
8759#ifdef CONFIG_WNM
8760 wpa_s->bss_trans_mgmt_in_progress = false;
8761#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008762}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008763
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008764
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008765void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8766 struct wpa_used_freq_data *freqs_data,
8767 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008768{
8769 unsigned int i;
8770
8771 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8772 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008773 for (i = 0; i < len; i++) {
8774 struct wpa_used_freq_data *cur = &freqs_data[i];
8775 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8776 i, cur->freq, cur->flags);
8777 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008778}
8779
8780
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008781/*
8782 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008783 * are using the same radio as the current interface, and in addition, get
8784 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008785 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008786int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8787 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008788 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008789{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008790 struct wpa_supplicant *ifs;
8791 u8 bssid[ETH_ALEN];
8792 int freq;
8793 unsigned int idx = 0, i;
8794
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008795 wpa_dbg(wpa_s, MSG_DEBUG,
8796 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008797 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008798
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008799 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8800 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008801 if (idx == len)
8802 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008803
Sunil Ravi77d572f2023-01-17 23:58:31 +00008804 if (exclude_current && ifs == wpa_s)
8805 continue;
8806
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008807 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8808 continue;
8809
8810 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008811 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8812 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008813 freq = ifs->current_ssid->frequency;
8814 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8815 freq = ifs->assoc_freq;
8816 else
8817 continue;
8818
8819 /* Hold only distinct freqs */
8820 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008821 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008822 break;
8823
8824 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008825 freqs_data[idx++].freq = freq;
8826
8827 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008828 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008829 WPA_FREQ_USED_BY_P2P_CLIENT :
8830 WPA_FREQ_USED_BY_INFRA_STATION;
8831 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008832 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008833
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008834 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008835 return idx;
8836}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008837
8838
8839/*
8840 * Find the operating frequencies of any of the virtual interfaces that
8841 * are using the same radio as the current interface.
8842 */
8843int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008844 int *freq_array, unsigned int len,
8845 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008846{
8847 struct wpa_used_freq_data *freqs_data;
8848 int num, i;
8849
8850 os_memset(freq_array, 0, sizeof(int) * len);
8851
8852 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8853 if (!freqs_data)
8854 return -1;
8855
Sunil Ravi77d572f2023-01-17 23:58:31 +00008856 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8857 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008858 for (i = 0; i < num; i++)
8859 freq_array[i] = freqs_data[i].freq;
8860
8861 os_free(freqs_data);
8862
8863 return num;
8864}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008865
8866
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008867struct wpa_supplicant *
8868wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8869{
8870 switch (frame) {
8871#ifdef CONFIG_P2P
8872 case VENDOR_ELEM_PROBE_REQ_P2P:
8873 case VENDOR_ELEM_PROBE_RESP_P2P:
8874 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8875 case VENDOR_ELEM_BEACON_P2P_GO:
8876 case VENDOR_ELEM_P2P_PD_REQ:
8877 case VENDOR_ELEM_P2P_PD_RESP:
8878 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8879 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8880 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8881 case VENDOR_ELEM_P2P_INV_REQ:
8882 case VENDOR_ELEM_P2P_INV_RESP:
8883 case VENDOR_ELEM_P2P_ASSOC_REQ:
8884 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008885 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008886#endif /* CONFIG_P2P */
8887 default:
8888 return wpa_s;
8889 }
8890}
8891
8892
8893void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8894{
8895 unsigned int i;
8896 char buf[30];
8897
8898 wpa_printf(MSG_DEBUG, "Update vendor elements");
8899
8900 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8901 if (wpa_s->vendor_elem[i]) {
8902 int res;
8903
8904 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8905 if (!os_snprintf_error(sizeof(buf), res)) {
8906 wpa_hexdump_buf(MSG_DEBUG, buf,
8907 wpa_s->vendor_elem[i]);
8908 }
8909 }
8910 }
8911
8912#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008913 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008914 wpa_s->global->p2p &&
8915 !wpa_s->global->p2p_disabled)
8916 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8917#endif /* CONFIG_P2P */
8918}
8919
8920
8921int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8922 const u8 *elem, size_t len)
8923{
8924 u8 *ie, *end;
8925
8926 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8927 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8928
8929 for (; ie + 1 < end; ie += 2 + ie[1]) {
8930 if (ie + len > end)
8931 break;
8932 if (os_memcmp(ie, elem, len) != 0)
8933 continue;
8934
8935 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8936 wpabuf_free(wpa_s->vendor_elem[frame]);
8937 wpa_s->vendor_elem[frame] = NULL;
8938 } else {
8939 os_memmove(ie, ie + len, end - (ie + len));
8940 wpa_s->vendor_elem[frame]->used -= len;
8941 }
8942 wpas_vendor_elem_update(wpa_s);
8943 return 0;
8944 }
8945
8946 return -1;
8947}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008948
8949
8950struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008951 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008952 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008953{
8954 u16 i;
8955
Hai Shalomc1a21442022-02-04 13:43:00 -08008956 if (!modes)
8957 return NULL;
8958
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008959 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008960 if (modes[i].mode != mode ||
8961 !modes[i].num_channels || !modes[i].channels)
8962 continue;
8963 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8964 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008965 return &modes[i];
8966 }
8967
8968 return NULL;
8969}
8970
8971
Hai Shalomc1a21442022-02-04 13:43:00 -08008972struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8973 u16 num_modes, int freq)
8974{
8975 int i, j;
8976
8977 for (i = 0; i < num_modes; i++) {
8978 for (j = 0; j < modes[i].num_channels; j++) {
8979 if (freq == modes[i].channels[j].freq)
8980 return &modes[i];
8981 }
8982 }
8983
8984 return NULL;
8985}
8986
8987
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008988static struct
8989wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8990 const u8 *bssid)
8991{
8992 struct wpa_bss_tmp_disallowed *bss;
8993
8994 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8995 struct wpa_bss_tmp_disallowed, list) {
8996 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8997 return bss;
8998 }
8999
9000 return NULL;
9001}
9002
9003
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009004static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9005{
9006 struct wpa_bss_tmp_disallowed *tmp;
9007 unsigned int num_bssid = 0;
9008 u8 *bssids;
9009 int ret;
9010
9011 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9012 if (!bssids)
9013 return -1;
9014 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9015 struct wpa_bss_tmp_disallowed, list) {
9016 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9017 ETH_ALEN);
9018 num_bssid++;
9019 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009020 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009021 os_free(bssids);
9022 return ret;
9023}
9024
9025
9026static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9027{
9028 struct wpa_supplicant *wpa_s = eloop_ctx;
9029 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9030
9031 /* Make sure the bss is not already freed */
9032 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9033 struct wpa_bss_tmp_disallowed, list) {
9034 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009035 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009036 wpa_set_driver_tmp_disallow_list(wpa_s);
9037 break;
9038 }
9039 }
9040}
9041
9042
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009043void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009044 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009045{
9046 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009047
9048 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9049 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009050 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009051 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009052 }
9053
9054 bss = os_malloc(sizeof(*bss));
9055 if (!bss) {
9056 wpa_printf(MSG_DEBUG,
9057 "Failed to allocate memory for temp disallow BSS");
9058 return;
9059 }
9060
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009061 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9062 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009063 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009064
9065finish:
9066 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009067 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9068 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009069}
9070
9071
Hai Shalom74f70d42019-02-11 14:42:39 -08009072int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9073 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009074{
Hai Shalom74f70d42019-02-11 14:42:39 -08009075 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009076
9077 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9078 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009079 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9080 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009081 break;
9082 }
9083 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009084 if (!disallowed)
9085 return 0;
9086
9087 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009088 bss->level > disallowed->rssi_threshold) {
9089 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9090 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009091 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009092 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009093
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009094 return 1;
9095}
Hai Shalom81f62d82019-07-22 12:10:00 -07009096
9097
9098int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9099 unsigned int type, const u8 *addr,
9100 const u8 *mask)
9101{
9102 if ((addr && !mask) || (!addr && mask)) {
9103 wpa_printf(MSG_INFO,
9104 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9105 return -1;
9106 }
9107
9108 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9109 wpa_printf(MSG_INFO,
9110 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9111 return -1;
9112 }
9113
9114 if (type & MAC_ADDR_RAND_SCAN) {
9115 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9116 addr, mask))
9117 return -1;
9118 }
9119
9120 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9121 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9122 addr, mask))
9123 return -1;
9124
9125 if (wpa_s->sched_scanning && !wpa_s->pno)
9126 wpas_scan_restart_sched_scan(wpa_s);
9127 }
9128
9129 if (type & MAC_ADDR_RAND_PNO) {
9130 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9131 addr, mask))
9132 return -1;
9133
9134 if (wpa_s->pno) {
9135 wpas_stop_pno(wpa_s);
9136 wpas_start_pno(wpa_s);
9137 }
9138 }
9139
9140 return 0;
9141}
9142
9143
9144int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9145 unsigned int type)
9146{
9147 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9148 if (wpa_s->pno) {
9149 if (type & MAC_ADDR_RAND_PNO) {
9150 wpas_stop_pno(wpa_s);
9151 wpas_start_pno(wpa_s);
9152 }
9153 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9154 wpas_scan_restart_sched_scan(wpa_s);
9155 }
9156
9157 return 0;
9158}
Hai Shalomfdcde762020-04-02 11:19:20 -07009159
9160
9161int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9162 struct wpa_signal_info *si)
9163{
9164 int res;
9165
9166 if (!wpa_s->driver->signal_poll)
9167 return -1;
9168
9169 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9170
9171#ifdef CONFIG_TESTING_OPTIONS
9172 if (res == 0) {
9173 struct driver_signal_override *dso;
9174
9175 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9176 struct driver_signal_override, list) {
9177 if (os_memcmp(wpa_s->bssid, dso->bssid,
9178 ETH_ALEN) != 0)
9179 continue;
9180 wpa_printf(MSG_DEBUG,
9181 "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 +00009182 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009183 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009184 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009185 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009186 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009187 dso->si_avg_beacon_signal,
9188 si->current_noise,
9189 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009190 si->data.signal = dso->si_current_signal;
9191 si->data.avg_signal = dso->si_avg_signal;
9192 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009193 si->current_noise = dso->si_current_noise;
9194 break;
9195 }
9196 }
9197#endif /* CONFIG_TESTING_OPTIONS */
9198
9199 return res;
9200}
9201
9202
9203struct wpa_scan_results *
9204wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9205{
9206 struct wpa_scan_results *scan_res;
9207#ifdef CONFIG_TESTING_OPTIONS
9208 size_t idx;
9209#endif /* CONFIG_TESTING_OPTIONS */
9210
9211 if (!wpa_s->driver->get_scan_results2)
9212 return NULL;
9213
9214 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9215
9216#ifdef CONFIG_TESTING_OPTIONS
9217 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9218 struct driver_signal_override *dso;
9219 struct wpa_scan_res *res = scan_res->res[idx];
9220
9221 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9222 struct driver_signal_override, list) {
9223 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9224 continue;
9225 wpa_printf(MSG_DEBUG,
9226 "Override driver scan signal level %d->%d for "
9227 MACSTR,
9228 res->level, dso->scan_level,
9229 MAC2STR(res->bssid));
9230 res->flags |= WPA_SCAN_QUAL_INVALID;
9231 if (dso->scan_level < 0)
9232 res->flags |= WPA_SCAN_LEVEL_DBM;
9233 else
9234 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9235 res->level = dso->scan_level;
9236 break;
9237 }
9238 }
9239#endif /* CONFIG_TESTING_OPTIONS */
9240
9241 return scan_res;
9242}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009243
9244
9245static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9246{
9247 int i;
9248
9249 if (!wpa_s->valid_links)
9250 return false;
9251
9252 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9253 if (!(wpa_s->valid_links & BIT(i)))
9254 continue;
9255
9256 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9257 return true;
9258 }
9259
9260 return false;
9261}
9262
9263
9264int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9265 unsigned int wait, const u8 *dst, const u8 *src,
9266 const u8 *bssid, const u8 *data, size_t data_len,
9267 int no_cck)
9268{
9269 if (!wpa_s->driver->send_action)
9270 return -1;
9271
9272 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9273 if (wpas_ap_link_address(wpa_s, dst))
9274 dst = wpa_s->ap_mld_addr;
9275
9276 if (wpas_ap_link_address(wpa_s, bssid))
9277 bssid = wpa_s->ap_mld_addr;
9278 }
9279
9280 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9281 bssid, data, data_len, no_cck);
9282}