blob: a3645d1cc0e7342f6fa6e91e9a13ba30231f528f [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;
Sunil Ravi640215c2023-06-28 23:08:09 +00001590 bool wmm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591
1592 if (bss) {
1593 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1594 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001595 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001596 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001597 } else {
1598 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1599 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600
1601 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1602 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001603 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604 (ie.key_mgmt & ssid->key_mgmt)) {
1605 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1606 proto = WPA_PROTO_RSN;
1607 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001608 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 (ie.group_cipher & ssid->group_cipher) &&
1610 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1611 (ie.key_mgmt & ssid->key_mgmt)) {
1612 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1613 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001614#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001615 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1616 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1617 (ie.group_cipher & ssid->group_cipher) &&
1618 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1619 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001620 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001621 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001622 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1623 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1624 (ie.group_cipher & ssid->group_cipher) &&
1625 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1626 (ie.key_mgmt & ssid->key_mgmt)) {
1627 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1628 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001629#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 } else if (bss) {
1631 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001632 wpa_dbg(wpa_s, MSG_DEBUG,
1633 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1634 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1635 ssid->key_mgmt);
1636 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1637 MAC2STR(bss->bssid),
1638 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1639 bss_wpa ? " WPA" : "",
1640 bss_rsn ? " RSN" : "",
1641 bss_osen ? " OSEN" : "");
1642 if (bss_rsn) {
1643 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1644 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1645 wpa_dbg(wpa_s, MSG_DEBUG,
1646 "Could not parse RSN element");
1647 } else {
1648 wpa_dbg(wpa_s, MSG_DEBUG,
1649 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1650 ie.pairwise_cipher, ie.group_cipher,
1651 ie.key_mgmt);
1652 }
1653 }
1654 if (bss_wpa) {
1655 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1656 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1657 wpa_dbg(wpa_s, MSG_DEBUG,
1658 "Could not parse WPA element");
1659 } else {
1660 wpa_dbg(wpa_s, MSG_DEBUG,
1661 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1662 ie.pairwise_cipher, ie.group_cipher,
1663 ie.key_mgmt);
1664 }
1665 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 return -1;
1667 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001668 if (ssid->proto & WPA_PROTO_OSEN)
1669 proto = WPA_PROTO_OSEN;
1670 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671 proto = WPA_PROTO_RSN;
1672 else
1673 proto = WPA_PROTO_WPA;
1674 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1675 os_memset(&ie, 0, sizeof(ie));
1676 ie.group_cipher = ssid->group_cipher;
1677 ie.pairwise_cipher = ssid->pairwise_cipher;
1678 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001679 ie.mgmt_group_cipher = 0;
1680 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1681 if (ssid->group_mgmt_cipher &
1682 WPA_CIPHER_BIP_GMAC_256)
1683 ie.mgmt_group_cipher =
1684 WPA_CIPHER_BIP_GMAC_256;
1685 else if (ssid->group_mgmt_cipher &
1686 WPA_CIPHER_BIP_CMAC_256)
1687 ie.mgmt_group_cipher =
1688 WPA_CIPHER_BIP_CMAC_256;
1689 else if (ssid->group_mgmt_cipher &
1690 WPA_CIPHER_BIP_GMAC_128)
1691 ie.mgmt_group_cipher =
1692 WPA_CIPHER_BIP_GMAC_128;
1693 else
1694 ie.mgmt_group_cipher =
1695 WPA_CIPHER_AES_128_CMAC;
1696 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001697#ifdef CONFIG_OWE
1698 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1699 !ssid->owe_only &&
1700 !bss_wpa && !bss_rsn && !bss_osen) {
1701 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1702 wpa_s->wpa_proto = 0;
1703 *wpa_ie_len = 0;
1704 return 0;
1705 }
1706#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001707 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1708 "based on configuration");
1709 } else
1710 proto = ie.proto;
1711 }
1712
1713 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1714 "pairwise %d key_mgmt %d proto %d",
1715 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716 if (ssid->ieee80211w) {
1717 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1718 ie.mgmt_group_cipher);
1719 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001721 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1723 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001724 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725
1726 if (bss || !wpa_s->ap_ies_from_associnfo) {
1727 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1728 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1729 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001730 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1731 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1732 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733 return -1;
1734 }
1735
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001736#ifdef CONFIG_NO_WPA
1737 wpa_s->group_cipher = WPA_CIPHER_NONE;
1738 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1739#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001740 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001741 wpa_dbg(wpa_s, MSG_DEBUG,
1742 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1743 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001744 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1745 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1747 "cipher");
1748 return -1;
1749 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001750 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1751 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752
1753 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001754 wpa_dbg(wpa_s, MSG_DEBUG,
1755 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1756 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001757 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1758 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1760 "cipher");
1761 return -1;
1762 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001763 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1764 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001765#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766
1767 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001768#ifdef CONFIG_SAE
Sunil Ravi77d572f2023-01-17 23:58:31 +00001769 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) ||
1770 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001771 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1772 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001773#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001774#ifdef CONFIG_IEEE80211R
1775 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1776 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1777 sel &= ~WPA_KEY_MGMT_FT;
1778#endif /* CONFIG_IEEE80211R */
1779 wpa_dbg(wpa_s, MSG_DEBUG,
1780 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1781 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001782 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001783#ifdef CONFIG_IEEE80211R
1784#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001785 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1786 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001787 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1788 wpa_dbg(wpa_s, MSG_DEBUG,
1789 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001790 if (!ssid->ft_eap_pmksa_caching &&
1791 pmksa_cache_get_current(wpa_s->wpa)) {
1792 /* PMKSA caching with FT may have interoperability
1793 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001794 wpa_dbg(wpa_s, MSG_DEBUG,
1795 "WPA: Disable PMKSA caching for FT/802.1X connection");
1796 pmksa_cache_clear_current(wpa_s->wpa);
1797 }
1798#endif /* CONFIG_SHA384 */
1799#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001800#ifdef CONFIG_SUITEB192
1801 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1802 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1803 wpa_dbg(wpa_s, MSG_DEBUG,
1804 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1805#endif /* CONFIG_SUITEB192 */
1806#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001807 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1808 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1809 wpa_dbg(wpa_s, MSG_DEBUG,
1810 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001811#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001812#ifdef CONFIG_FILS
1813#ifdef CONFIG_IEEE80211R
1814 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1815 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1816 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001817#endif /* CONFIG_IEEE80211R */
1818 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1819 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1820 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001821#ifdef CONFIG_IEEE80211R
1822 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1823 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1824 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1825#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001826 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1827 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1828 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1829#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001831 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1832 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001833 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1834 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001835 if (!ssid->ft_eap_pmksa_caching &&
1836 pmksa_cache_get_current(wpa_s->wpa)) {
1837 /* PMKSA caching with FT may have interoperability
1838 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001839 wpa_dbg(wpa_s, MSG_DEBUG,
1840 "WPA: Disable PMKSA caching for FT/802.1X connection");
1841 pmksa_cache_clear_current(wpa_s->wpa);
1842 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001843#endif /* CONFIG_IEEE80211R */
1844#ifdef CONFIG_DPP
1845 } else if (sel & WPA_KEY_MGMT_DPP) {
1846 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1847 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1848#endif /* CONFIG_DPP */
1849#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001850 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1851 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1852 wpa_dbg(wpa_s, MSG_DEBUG,
1853 "RSN: using KEY_MGMT FT/SAE (ext key)");
1854 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1855 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1856 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001857 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1858 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1859 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1860 } else if (sel & WPA_KEY_MGMT_SAE) {
1861 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1862 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1863#endif /* CONFIG_SAE */
1864#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1866 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1867 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1868#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1870 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1871 wpa_dbg(wpa_s, MSG_DEBUG,
1872 "WPA: using KEY_MGMT 802.1X with SHA256");
1873 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1874 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1875 wpa_dbg(wpa_s, MSG_DEBUG,
1876 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1878 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1879 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1880 } else if (sel & WPA_KEY_MGMT_PSK) {
1881 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1882 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1883 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1884 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1885 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001886#ifdef CONFIG_HS20
1887 } else if (sel & WPA_KEY_MGMT_OSEN) {
1888 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1889 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1890#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001891#ifdef CONFIG_OWE
1892 } else if (sel & WPA_KEY_MGMT_OWE) {
1893 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1894 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1895#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001896 } else {
1897 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1898 "authenticated key management type");
1899 return -1;
1900 }
1901
1902 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1903 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1904 wpa_s->pairwise_cipher);
1905 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1906
Hai Shalomc3565922019-10-28 11:58:20 -07001907 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001908 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1909 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001910 wpa_msg(wpa_s, MSG_INFO,
1911 "RSN: Management frame protection required but the selected AP does not enable it");
1912 return -1;
1913 }
1914
Hai Shalomc1a21442022-02-04 13:43:00 -08001915 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001916#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001917 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1918 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1919 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001920#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001921 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001922 if ((ssid->sae_password_id ||
1923 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001924 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1925 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1926 if (bss && is_6ghz_freq(bss->freq) &&
1927 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1928 wpa_dbg(wpa_s, MSG_DEBUG,
1929 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1930 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001931 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001932 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001933#ifdef CONFIG_SAE_PK
1934 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1935 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1936 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1937 ((ssid->sae_password &&
1938 sae_pk_valid_password(ssid->sae_password)) ||
1939 (!ssid->sae_password && ssid->passphrase &&
1940 sae_pk_valid_password(ssid->passphrase))));
1941#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001942 if (bss && is_6ghz_freq(bss->freq) &&
1943 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1944 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1945 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1946 MGMT_FRAME_PROTECTION_REQUIRED);
1947 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001948#ifdef CONFIG_TESTING_OPTIONS
1949 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1950 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001951 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1952 wpa_s->oci_freq_override_eapol);
1953 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1954 wpa_s->oci_freq_override_eapol_g2);
1955 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1956 wpa_s->oci_freq_override_ft_assoc);
1957 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1958 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001959 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1960 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001961#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001962
1963 /* Extended Key ID is only supported in infrastructure BSS so far */
1964 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1965 (ssid->proto & WPA_PROTO_RSN) &&
1966 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1967 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1968 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1969 int use_ext_key_id = 0;
1970
1971 wpa_msg(wpa_s, MSG_DEBUG,
1972 "WPA: Enable Extended Key ID support");
1973 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1974 wpa_s->conf->extended_key_id);
1975 if (bss_rsn &&
1976 wpa_s->conf->extended_key_id &&
1977 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1978 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1979 use_ext_key_id = 1;
1980 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1981 use_ext_key_id);
1982 } else {
1983 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1984 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1985 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001986
Sunil Ravi640215c2023-06-28 23:08:09 +00001987 /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
1988 * appropriate advertisement of the supported number of PTKSA receive
1989 * counters. In theory, this could be based on a driver capability, but
1990 * in practice all cases using WMM support at least eight replay
1991 * counters, so use a hardcoded value for now since there is no explicit
1992 * driver capability indication for this.
1993 *
1994 * In addition, claim WMM to be enabled if the AP supports it since it
1995 * is far more likely for any current device to support WMM. */
1996 wmm = wpa_s->connection_set &&
1997 (wpa_s->connection_ht || wpa_s->connection_vht ||
1998 wpa_s->connection_he || wpa_s->connection_eht);
1999 if (!wmm && bss)
2000 wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
2001 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
2002
Sunil Ravi77d572f2023-01-17 23:58:31 +00002003 if (!skip_default_rsne) {
2004 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
2005 wpa_ie_len)) {
2006 wpa_msg(wpa_s, MSG_WARNING,
2007 "RSN: Failed to generate RSNE/WPA IE");
2008 return -1;
2009 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010
Sunil Ravi77d572f2023-01-17 23:58:31 +00002011 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
2012 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
2013 &wpa_s->rsnxe_len)) {
2014 wpa_msg(wpa_s, MSG_WARNING,
2015 "RSN: Failed to generate RSNXE");
2016 return -1;
2017 }
Hai Shalomc3565922019-10-28 11:58:20 -07002018 }
2019
Hai Shalom021b0b52019-04-10 11:17:58 -07002020 if (0) {
2021#ifdef CONFIG_DPP
2022 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2023 /* Use PMK from DPP network introduction (PMKSA entry) */
2024 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002025#ifdef CONFIG_DPP2
2026 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2027#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002028#endif /* CONFIG_DPP */
2029 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002030 int psk_set = 0;
2031
Sunil Ravi77d572f2023-01-17 23:58:31 +00002032 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2033 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002034
Sunil Ravi77d572f2023-01-17 23:58:31 +00002035 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2036 psk) == 0) {
2037 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2038 NULL);
2039 psk_set = 1;
2040 }
2041 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002042 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002043
Roshan Pius3a1667e2018-07-03 15:17:14 -07002044 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002045 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002046 psk_set = 1;
2047
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002048 if (!psk_set) {
2049 wpa_msg(wpa_s, MSG_INFO,
2050 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002051 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002052 return -1;
2053 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002054#ifdef CONFIG_OWE
2055 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2056 /* OWE Diffie-Hellman exchange in (Re)Association
2057 * Request/Response frames set the PMK, so do not override it
2058 * here. */
2059#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002060 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2062
Hai Shalomfdcde762020-04-02 11:19:20 -07002063 if (ssid->mode != WPAS_MODE_IBSS &&
2064 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2065 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2066 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2067 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2068 wpa_msg(wpa_s, MSG_INFO,
2069 "Disable PTK0 rekey support - replaced with reconnect");
2070 wpa_s->deny_ptk0_rekey = 1;
2071 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2072 } else {
2073 wpa_s->deny_ptk0_rekey = 0;
2074 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2075 }
2076
Winnie Chen4138eec2022-11-10 16:32:53 +08002077#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302078 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002079 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2080 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002081 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2082 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302083 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2084 wpa_dbg(wpa_s, MSG_INFO,
2085 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2086 }
Sunil Ravif42be322022-11-04 03:31:21 +00002087#else
2088 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2089 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2090 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002091#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302092
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 return 0;
2094}
2095
2096
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002097static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
2098{
Hai Shalomc1a21442022-02-04 13:43:00 -08002099 bool scs = true, mscs = true;
2100
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002101 *pos = 0x00;
2102
2103 switch (idx) {
2104 case 0: /* Bits 0-7 */
2105 break;
2106 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002107 if (wpa_s->conf->coloc_intf_reporting) {
2108 /* Bit 13 - Collocated Interference Reporting */
2109 *pos |= 0x20;
2110 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002111 break;
2112 case 2: /* Bits 16-23 */
2113#ifdef CONFIG_WNM
2114 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002115 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002116 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002117#endif /* CONFIG_WNM */
2118 break;
2119 case 3: /* Bits 24-31 */
2120#ifdef CONFIG_WNM
2121 *pos |= 0x02; /* Bit 25 - SSID List */
2122#endif /* CONFIG_WNM */
2123#ifdef CONFIG_INTERWORKING
2124 if (wpa_s->conf->interworking)
2125 *pos |= 0x80; /* Bit 31 - Interworking */
2126#endif /* CONFIG_INTERWORKING */
2127 break;
2128 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002129#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002130 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002131 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002132#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002133 break;
2134 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002135#ifdef CONFIG_HS20
2136 if (wpa_s->conf->hs20)
2137 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2138#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002139#ifdef CONFIG_MBO
2140 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2141#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002142 break;
2143 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002144#ifdef CONFIG_TESTING_OPTIONS
2145 if (wpa_s->disable_scs_support)
2146 scs = false;
2147#endif /* CONFIG_TESTING_OPTIONS */
2148 if (scs)
2149 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002150 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002151 case 7: /* Bits 56-63 */
2152 break;
2153 case 8: /* Bits 64-71 */
2154 if (wpa_s->conf->ftm_responder)
2155 *pos |= 0x40; /* Bit 70 - FTM responder */
2156 if (wpa_s->conf->ftm_initiator)
2157 *pos |= 0x80; /* Bit 71 - FTM initiator */
2158 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002159 case 9: /* Bits 72-79 */
2160#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002161 if (!wpa_s->disable_fils)
2162 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002163#endif /* CONFIG_FILS */
2164 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002165 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002166#ifdef CONFIG_TESTING_OPTIONS
2167 if (wpa_s->disable_mscs_support)
2168 mscs = false;
2169#endif /* CONFIG_TESTING_OPTIONS */
2170 if (mscs)
2171 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002172 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002173 }
2174}
2175
2176
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002177int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002178{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002179 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002180 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002181
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002182 if (len < wpa_s->extended_capa_len)
2183 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002184 if (buflen < (size_t) len + 2) {
2185 wpa_printf(MSG_INFO,
2186 "Not enough room for building extended capabilities element");
2187 return -1;
2188 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002189
2190 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002191 *pos++ = len;
2192 for (i = 0; i < len; i++, pos++) {
2193 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002194
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002195 if (i < wpa_s->extended_capa_len) {
2196 *pos &= ~wpa_s->extended_capa_mask[i];
2197 *pos |= wpa_s->extended_capa[i];
2198 }
2199 }
2200
2201 while (len > 0 && buf[1 + len] == 0) {
2202 len--;
2203 buf[1] = len;
2204 }
2205 if (len == 0)
2206 return 0;
2207
2208 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002209}
2210
2211
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002212static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2213 struct wpa_bss *test_bss)
2214{
2215 struct wpa_bss *bss;
2216
2217 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2218 if (bss == test_bss)
2219 return 1;
2220 }
2221
2222 return 0;
2223}
2224
2225
2226static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2227 struct wpa_ssid *test_ssid)
2228{
2229 struct wpa_ssid *ssid;
2230
2231 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2232 if (ssid == test_ssid)
2233 return 1;
2234 }
2235
2236 return 0;
2237}
2238
2239
2240int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2241 struct wpa_ssid *test_ssid)
2242{
2243 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2244 return 0;
2245
2246 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2247}
2248
2249
2250void wpas_connect_work_free(struct wpa_connect_work *cwork)
2251{
2252 if (cwork == NULL)
2253 return;
2254 os_free(cwork);
2255}
2256
2257
2258void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2259{
2260 struct wpa_connect_work *cwork;
2261 struct wpa_radio_work *work = wpa_s->connect_work;
2262
2263 if (!work)
2264 return;
2265
2266 wpa_s->connect_work = NULL;
2267 cwork = work->ctx;
2268 work->ctx = NULL;
2269 wpas_connect_work_free(cwork);
2270 radio_work_done(work);
2271}
2272
2273
Sunil Ravi77d572f2023-01-17 23:58:31 +00002274int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2275 enum wpas_mac_addr_style style,
2276 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002277{
2278 struct os_reltime now;
2279 u8 addr[ETH_ALEN];
2280
2281 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002282 /* Random addresses are valid within a given ESS so check
2283 * expiration/value only when continuing to use the same ESS. */
2284 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2285 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2286 /* Pregenerated addresses do not expire but their value
2287 * might have changed, so let's check that. */
2288 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2289 ETH_ALEN) == 0)
2290 return 0;
2291 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2292 wpa_s->last_mac_addr_change.usec != 0) &&
2293 !os_reltime_expired(
2294 &now,
2295 &wpa_s->last_mac_addr_change,
2296 wpa_s->conf->rand_addr_lifetime)) {
2297 wpa_msg(wpa_s, MSG_DEBUG,
2298 "Previously selected random MAC address has not yet expired");
2299 return 0;
2300 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002301 }
2302
2303 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002304 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002305 if (random_mac_addr(addr) < 0)
2306 return -1;
2307 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002308 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002309 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2310 if (random_mac_addr_keep_oui(addr) < 0)
2311 return -1;
2312 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002313 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2314 if (!ssid) {
2315 wpa_msg(wpa_s, MSG_INFO,
2316 "Invalid 'ssid' for address policy 3");
2317 return -1;
2318 }
2319 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2320 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002321 default:
2322 return -1;
2323 }
2324
2325 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2326 wpa_msg(wpa_s, MSG_INFO,
2327 "Failed to set random MAC address");
2328 return -1;
2329 }
2330
2331 os_get_reltime(&wpa_s->last_mac_addr_change);
2332 wpa_s->mac_addr_changed = 1;
2333 wpa_s->last_mac_addr_style = style;
2334
2335 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2336 wpa_msg(wpa_s, MSG_INFO,
2337 "Could not update MAC address information");
2338 return -1;
2339 }
2340
2341 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2342 MAC2STR(addr));
2343
Sunil Ravi77d572f2023-01-17 23:58:31 +00002344 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002345}
2346
2347
2348int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2349{
2350 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2351 !wpa_s->conf->preassoc_mac_addr)
2352 return 0;
2353
Sunil Ravi77d572f2023-01-17 23:58:31 +00002354 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2355 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002356}
2357
2358
Sunil Ravi036cec52023-03-29 11:35:17 -07002359void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2360 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002361{
2362#ifdef CONFIG_SAE
2363 int *groups = conf->sae_groups;
2364 int default_groups[] = { 19, 20, 21, 0 };
2365 const char *password;
2366
2367 if (!groups || groups[0] <= 0)
2368 groups = default_groups;
2369
2370 password = ssid->sae_password;
2371 if (!password)
2372 password = ssid->passphrase;
2373
Hai Shalom899fcc72020-10-19 14:38:18 -07002374 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002375 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002376 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002377 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002378 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002379 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002380 /* PT derivation not needed */
2381 sae_deinit_pt(ssid->pt);
2382 ssid->pt = NULL;
2383 return;
2384 }
2385
2386 if (ssid->pt)
2387 return; /* PT already derived */
2388 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2389 (const u8 *) password, os_strlen(password),
2390 ssid->sae_password_id);
2391#endif /* CONFIG_SAE */
2392}
2393
2394
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002395static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2396{
2397#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2398 os_free(wpa_s->sme.sae_rejected_groups);
2399 wpa_s->sme.sae_rejected_groups = NULL;
2400#ifdef CONFIG_TESTING_OPTIONS
2401 if (wpa_s->extra_sae_rejected_groups) {
2402 int i, *groups = wpa_s->extra_sae_rejected_groups;
2403
2404 for (i = 0; groups[i]; i++) {
2405 wpa_printf(MSG_DEBUG,
2406 "TESTING: Indicate rejection of an extra SAE group %d",
2407 groups[i]);
2408 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2409 groups[i]);
2410 }
2411 }
2412#endif /* CONFIG_TESTING_OPTIONS */
2413#endif /* CONFIG_SAE && CONFIG_SME */
2414}
2415
2416
Hai Shalom60840252021-02-19 19:02:11 -08002417int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2418{
2419 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2420 wpa_msg(wpa_s, MSG_INFO,
2421 "Could not restore permanent MAC address");
2422 return -1;
2423 }
2424 wpa_s->mac_addr_changed = 0;
2425 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2426 wpa_msg(wpa_s, MSG_INFO,
2427 "Could not update MAC address information");
2428 return -1;
2429 }
2430 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2431 return 0;
2432}
2433
2434
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002435static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437/**
2438 * wpa_supplicant_associate - Request association
2439 * @wpa_s: Pointer to wpa_supplicant data
2440 * @bss: Scan results for the selected BSS, or %NULL if not available
2441 * @ssid: Configuration data for the selected network
2442 *
2443 * This function is used to request %wpa_supplicant to associate with a BSS.
2444 */
2445void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2446 struct wpa_bss *bss, struct wpa_ssid *ssid)
2447{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002448 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002449 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002450
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002451 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002452 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002453
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002454 /*
2455 * If we are starting a new connection, any previously pending EAPOL
2456 * RX cannot be valid anymore.
2457 */
2458 wpabuf_free(wpa_s->pending_eapol_rx);
2459 wpa_s->pending_eapol_rx = NULL;
2460
Sunil Ravi77d572f2023-01-17 23:58:31 +00002461 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002462 rand_style = wpa_s->conf->mac_addr;
2463 else
2464 rand_style = ssid->mac_addr;
2465
Sunil Ravia04bd252022-05-02 22:54:18 -07002466 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002467 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002468 wmm_ac_clear_saved_tspecs(wpa_s);
2469 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002470 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002471#ifdef CONFIG_TESTING_OPTIONS
2472 wpa_s->testing_resend_assoc = 0;
2473#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002474
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002475 if (wpa_s->last_ssid == ssid) {
2476 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002477 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002478 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2479 wmm_ac_save_tspecs(wpa_s);
2480 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002481 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2482 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002483 }
Hai Shalomc3565922019-10-28 11:58:20 -07002484 } else {
2485#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002486 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002487#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002488 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002489#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002490 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002491#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002492
Sunil Ravi77d572f2023-01-17 23:58:31 +00002493 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2494 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2495
2496 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002497 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002498 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2499 status > 0) /* MAC changed */
2500 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2501 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2502 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002503 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002504 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002505 }
2506 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507
2508#ifdef CONFIG_IBSS_RSN
2509 ibss_rsn_deinit(wpa_s->ibss_rsn);
2510 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002511#else /* CONFIG_IBSS_RSN */
2512 if (ssid->mode == WPAS_MODE_IBSS &&
2513 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2514 wpa_msg(wpa_s, MSG_INFO,
2515 "IBSS RSN not supported in the build");
2516 return;
2517 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518#endif /* CONFIG_IBSS_RSN */
2519
2520 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2521 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2522#ifdef CONFIG_AP
2523 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2524 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2525 "mode");
2526 return;
2527 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002528 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2529 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002530 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2531 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002532 return;
2533 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 wpa_s->current_bss = bss;
2535#else /* CONFIG_AP */
2536 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2537 "the build");
2538#endif /* CONFIG_AP */
2539 return;
2540 }
2541
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002542 if (ssid->mode == WPAS_MODE_MESH) {
2543#ifdef CONFIG_MESH
2544 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2545 wpa_msg(wpa_s, MSG_INFO,
2546 "Driver does not support mesh mode");
2547 return;
2548 }
2549 if (bss)
2550 ssid->frequency = bss->freq;
2551 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002552 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002553 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2554 return;
2555 }
2556 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002557#else /* CONFIG_MESH */
2558 wpa_msg(wpa_s, MSG_ERROR,
2559 "mesh mode support not included in the build");
2560#endif /* CONFIG_MESH */
2561 return;
2562 }
2563
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002564 /*
2565 * Set WPA state machine configuration to match the selected network now
2566 * so that the information is available before wpas_start_assoc_cb()
2567 * gets called. This is needed at least for RSN pre-authentication where
2568 * candidate APs are added to a list based on scan result processing
2569 * before completion of the first association.
2570 */
2571 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2572
2573#ifdef CONFIG_DPP
2574 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2575 return;
2576#endif /* CONFIG_DPP */
2577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578#ifdef CONFIG_TDLS
2579 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002580 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581#endif /* CONFIG_TDLS */
2582
Hai Shalomc3565922019-10-28 11:58:20 -07002583#ifdef CONFIG_MBO
2584 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2585#endif /* CONFIG_MBO */
2586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002588 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 sme_authenticate(wpa_s, bss, ssid);
2590 return;
2591 }
2592
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002593 if (wpa_s->connect_work) {
2594 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2595 return;
2596 }
2597
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002598 if (radio_work_pending(wpa_s, "connect")) {
2599 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2600 return;
2601 }
2602
Dmitry Shmidt29333592017-01-09 12:27:11 -08002603#ifdef CONFIG_SME
2604 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2605 /* Clear possibly set auth_alg, if any, from last attempt. */
2606 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2607 }
2608#endif /* CONFIG_SME */
2609
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002610 wpas_abort_ongoing_scan(wpa_s);
2611
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002612 cwork = os_zalloc(sizeof(*cwork));
2613 if (cwork == NULL)
2614 return;
2615
2616 cwork->bss = bss;
2617 cwork->ssid = ssid;
2618
2619 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2620 wpas_start_assoc_cb, cwork) < 0) {
2621 os_free(cwork);
2622 }
2623}
2624
2625
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002626static int bss_is_ibss(struct wpa_bss *bss)
2627{
2628 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2629 IEEE80211_CAP_IBSS;
2630}
2631
2632
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002633static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2634 const struct wpa_ssid *ssid)
2635{
2636 enum hostapd_hw_mode hw_mode;
2637 struct hostapd_hw_modes *mode = NULL;
2638 u8 channel;
2639 int i;
2640
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002641 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2642 if (hw_mode == NUM_HOSTAPD_MODES)
2643 return 0;
2644 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2645 if (wpa_s->hw.modes[i].mode == hw_mode) {
2646 mode = &wpa_s->hw.modes[i];
2647 break;
2648 }
2649 }
2650
2651 if (!mode)
2652 return 0;
2653
2654 return mode->vht_capab != 0;
2655}
2656
2657
Hai Shalomc1a21442022-02-04 13:43:00 -08002658static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2659{
2660 int i;
2661
2662 for (i = channel; i < channel + 16; i += 4) {
2663 struct hostapd_channel_data *chan;
2664
2665 chan = hw_get_channel_chan(mode, i, NULL);
2666 if (!chan ||
2667 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2668 return false;
2669 }
2670
2671 return true;
2672}
2673
2674
Sunil Ravi036cec52023-03-29 11:35:17 -07002675static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2676 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002677{
Sunil Ravi036cec52023-03-29 11:35:17 -07002678 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002679
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002680 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2681 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2682
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002683 if (!bss_is_ibss(bss))
2684 continue;
2685
2686 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002687 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2688 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002689 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002690 return NULL;
2691}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002692
Sunil Ravi036cec52023-03-29 11:35:17 -07002693
2694static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2695 const struct wpa_ssid *ssid,
2696 struct hostapd_hw_modes *mode)
2697{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002698 /* For IBSS check HT_IBSS flag */
2699 if (ssid->mode == WPAS_MODE_IBSS &&
2700 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002701 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002702
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002703 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2704 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2705 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2706 wpa_printf(MSG_DEBUG,
2707 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002708 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002709 }
2710
Sunil Ravi036cec52023-03-29 11:35:17 -07002711 if (!ht_supported(mode))
2712 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002713
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002714#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002715 if (ssid->disable_ht)
2716 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002717#endif /* CONFIG_HT_OVERRIDES */
2718
Sunil Ravi036cec52023-03-29 11:35:17 -07002719 return true;
2720}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002721
Sunil Ravi036cec52023-03-29 11:35:17 -07002722
2723static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2724 const struct wpa_ssid *ssid,
2725 struct hostapd_hw_modes *mode)
2726{
2727 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2728 return false;
2729
2730 if (!drv_supports_vht(wpa_s, ssid))
2731 return false;
2732
2733 /* For IBSS check VHT_IBSS flag */
2734 if (ssid->mode == WPAS_MODE_IBSS &&
2735 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2736 return false;
2737
2738 if (!vht_supported(mode))
2739 return false;
2740
2741#ifdef CONFIG_VHT_OVERRIDES
2742 if (ssid->disable_vht)
2743 return false;
2744#endif /* CONFIG_VHT_OVERRIDES */
2745
2746 return true;
2747}
2748
2749
2750static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2751 const struct wpa_ssid *ssid,
2752 const struct hostapd_hw_modes *mode,
2753 int ieee80211_mode)
2754{
Hai Shalomfdcde762020-04-02 11:19:20 -07002755#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002756 if (ssid->disable_he)
2757 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002758#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002759
Sunil Ravi036cec52023-03-29 11:35:17 -07002760 switch (mode->mode) {
2761 case HOSTAPD_MODE_IEEE80211G:
2762 case HOSTAPD_MODE_IEEE80211B:
2763 case HOSTAPD_MODE_IEEE80211A:
2764 return mode->he_capab[ieee80211_mode].he_supported;
2765 default:
2766 return false;
2767 }
2768}
2769
2770
2771static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2772 const struct wpa_ssid *ssid,
2773 const struct hostapd_hw_modes *mode,
2774 int ieee80211_mode)
2775{
2776 if (ssid->disable_eht)
2777 return false;
2778
2779 switch(mode->mode) {
2780 case HOSTAPD_MODE_IEEE80211G:
2781 case HOSTAPD_MODE_IEEE80211B:
2782 case HOSTAPD_MODE_IEEE80211A:
2783 return mode->eht_capab[ieee80211_mode].eht_supported;
2784 default:
2785 return false;
2786 }
2787}
2788
2789
2790static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2791 const struct wpa_ssid *ssid,
2792 struct hostapd_hw_modes *mode,
2793 struct hostapd_freq_params *freq,
2794 int obss_scan) {
2795 int chan_idx;
2796 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2797 int i, res;
2798 unsigned int j;
2799 static const int ht40plus[] = {
2800 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 165, 173,
2801 184, 192
2802 };
2803 int ht40 = -1;
2804
2805 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002806 return;
2807
2808 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2809 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002810 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002811 break;
2812 pri_chan = NULL;
2813 }
2814 if (!pri_chan)
2815 return;
2816
2817 /* Check primary channel flags */
2818 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2819 return;
2820
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002821#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002822 if (ssid->disable_ht40)
2823 return;
2824#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002825
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002826 /* Check/setup HT40+/HT40- */
2827 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002828 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002829 ht40 = 1;
2830 break;
2831 }
2832 }
2833
2834 /* Find secondary channel */
2835 for (i = 0; i < mode->num_channels; i++) {
2836 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002837 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002838 break;
2839 sec_chan = NULL;
2840 }
2841 if (!sec_chan)
2842 return;
2843
2844 /* Check secondary channel flags */
2845 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2846 return;
2847
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002848 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002849 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2850 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002851 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002852 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2853 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002854 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002855 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002856
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002857 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002858 struct wpa_scan_results *scan_res;
2859
2860 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2861 if (scan_res == NULL) {
2862 /* Back to HT20 */
2863 freq->sec_channel_offset = 0;
2864 return;
2865 }
2866
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002867 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002868 switch (res) {
2869 case 0:
2870 /* Back to HT20 */
2871 freq->sec_channel_offset = 0;
2872 break;
2873 case 1:
2874 /* Configuration allowed */
2875 break;
2876 case 2:
2877 /* Switch pri/sec channels */
2878 freq->freq = hw_get_freq(mode, sec_chan->chan);
2879 freq->sec_channel_offset = -freq->sec_channel_offset;
2880 freq->channel = sec_chan->chan;
2881 break;
2882 default:
2883 freq->sec_channel_offset = 0;
2884 break;
2885 }
2886
2887 wpa_scan_results_free(scan_res);
2888 }
2889
2890 wpa_printf(MSG_DEBUG,
2891 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2892 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002893}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002894
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002895
Sunil Ravi036cec52023-03-29 11:35:17 -07002896static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2897 const struct wpa_ssid *ssid,
2898 struct hostapd_hw_modes *mode,
2899 struct hostapd_freq_params *freq,
2900 int ieee80211_mode, bool is_6ghz) {
2901 static const int bw80[] = {
2902 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2903 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2904 6515, 6595, 6675, 6755, 6835, 6915, 6995
2905 };
2906 static const int bw160[] = {
2907 5955, 6115, 6275, 6435, 6595, 6755, 6915
2908 };
2909 struct hostapd_freq_params vht_freq;
2910 int i;
2911 unsigned int j, k;
2912 int chwidth, seg0, seg1;
2913 u32 vht_caps = 0;
2914 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002915
Sunil Ravi036cec52023-03-29 11:35:17 -07002916 if (!freq->vht_enabled && !freq->he_enabled)
2917 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002918
Hai Shalomc1a21442022-02-04 13:43:00 -08002919 vht_freq = *freq;
2920
Sunil Ravi036cec52023-03-29 11:35:17 -07002921 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2922 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2923 seg1 = 0;
2924 if (freq->sec_channel_offset == 0) {
2925 seg0 = 0;
2926 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2927 if (freq->ht_enabled && !is_6ghz)
2928 goto skip_80mhz;
2929 }
2930 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2931 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002932
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002933 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002934 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2935 if (freq->freq >= bw80[j] &&
2936 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002937 break;
2938 }
2939
Hai Shalomc1a21442022-02-04 13:43:00 -08002940 if (j == ARRAY_SIZE(bw80) ||
2941 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002942 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002943
Sunil Ravi036cec52023-03-29 11:35:17 -07002944 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002945 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002946 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002947
Sunil8cd6f4d2022-06-28 18:40:46 +00002948 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002949 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002950 seg1 = 0;
2951
Sunil Ravi036cec52023-03-29 11:35:17 -07002952 /* In 160 MHz, the initial four 20 MHz channels were validated
2953 * above. If 160 MHz is supported, check the remaining four 20 MHz
2954 * channels for the total of 160 MHz bandwidth for 6 GHz.
2955 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002956 if ((mode->he_capab[ieee80211_mode].phy_cap[
2957 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002958 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2959 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002960 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2961 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002962 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002963 seg0 = channel + 14;
2964 break;
2965 }
2966 }
2967 }
2968
Sunil8cd6f4d2022-06-28 18:40:46 +00002969 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002970 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002971 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002972 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002973 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002974 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002975
2976 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2977 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002978 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08002979
2980 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002981 struct hostapd_channel_data *chan;
2982
2983 chan = hw_get_channel_chan(mode, i, NULL);
2984 if (!chan)
2985 continue;
2986
2987 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2988 HOSTAPD_CHAN_NO_IR |
2989 HOSTAPD_CHAN_RADAR))
2990 continue;
2991
2992 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002993 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002994 if (!is_6ghz)
2995 vht_caps |=
2996 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2997 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002998 }
2999
Sunil8cd6f4d2022-06-28 18:40:46 +00003000 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003001 break;
3002 }
Sunil8cd6f4d2022-06-28 18:40:46 +00003003 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003004 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003005 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003006 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3007 seg0 = 50;
3008 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00003009 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07003010 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
3011 seg0 = 114;
3012 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003013 }
3014
Sunil Ravi036cec52023-03-29 11:35:17 -07003015skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003016 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07003017 freq->channel, ssid->enable_edmg,
3018 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003019 freq->vht_enabled, freq->he_enabled,
3020 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003021 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003022 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003023 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003024 &mode->eht_capab[ieee80211_mode]) != 0)
3025 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003026
3027 *freq = vht_freq;
3028
3029 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3030 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003031 return true;
3032}
3033
3034
3035void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3036 const struct wpa_ssid *ssid,
3037 struct hostapd_freq_params *freq)
3038{
3039 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3040 enum hostapd_hw_mode hw_mode;
3041 struct hostapd_hw_modes *mode = NULL;
3042 int i, obss_scan = 1;
3043 u8 channel;
3044 bool is_6ghz;
3045
3046 freq->freq = ssid->frequency;
3047
3048 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3049 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3050
3051 if (bss) {
3052 wpa_printf(MSG_DEBUG,
3053 "IBSS already found in scan results, adjust control freq: %d",
3054 bss->freq);
3055 freq->freq = bss->freq;
3056 obss_scan = 0;
3057 }
3058 }
3059
3060 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3061 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3062 if (wpa_s->hw.modes[i].mode == hw_mode &&
3063 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3064 NULL) != NULL) {
3065 mode = &wpa_s->hw.modes[i];
3066 break;
3067 }
3068 }
3069
3070 if (!mode)
3071 return;
3072
3073 is_6ghz = is_6ghz_freq(freq->freq);
3074
3075 freq->ht_enabled = 0;
3076 freq->vht_enabled = 0;
3077 freq->he_enabled = 0;
3078 freq->eht_enabled = 0;
3079
3080 if (!is_6ghz)
3081 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3082 if (freq->ht_enabled)
3083 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3084 if (freq->vht_enabled || is_6ghz)
3085 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3086 ieee80211_mode);
3087 freq->channel = channel;
3088 /* Setup higher BW only for 5 GHz */
3089 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3090 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3091 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3092 ieee80211_mode, is_6ghz))
3093 freq->he_enabled = freq->vht_enabled = false;
3094 }
3095
3096 if (freq->he_enabled)
3097 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3098 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003099}
3100
3101
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003102#ifdef CONFIG_FILS
3103static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3104 size_t ie_buf_len)
3105{
3106 struct fils_hlp_req *req;
3107 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3108 const u8 *pos;
3109 u8 *buf = ie_buf;
3110
3111 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3112 list) {
3113 rem_len = ie_buf_len - ie_len;
3114 pos = wpabuf_head(req->pkt);
3115 hdr_len = 1 + 2 * ETH_ALEN + 6;
3116 hlp_len = wpabuf_len(req->pkt);
3117
3118 if (rem_len < 2 + hdr_len + hlp_len) {
3119 wpa_printf(MSG_ERROR,
3120 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3121 (unsigned long) rem_len,
3122 (unsigned long) (2 + hdr_len + hlp_len));
3123 break;
3124 }
3125
3126 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3127 /* Element ID */
3128 *buf++ = WLAN_EID_EXTENSION;
3129 /* Length */
3130 *buf++ = len;
3131 /* Element ID Extension */
3132 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3133 /* Destination MAC address */
3134 os_memcpy(buf, req->dst, ETH_ALEN);
3135 buf += ETH_ALEN;
3136 /* Source MAC address */
3137 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3138 buf += ETH_ALEN;
3139 /* LLC/SNAP Header */
3140 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3141 buf += 6;
3142 /* HLP Packet */
3143 os_memcpy(buf, pos, len - hdr_len);
3144 buf += len - hdr_len;
3145 pos += len - hdr_len;
3146
3147 hlp_len -= len - hdr_len;
3148 ie_len += 2 + len;
3149 rem_len -= 2 + len;
3150
3151 while (hlp_len) {
3152 len = (hlp_len > 255) ? 255 : hlp_len;
3153 if (rem_len < 2 + len)
3154 break;
3155 *buf++ = WLAN_EID_FRAGMENT;
3156 *buf++ = len;
3157 os_memcpy(buf, pos, len);
3158 buf += len;
3159 pos += len;
3160
3161 hlp_len -= len;
3162 ie_len += 2 + len;
3163 rem_len -= 2 + len;
3164 }
3165 }
3166
3167 return ie_len;
3168}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003169
3170
3171int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3172{
3173 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3174 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3175 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3176 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3177}
3178
3179
3180int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3181{
3182#ifdef CONFIG_FILS_SK_PFS
3183 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3184 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3185#else /* CONFIG_FILS_SK_PFS */
3186 return 0;
3187#endif /* CONFIG_FILS_SK_PFS */
3188}
3189
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190#endif /* CONFIG_FILS */
3191
3192
Hai Shalomc1a21442022-02-04 13:43:00 -08003193static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3194 struct wpa_bss *bss,
3195 u8 *wpa_ie, size_t wpa_ie_len,
3196 size_t max_wpa_ie_len)
3197{
3198 struct wpabuf *wfa_ie = NULL;
3199 u8 wfa_capa[1];
3200 size_t wfa_ie_len, buf_len;
3201
3202 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3203 if (wpa_s->enable_dscp_policy_capa)
3204 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3205
3206 if (!wfa_capa[0])
3207 return wpa_ie_len;
3208
3209 /* Wi-Fi Alliance element */
3210 buf_len = 1 + /* Element ID */
3211 1 + /* Length */
3212 3 + /* OUI */
3213 1 + /* OUI Type */
3214 1 + /* Capabilities Length */
3215 sizeof(wfa_capa); /* Capabilities */
3216 wfa_ie = wpabuf_alloc(buf_len);
3217 if (!wfa_ie)
3218 return wpa_ie_len;
3219
3220 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3221 wpabuf_put_u8(wfa_ie, buf_len - 2);
3222 wpabuf_put_be24(wfa_ie, OUI_WFA);
3223 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3224 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3225 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3226
3227 wfa_ie_len = wpabuf_len(wfa_ie);
3228 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3229 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3230 wfa_ie);
3231 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3232 wfa_ie_len);
3233 wpa_ie_len += wfa_ie_len;
3234 }
3235
3236 wpabuf_free(wfa_ie);
3237 return wpa_ie_len;
3238}
3239
3240
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003241static u8 * wpas_populate_assoc_ies(
3242 struct wpa_supplicant *wpa_s,
3243 struct wpa_bss *bss, struct wpa_ssid *ssid,
3244 struct wpa_driver_associate_params *params,
3245 enum wpa_drv_update_connect_params_mask *mask)
3246{
3247 u8 *wpa_ie;
3248 size_t max_wpa_ie_len = 500;
3249 size_t wpa_ie_len;
3250 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003251#ifdef CONFIG_MBO
3252 const u8 *mbo_ie;
3253#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303254#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3255 int pmksa_cached = 0;
3256#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003257#ifdef CONFIG_FILS
3258 const u8 *realm, *username, *rrk;
3259 size_t realm_len, username_len, rrk_len;
3260 u16 next_seq_num;
3261 struct fils_hlp_req *req;
3262
3263 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3264 list) {
3265 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3266 2 + 2 * wpabuf_len(req->pkt) / 255;
3267 }
3268#endif /* CONFIG_FILS */
3269
3270 wpa_ie = os_malloc(max_wpa_ie_len);
3271 if (!wpa_ie) {
3272 wpa_printf(MSG_ERROR,
3273 "Failed to allocate connect IE buffer for %lu bytes",
3274 (unsigned long) max_wpa_ie_len);
3275 return NULL;
3276 }
3277
3278 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3279 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3280 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3281 int try_opportunistic;
3282 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003283 const u8 *addr = bss->bssid;
3284
Sunil Ravi036cec52023-03-29 11:35:17 -07003285 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3286 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3287 !is_zero_ether_addr(bss->mld_addr))
3288 addr = bss->mld_addr;
3289
3290 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3291 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003292 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003293
3294 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3295 wpa_s->conf->okc :
3296 ssid->proactive_key_caching) &&
3297 (ssid->proto & WPA_PROTO_RSN);
3298#ifdef CONFIG_FILS
3299 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3300 cache_id = wpa_bss_get_fils_cache_id(bss);
3301#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003302 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003303 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003304 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003305 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303306#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3307 pmksa_cached = 1;
3308#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003309 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003310 wpa_ie_len = max_wpa_ie_len;
3311 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003312 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3314 "key management and encryption suites");
3315 os_free(wpa_ie);
3316 return NULL;
3317 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003318#ifdef CONFIG_HS20
3319 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3320 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3321 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3322 wpa_ie_len = max_wpa_ie_len;
3323 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003324 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003325 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3326 "key management and encryption suites");
3327 os_free(wpa_ie);
3328 return NULL;
3329 }
3330#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003331 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3332 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3333 /*
3334 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3335 * use non-WPA since the scan results did not indicate that the
3336 * AP is using WPA or WPA2.
3337 */
3338 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3339 wpa_ie_len = 0;
3340 wpa_s->wpa_proto = 0;
3341 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3342 wpa_ie_len = max_wpa_ie_len;
3343 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003344 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003345 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3346 "key management and encryption suites (no "
3347 "scan results)");
3348 os_free(wpa_ie);
3349 return NULL;
3350 }
3351#ifdef CONFIG_WPS
3352 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3353 struct wpabuf *wps_ie;
3354 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3355 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3356 wpa_ie_len = wpabuf_len(wps_ie);
3357 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3358 } else
3359 wpa_ie_len = 0;
3360 wpabuf_free(wps_ie);
3361 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3362 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3363 params->wps = WPS_MODE_PRIVACY;
3364 else
3365 params->wps = WPS_MODE_OPEN;
3366 wpa_s->wpa_proto = 0;
3367#endif /* CONFIG_WPS */
3368 } else {
3369 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3370 wpa_ie_len = 0;
3371 wpa_s->wpa_proto = 0;
3372 }
3373
3374#ifdef IEEE8021X_EAPOL
3375 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3376 if (ssid->leap) {
3377 if (ssid->non_leap == 0)
3378 algs = WPA_AUTH_ALG_LEAP;
3379 else
3380 algs |= WPA_AUTH_ALG_LEAP;
3381 }
3382 }
3383
3384#ifdef CONFIG_FILS
3385 /* Clear FILS association */
3386 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3387
3388 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3389 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3390 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3391 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003392 &next_seq_num, &rrk, &rrk_len) == 0 &&
3393 (!wpa_s->last_con_fail_realm ||
3394 wpa_s->last_con_fail_realm_len != realm_len ||
3395 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003396 algs = WPA_AUTH_ALG_FILS;
3397 params->fils_erp_username = username;
3398 params->fils_erp_username_len = username_len;
3399 params->fils_erp_realm = realm;
3400 params->fils_erp_realm_len = realm_len;
3401 params->fils_erp_next_seq_num = next_seq_num;
3402 params->fils_erp_rrk = rrk;
3403 params->fils_erp_rrk_len = rrk_len;
3404
3405 if (mask)
3406 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303407 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3408 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3409 pmksa_cached) {
3410 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003411 }
3412#endif /* CONFIG_FILS */
3413#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003414#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003415 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003416 algs = WPA_AUTH_ALG_SAE;
3417#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003418
3419 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3420 if (ssid->auth_alg) {
3421 algs = ssid->auth_alg;
3422 wpa_dbg(wpa_s, MSG_DEBUG,
3423 "Overriding auth_alg selection: 0x%x", algs);
3424 }
3425
Hai Shalom5f92bc92019-04-18 11:54:11 -07003426#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303427 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003428 wpa_dbg(wpa_s, MSG_DEBUG,
3429 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3430 algs = WPA_AUTH_ALG_OPEN;
3431 }
3432#endif /* CONFIG_SAE */
3433
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003434#ifdef CONFIG_P2P
3435 if (wpa_s->global->p2p) {
3436 u8 *pos;
3437 size_t len;
3438 int res;
3439 pos = wpa_ie + wpa_ie_len;
3440 len = max_wpa_ie_len - wpa_ie_len;
3441 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3442 ssid->p2p_group);
3443 if (res >= 0)
3444 wpa_ie_len += res;
3445 }
3446
3447 wpa_s->cross_connect_disallowed = 0;
3448 if (bss) {
3449 struct wpabuf *p2p;
3450 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3451 if (p2p) {
3452 wpa_s->cross_connect_disallowed =
3453 p2p_get_cross_connect_disallowed(p2p);
3454 wpabuf_free(p2p);
3455 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3456 "connection",
3457 wpa_s->cross_connect_disallowed ?
3458 "disallows" : "allows");
3459 }
3460 }
3461
3462 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3463#endif /* CONFIG_P2P */
3464
3465 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003466 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003467 wpa_ie + wpa_ie_len,
3468 max_wpa_ie_len -
3469 wpa_ie_len);
3470 }
3471
3472 /*
3473 * Workaround: Add Extended Capabilities element only if the AP
3474 * included this element in Beacon/Probe Response frames. Some older
3475 * APs seem to have interoperability issues if this element is
3476 * included, so while the standard may require us to include the
3477 * element in all cases, it is justifiable to skip it to avoid
3478 * interoperability issues.
3479 */
3480 if (ssid->p2p_group)
3481 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3482 else
3483 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3484
3485 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3486 u8 ext_capab[18];
3487 int ext_capab_len;
3488 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3489 sizeof(ext_capab));
3490 if (ext_capab_len > 0 &&
3491 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3492 u8 *pos = wpa_ie;
3493 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3494 pos += 2 + pos[1];
3495 os_memmove(pos + ext_capab_len, pos,
3496 wpa_ie_len - (pos - wpa_ie));
3497 wpa_ie_len += ext_capab_len;
3498 os_memcpy(pos, ext_capab, ext_capab_len);
3499 }
3500 }
3501
3502#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003503 if (is_hs20_network(wpa_s, ssid, bss)
3504#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3505 && is_hs20_config(wpa_s)
3506#endif /* ANDROID */
3507 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003508 struct wpabuf *hs20;
3509
Roshan Pius3a1667e2018-07-03 15:17:14 -07003510 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003511 if (hs20) {
3512 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3513 size_t len;
3514
Hai Shalom74f70d42019-02-11 14:42:39 -08003515 wpas_hs20_add_indication(hs20, pps_mo_id,
3516 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003517 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003518 len = max_wpa_ie_len - wpa_ie_len;
3519 if (wpabuf_len(hs20) <= len) {
3520 os_memcpy(wpa_ie + wpa_ie_len,
3521 wpabuf_head(hs20), wpabuf_len(hs20));
3522 wpa_ie_len += wpabuf_len(hs20);
3523 }
3524 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003525 }
3526 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003527 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003528#endif /* CONFIG_HS20 */
3529
3530 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3531 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3532 size_t len;
3533
3534 len = max_wpa_ie_len - wpa_ie_len;
3535 if (wpabuf_len(buf) <= len) {
3536 os_memcpy(wpa_ie + wpa_ie_len,
3537 wpabuf_head(buf), wpabuf_len(buf));
3538 wpa_ie_len += wpabuf_len(buf);
3539 }
3540 }
3541
3542#ifdef CONFIG_FST
3543 if (wpa_s->fst_ies) {
3544 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3545
3546 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3547 os_memcpy(wpa_ie + wpa_ie_len,
3548 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3549 wpa_ie_len += fst_ies_len;
3550 }
3551 }
3552#endif /* CONFIG_FST */
3553
3554#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003555 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003556 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003557 int len;
3558
3559 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003560 max_wpa_ie_len - wpa_ie_len,
3561 !!mbo_attr_from_mbo_ie(mbo_ie,
3562 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003563 if (len >= 0)
3564 wpa_ie_len += len;
3565 }
3566#endif /* CONFIG_MBO */
3567
3568#ifdef CONFIG_FILS
3569 if (algs == WPA_AUTH_ALG_FILS) {
3570 size_t len;
3571
3572 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3573 max_wpa_ie_len - wpa_ie_len);
3574 wpa_ie_len += len;
3575 }
3576#endif /* CONFIG_FILS */
3577
3578#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003579#ifdef CONFIG_TESTING_OPTIONS
3580 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3581 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3582 } else
3583#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003584 if (algs == WPA_AUTH_ALG_OPEN &&
3585 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3586 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003587 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003588
Roshan Pius3a1667e2018-07-03 15:17:14 -07003589 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003590 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003591 } else if (wpa_s->assoc_status_code ==
3592 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003593 if (wpa_s->last_owe_group == 19)
3594 group = 20;
3595 else if (wpa_s->last_owe_group == 20)
3596 group = 21;
3597 else
3598 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003599 } else {
3600 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003601 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003602
Roshan Pius3a1667e2018-07-03 15:17:14 -07003603 wpa_s->last_owe_group = group;
3604 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003605 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3606 if (owe_ie &&
3607 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3608 os_memcpy(wpa_ie + wpa_ie_len,
3609 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3610 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003611 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003612 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003613 }
3614#endif /* CONFIG_OWE */
3615
Hai Shalom021b0b52019-04-10 11:17:58 -07003616#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003617 if (DPP_VERSION > 1 &&
3618 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003619 ssid->dpp_netaccesskey &&
3620 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003621 struct rsn_pmksa_cache_entry *pmksa;
3622
3623 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3624 if (!pmksa || !pmksa->dpp_pfs)
3625 goto pfs_fail;
3626
Hai Shalom021b0b52019-04-10 11:17:58 -07003627 dpp_pfs_free(wpa_s->dpp_pfs);
3628 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3629 ssid->dpp_netaccesskey_len);
3630 if (!wpa_s->dpp_pfs) {
3631 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3632 /* Try to continue without PFS */
3633 goto pfs_fail;
3634 }
3635 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3636 max_wpa_ie_len - wpa_ie_len) {
3637 os_memcpy(wpa_ie + wpa_ie_len,
3638 wpabuf_head(wpa_s->dpp_pfs->ie),
3639 wpabuf_len(wpa_s->dpp_pfs->ie));
3640 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3641 }
3642 }
3643pfs_fail:
3644#endif /* CONFIG_DPP2 */
3645
Roshan Pius3a1667e2018-07-03 15:17:14 -07003646#ifdef CONFIG_IEEE80211R
3647 /*
3648 * Add MDIE under these conditions: the network profile allows FT,
3649 * the AP supports FT, and the mobility domain ID matches.
3650 */
3651 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3652 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3653
3654 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3655 size_t len = 0;
3656 const u8 *md = mdie + 2;
3657 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3658
3659 if (os_memcmp(md, wpa_md,
3660 MOBILITY_DOMAIN_ID_LEN) == 0) {
3661 /* Add mobility domain IE */
3662 len = wpa_ft_add_mdie(
3663 wpa_s->wpa, wpa_ie + wpa_ie_len,
3664 max_wpa_ie_len - wpa_ie_len, mdie);
3665 wpa_ie_len += len;
3666 }
3667#ifdef CONFIG_SME
3668 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003669 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003670 wpa_dbg(wpa_s, MSG_DEBUG,
3671 "SME: Trying to use FT over-the-air");
3672 algs |= WPA_AUTH_ALG_FT;
3673 }
3674#endif /* CONFIG_SME */
3675 }
3676 }
3677#endif /* CONFIG_IEEE80211R */
3678
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003679#ifdef CONFIG_TESTING_OPTIONS
3680 if (wpa_s->rsnxe_override_assoc &&
3681 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3682 max_wpa_ie_len - wpa_ie_len) {
3683 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3684 os_memcpy(wpa_ie + wpa_ie_len,
3685 wpabuf_head(wpa_s->rsnxe_override_assoc),
3686 wpabuf_len(wpa_s->rsnxe_override_assoc));
3687 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3688 } else
3689#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003690 if (wpa_s->rsnxe_len > 0 &&
3691 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3692 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3693 wpa_ie_len += wpa_s->rsnxe_len;
3694 }
3695
Hai Shalomc1a21442022-02-04 13:43:00 -08003696#ifdef CONFIG_TESTING_OPTIONS
3697 if (wpa_s->disable_mscs_support)
3698 goto mscs_end;
3699#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003700 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3701 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003702 struct wpabuf *mscs_ie;
3703 size_t mscs_ie_len, buf_len;
3704
Hai Shalom899fcc72020-10-19 14:38:18 -07003705 buf_len = 3 + /* MSCS descriptor IE header */
3706 1 + /* Request type */
3707 2 + /* User priority control */
3708 4 + /* Stream timeout */
3709 3 + /* TCLAS Mask IE header */
3710 wpa_s->robust_av.frame_classifier_len;
3711 mscs_ie = wpabuf_alloc(buf_len);
3712 if (!mscs_ie) {
3713 wpa_printf(MSG_INFO,
3714 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003715 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003716 }
3717
3718 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3719 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3720 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3721 mscs_ie_len = wpabuf_len(mscs_ie);
3722 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3723 mscs_ie_len);
3724 wpa_ie_len += mscs_ie_len;
3725 }
3726
3727 wpabuf_free(mscs_ie);
3728 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003729mscs_end:
3730
3731 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3732 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003733
Hai Shalom74f70d42019-02-11 14:42:39 -08003734 if (ssid->multi_ap_backhaul_sta) {
3735 size_t multi_ap_ie_len;
3736
3737 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3738 max_wpa_ie_len - wpa_ie_len,
3739 MULTI_AP_BACKHAUL_STA);
3740 if (multi_ap_ie_len == 0) {
3741 wpa_printf(MSG_ERROR,
3742 "Multi-AP: Failed to build Multi-AP IE");
3743 os_free(wpa_ie);
3744 return NULL;
3745 }
3746 wpa_ie_len += multi_ap_ie_len;
3747 }
3748
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003749 params->wpa_ie = wpa_ie;
3750 params->wpa_ie_len = wpa_ie_len;
3751 params->auth_alg = algs;
3752 if (mask)
3753 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3754
3755 return wpa_ie;
3756}
3757
3758
Hai Shalomc3565922019-10-28 11:58:20 -07003759#ifdef CONFIG_OWE
3760static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3761{
3762 struct wpa_driver_associate_params params;
3763 u8 *wpa_ie;
3764
3765 os_memset(&params, 0, sizeof(params));
3766 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3767 wpa_s->current_ssid, &params, NULL);
3768 if (!wpa_ie)
3769 return;
3770
3771 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3772 os_free(wpa_ie);
3773}
3774#endif /* CONFIG_OWE */
3775
3776
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003777#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3778static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3779{
3780 struct wpa_driver_associate_params params;
3781 enum wpa_drv_update_connect_params_mask mask = 0;
3782 u8 *wpa_ie;
3783
3784 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3785 return; /* nothing to do */
3786
3787 os_memset(&params, 0, sizeof(params));
3788 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3789 wpa_s->current_ssid, &params, &mask);
3790 if (!wpa_ie)
3791 return;
3792
Hai Shalomc1a21442022-02-04 13:43:00 -08003793 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3794 wpa_s->auth_alg = params.auth_alg;
3795 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003796 }
3797
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003798 os_free(wpa_ie);
3799}
3800#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3801
3802
Hai Shalomc3565922019-10-28 11:58:20 -07003803static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3804{
3805 if (!edmg_ie || edmg_ie[1] < 6)
3806 return 0;
3807 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3808}
3809
3810
3811static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3812{
3813 if (!edmg_ie || edmg_ie[1] < 6)
3814 return 0;
3815 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3816}
3817
3818
3819/* Returns the intersection of two EDMG configurations.
3820 * Note: The current implementation is limited to CB2 only (CB1 included),
3821 * i.e., the implementation supports up to 2 contiguous channels.
3822 * For supporting non-contiguous (aggregated) channels and for supporting
3823 * CB3 and above, this function will need to be extended.
3824 */
3825static struct ieee80211_edmg_config
3826get_edmg_intersection(struct ieee80211_edmg_config a,
3827 struct ieee80211_edmg_config b,
3828 u8 primary_channel)
3829{
3830 struct ieee80211_edmg_config result;
3831 int i, contiguous = 0;
3832 int max_contiguous = 0;
3833
3834 result.channels = b.channels & a.channels;
3835 if (!result.channels) {
3836 wpa_printf(MSG_DEBUG,
3837 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3838 a.channels, b.channels);
3839 goto fail;
3840 }
3841
3842 if (!(result.channels & BIT(primary_channel - 1))) {
3843 wpa_printf(MSG_DEBUG,
3844 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3845 primary_channel, result.channels);
3846 goto fail;
3847 }
3848
3849 /* Find max contiguous channels */
3850 for (i = 0; i < 6; i++) {
3851 if (result.channels & BIT(i))
3852 contiguous++;
3853 else
3854 contiguous = 0;
3855
3856 if (contiguous > max_contiguous)
3857 max_contiguous = contiguous;
3858 }
3859
3860 /* Assuming AP and STA supports ONLY contiguous channels,
3861 * bw configuration can have value between 4-7.
3862 */
3863 if ((b.bw_config < a.bw_config))
3864 result.bw_config = b.bw_config;
3865 else
3866 result.bw_config = a.bw_config;
3867
3868 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3869 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3870 wpa_printf(MSG_DEBUG,
3871 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3872 max_contiguous);
3873 goto fail;
3874 }
3875
3876 return result;
3877
3878fail:
3879 result.channels = 0;
3880 result.bw_config = 0;
3881 return result;
3882}
3883
3884
3885static struct ieee80211_edmg_config
3886get_supported_edmg(struct wpa_supplicant *wpa_s,
3887 struct hostapd_freq_params *freq,
3888 struct ieee80211_edmg_config request_edmg)
3889{
3890 enum hostapd_hw_mode hw_mode;
3891 struct hostapd_hw_modes *mode = NULL;
3892 u8 primary_channel;
3893
3894 if (!wpa_s->hw.modes)
3895 goto fail;
3896
3897 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3898 if (hw_mode == NUM_HOSTAPD_MODES)
3899 goto fail;
3900
Hai Shalom60840252021-02-19 19:02:11 -08003901 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003902 if (!mode)
3903 goto fail;
3904
3905 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3906
3907fail:
3908 request_edmg.channels = 0;
3909 request_edmg.bw_config = 0;
3910 return request_edmg;
3911}
3912
3913
Hai Shalom021b0b52019-04-10 11:17:58 -07003914#ifdef CONFIG_MBO
3915void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3916{
3917 struct wpa_driver_associate_params params;
3918 u8 *wpa_ie;
3919
3920 /*
3921 * Update MBO connect params only in case of change of MBO attributes
3922 * when connected, if the AP support MBO.
3923 */
3924
3925 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3926 !wpa_s->current_bss ||
3927 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3928 return;
3929
3930 os_memset(&params, 0, sizeof(params));
3931 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3932 wpa_s->current_ssid, &params, NULL);
3933 if (!wpa_ie)
3934 return;
3935
3936 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3937 os_free(wpa_ie);
3938}
3939#endif /* CONFIG_MBO */
3940
3941
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003942static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3943{
3944 struct wpa_connect_work *cwork = work->ctx;
3945 struct wpa_bss *bss = cwork->bss;
3946 struct wpa_ssid *ssid = cwork->ssid;
3947 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003948 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003949 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003950 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003951 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003952 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003953 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003954#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003955 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003956#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003957 int assoc_failed = 0;
3958 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003959 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003960#ifdef CONFIG_HT_OVERRIDES
3961 struct ieee80211_ht_capabilities htcaps;
3962 struct ieee80211_ht_capabilities htcaps_mask;
3963#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003964#ifdef CONFIG_VHT_OVERRIDES
3965 struct ieee80211_vht_capabilities vhtcaps;
3966 struct ieee80211_vht_capabilities vhtcaps_mask;
3967#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003968
Hai Shalomc1a21442022-02-04 13:43:00 -08003969 wpa_s->roam_in_progress = false;
3970#ifdef CONFIG_WNM
3971 wpa_s->bss_trans_mgmt_in_progress = false;
3972#endif /* CONFIG_WNM */
3973
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003974 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003975 if (work->started) {
3976 wpa_s->connect_work = NULL;
3977
3978 /* cancel possible auth. timeout */
3979 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3980 NULL);
3981 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003982 wpas_connect_work_free(cwork);
3983 return;
3984 }
3985
3986 wpa_s->connect_work = work;
3987
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003988 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3989 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003990 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3991 wpas_connect_work_done(wpa_s);
3992 return;
3993 }
3994
Sunil Ravi640215c2023-06-28 23:08:09 +00003995 /*
3996 * Set the current AP's BSSID (for non-MLO connection) or MLD address
3997 * (for MLO connection) as the previous BSSID for reassociation requests
3998 * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
3999 * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
4000 * will be zero.
4001 */
4002 os_memcpy(prev_bssid,
4003 wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
4004 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005 os_memset(&params, 0, sizeof(params));
4006 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004007 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004008
4009 /* Starting new association, so clear the possibly used WPA IE from the
4010 * previous association. */
4011 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
4012 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
4013 wpa_s->rsnxe_len = 0;
4014 wpa_s->mscs_setup_done = false;
4015
4016 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
4017 if (!wpa_ie) {
4018 wpas_connect_work_done(wpa_s);
4019 return;
4020 }
4021
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004022 if (bss &&
4023 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024#ifdef CONFIG_IEEE80211R
4025 const u8 *ie, *md = NULL;
4026#endif /* CONFIG_IEEE80211R */
4027 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4028 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4029 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4030 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4031 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4032 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4033 if (bssid_changed)
4034 wpas_notify_bssid_changed(wpa_s);
4035#ifdef CONFIG_IEEE80211R
4036 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4037 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4038 md = ie + 2;
4039 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4040 if (md) {
4041 /* Prepare for the next transition */
4042 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4043 }
4044#endif /* CONFIG_IEEE80211R */
4045#ifdef CONFIG_WPS
4046 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4047 wpa_s->conf->ap_scan == 2 &&
4048 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4049 /* Use ap_scan==1 style network selection to find the network
4050 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004051 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004052 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004053 wpa_s->reassociate = 1;
4054 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004055 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 return;
4057#endif /* CONFIG_WPS */
4058 } else {
4059 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4060 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004061 if (bss)
4062 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4063 else
4064 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004066 if (!wpa_s->pno)
4067 wpa_supplicant_cancel_sched_scan(wpa_s);
4068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004069 wpa_supplicant_cancel_scan(wpa_s);
4070
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004071 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4072 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004073 cipher_pairwise = wpa_s->pairwise_cipher;
4074 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004075 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4077 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4078 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4079 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004080#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004081 if (wpa_set_wep_keys(wpa_s, ssid)) {
4082 use_crypt = 1;
4083 wep_keys_set = 1;
4084 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004085#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004086 }
4087 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4088 use_crypt = 0;
4089
4090#ifdef IEEE8021X_EAPOL
4091 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4092 if ((ssid->eapol_flags &
4093 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4094 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4095 !wep_keys_set) {
4096 use_crypt = 0;
4097 } else {
4098 /* Assume that dynamic WEP-104 keys will be used and
4099 * set cipher suites in order for drivers to expect
4100 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004101 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004102 }
4103 }
4104#endif /* IEEE8021X_EAPOL */
4105
4106 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4107 /* Set the key before (and later after) association */
4108 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4109 }
4110
Sunil8cd6f4d2022-06-28 18:40:46 +00004111 /* Set current_ssid before changing state to ASSOCIATING, so that the
4112 * selected SSID is available to wpas_notify_state_changed(). */
4113 old_ssid = wpa_s->current_ssid;
4114 wpa_s->current_ssid = ssid;
4115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4117 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 params.ssid = bss->ssid;
4119 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004120 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4121 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004122 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4123 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004124 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004125 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004126 ssid->bssid_set,
4127 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004128 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004129 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004130 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004131 params.bssid_hint = bss->bssid;
4132 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004133 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004135 if (ssid->bssid_hint_set)
4136 params.bssid_hint = ssid->bssid_hint;
4137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 params.ssid = ssid->ssid;
4139 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004140 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004142
4143 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4144 wpa_s->conf->ap_scan == 2) {
4145 params.bssid = ssid->bssid;
4146 params.fixed_bssid = 1;
4147 }
4148
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004149 /* Initial frequency for IBSS/mesh */
4150 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004151 ssid->frequency > 0 && params.freq.freq == 0)
4152 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004153
4154 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004155 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004156 if (ssid->beacon_int)
4157 params.beacon_int = ssid->beacon_int;
4158 else
4159 params.beacon_int = wpa_s->conf->beacon_int;
4160 }
4161
Hai Shalomc3565922019-10-28 11:58:20 -07004162 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004163 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4164 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004165 else
4166 edmg_ie_oper = NULL;
4167
4168 if (edmg_ie_oper) {
4169 params.freq.edmg.channels =
4170 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4171 params.freq.edmg.bw_config =
4172 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4173 wpa_printf(MSG_DEBUG,
4174 "AP supports EDMG channels 0x%x, bw_config %d",
4175 params.freq.edmg.channels,
4176 params.freq.edmg.bw_config);
4177
4178 /* User may ask for specific EDMG channel for EDMG connection
4179 * (must be supported by AP)
4180 */
4181 if (ssid->edmg_channel) {
4182 struct ieee80211_edmg_config configured_edmg;
4183 enum hostapd_hw_mode hw_mode;
4184 u8 primary_channel;
4185
4186 hw_mode = ieee80211_freq_to_chan(bss->freq,
4187 &primary_channel);
4188 if (hw_mode == NUM_HOSTAPD_MODES)
4189 goto edmg_fail;
4190
4191 hostapd_encode_edmg_chan(ssid->enable_edmg,
4192 ssid->edmg_channel,
4193 primary_channel,
4194 &configured_edmg);
4195
4196 if (ieee802_edmg_is_allowed(params.freq.edmg,
4197 configured_edmg)) {
4198 params.freq.edmg = configured_edmg;
4199 wpa_printf(MSG_DEBUG,
4200 "Use EDMG channel %d for connection",
4201 ssid->edmg_channel);
4202 } else {
4203 edmg_fail:
4204 params.freq.edmg.channels = 0;
4205 params.freq.edmg.bw_config = 0;
4206 wpa_printf(MSG_WARNING,
4207 "EDMG channel %d not supported by AP, fallback to DMG",
4208 ssid->edmg_channel);
4209 }
4210 }
4211
4212 if (params.freq.edmg.channels) {
4213 wpa_printf(MSG_DEBUG,
4214 "EDMG before: channels 0x%x, bw_config %d",
4215 params.freq.edmg.channels,
4216 params.freq.edmg.bw_config);
4217 params.freq.edmg = get_supported_edmg(wpa_s,
4218 &params.freq,
4219 params.freq.edmg);
4220 wpa_printf(MSG_DEBUG,
4221 "EDMG after: channels 0x%x, bw_config %d",
4222 params.freq.edmg.channels,
4223 params.freq.edmg.bw_config);
4224 }
4225 }
4226
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004227 params.pairwise_suite = cipher_pairwise;
4228 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004229 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004230 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004231 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004232 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004233 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004235 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004236#ifdef CONFIG_WEP
4237 {
4238 int i;
4239
4240 for (i = 0; i < NUM_WEP_KEYS; i++) {
4241 if (ssid->wep_key_len[i])
4242 params.wep_key[i] = ssid->wep_key[i];
4243 params.wep_key_len[i] = ssid->wep_key_len[i];
4244 }
4245 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004246 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004247#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248
Hai Shalom74f70d42019-02-11 14:42:39 -08004249 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004250#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004251 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4252 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304253#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004254 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4255 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4256 (params.allowed_key_mgmts &
4257 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004258#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004259 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004260 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4261 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004262 }
4263
Hai Shalom74f70d42019-02-11 14:42:39 -08004264 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4265 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4266 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4267 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4268 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004269 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004270
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004271 if (wpa_s->conf->key_mgmt_offload) {
4272 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4273 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004274 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4275 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004276 params.req_key_mgmt_offload =
4277 ssid->proactive_key_caching < 0 ?
4278 wpa_s->conf->okc : ssid->proactive_key_caching;
4279 else
4280 params.req_key_mgmt_offload = 1;
4281
Winnie Chen4138eec2022-11-10 16:32:53 +08004282#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004283 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004284 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4285 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004286#else
4287 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4288 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004289#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004290 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4291 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004292 }
4293
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004294 params.drop_unencrypted = use_crypt;
4295
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004296 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004297 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004298 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4299 struct wpa_ie_data ie;
4300 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4301 ie.capabilities &
4302 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4303 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4304 "MFP: require MFP");
4305 params.mgmt_frame_protection =
4306 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004307#ifdef CONFIG_OWE
4308 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4309 !ssid->owe_only) {
4310 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4311#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312 }
4313 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004315 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004316
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004317 if (wpa_s->p2pdev->set_sta_uapsd)
4318 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319 else
4320 params.uapsd = -1;
4321
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004322#ifdef CONFIG_HT_OVERRIDES
4323 os_memset(&htcaps, 0, sizeof(htcaps));
4324 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4325 params.htcaps = (u8 *) &htcaps;
4326 params.htcaps_mask = (u8 *) &htcaps_mask;
4327 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4328#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004329#ifdef CONFIG_VHT_OVERRIDES
4330 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4331 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4332 params.vhtcaps = &vhtcaps;
4333 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004334 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004335#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004336#ifdef CONFIG_HE_OVERRIDES
4337 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4338#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004339 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004340
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004341#ifdef CONFIG_P2P
4342 /*
4343 * If multi-channel concurrency is not supported, check for any
4344 * frequency conflict. In case of any frequency conflict, remove the
4345 * least prioritized connection.
4346 */
4347 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004348 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004349 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004350 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004351 wpa_printf(MSG_DEBUG,
4352 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004353 freq, params.freq.freq);
4354 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004355 wpa_s, params.freq.freq, ssid) < 0) {
4356 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004357 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004358 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004359 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004360 }
4361 }
4362#endif /* CONFIG_P2P */
4363
Dmitry Shmidte4663042016-04-04 10:07:49 -07004364 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004365 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004366 params.prev_bssid = prev_bssid;
4367
Hai Shalom60840252021-02-19 19:02:11 -08004368#ifdef CONFIG_SAE
4369 params.sae_pwe = wpa_s->conf->sae_pwe;
4370#endif /* CONFIG_SAE */
4371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004372 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004373 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004374 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375 if (ret < 0) {
4376 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4377 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004378 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004379 /*
4380 * The driver is known to mean what is saying, so we
4381 * can stop right here; the association will not
4382 * succeed.
4383 */
4384 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004385 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004386 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004387 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4389 return;
4390 }
4391 /* try to continue anyway; new association will be tried again
4392 * after timeout */
4393 assoc_failed = 1;
4394 }
4395
4396 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4397 /* Set the key after the association just in case association
4398 * cleared the previously configured key. */
4399 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4400 /* No need to timeout authentication since there is no key
4401 * management. */
4402 wpa_supplicant_cancel_auth_timeout(wpa_s);
4403 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4404#ifdef CONFIG_IBSS_RSN
4405 } else if (ssid->mode == WPAS_MODE_IBSS &&
4406 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4407 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4408 /*
4409 * RSN IBSS authentication is per-STA and we can disable the
4410 * per-BSSID authentication.
4411 */
4412 wpa_supplicant_cancel_auth_timeout(wpa_s);
4413#endif /* CONFIG_IBSS_RSN */
4414 } else {
4415 /* Timeout for IEEE 802.11 authentication and association */
4416 int timeout = 60;
4417
4418 if (assoc_failed) {
4419 /* give IBSS a bit more time */
4420 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4421 } else if (wpa_s->conf->ap_scan == 1) {
4422 /* give IBSS a bit more time */
4423 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4424 }
4425 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4426 }
4427
Hai Shalomfdcde762020-04-02 11:19:20 -07004428#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004429 if (wep_keys_set &&
4430 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004431 /* Set static WEP keys again */
4432 wpa_set_wep_keys(wpa_s, ssid);
4433 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004434#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004435
Sunil8cd6f4d2022-06-28 18:40:46 +00004436 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004437 /*
4438 * Do not allow EAP session resumption between different
4439 * network configurations.
4440 */
4441 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4442 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004443
4444 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004445 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004446#ifdef CONFIG_HS20
4447 hs20_configure_frame_filters(wpa_s);
4448#endif /* CONFIG_HS20 */
4449 }
4450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004451 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4452 wpa_supplicant_initiate_eapol(wpa_s);
4453 if (old_ssid != wpa_s->current_ssid)
4454 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004455 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4456 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457}
4458
4459
4460static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4461 const u8 *addr)
4462{
4463 struct wpa_ssid *old_ssid;
4464
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004465 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004466 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004468 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469 wpa_sm_set_config(wpa_s->wpa, NULL);
4470 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4471 if (old_ssid != wpa_s->current_ssid)
4472 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004473
4474 wpas_scs_deinit(wpa_s);
4475 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004476 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4477}
4478
4479
4480/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004481 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4482 * @wpa_s: Pointer to wpa_supplicant data
4483 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4484 *
4485 * This function is used to request %wpa_supplicant to deauthenticate from the
4486 * current AP.
4487 */
4488void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004489 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004490{
4491 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004492 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004493 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004494
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004495 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004496 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004497 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004498 reason_code, reason2str(reason_code),
4499 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004500
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004501 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4502 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4503 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004504 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004505 else if (!is_zero_ether_addr(wpa_s->bssid))
4506 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004507 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4508 /*
4509 * When using driver-based BSS selection, we may not know the
4510 * BSSID with which we are currently trying to associate. We
4511 * need to notify the driver of this disconnection even in such
4512 * a case, so use the all zeros address here.
4513 */
4514 addr = wpa_s->bssid;
4515 zero_addr = 1;
4516 }
4517
Hai Shalom74f70d42019-02-11 14:42:39 -08004518 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4519 wpa_s->enabled_4addr_mode = 0;
4520
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004521#ifdef CONFIG_TDLS
4522 wpa_tdls_teardown_peers(wpa_s->wpa);
4523#endif /* CONFIG_TDLS */
4524
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004525#ifdef CONFIG_MESH
4526 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004527 struct mesh_conf *mconf;
4528
4529 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004530 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4531 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004532 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4533 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004534 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004535 }
4536#endif /* CONFIG_MESH */
4537
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004538 if (addr) {
4539 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004540 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004541 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004542 event.deauth_info.locally_generated = 1;
4543 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004544 if (zero_addr)
4545 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546 }
4547
4548 wpa_supplicant_clear_connection(wpa_s, addr);
4549}
4550
Hai Shalomfdcde762020-04-02 11:19:20 -07004551
4552void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4553{
4554 wpa_s->own_reconnect_req = 1;
4555 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4556
4557}
4558
4559
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004560static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4561 struct wpa_ssid *ssid)
4562{
4563 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4564 return;
4565
4566 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004567 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004568 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4569 wpas_notify_network_enabled_changed(wpa_s, ssid);
4570
4571 /*
4572 * Try to reassociate since there is no current configuration and a new
4573 * network was made available.
4574 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004575 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004576 wpa_s->reassociate = 1;
4577}
4578
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004579
Roshan Pius950bec92016-07-19 09:49:24 -07004580/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004581 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004582 * @wpa_s: wpa_supplicant structure for a network interface
4583 * Returns: The new network configuration or %NULL if operation failed
4584 *
4585 * This function performs the following operations:
4586 * 1. Adds a new network.
4587 * 2. Send network addition notification.
4588 * 3. Marks the network disabled.
4589 * 4. Set network default parameters.
4590 */
4591struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4592{
4593 struct wpa_ssid *ssid;
4594
4595 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004596 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004597 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004598 wpas_notify_network_added(wpa_s, ssid);
4599 ssid->disabled = 1;
4600 wpa_config_set_network_defaults(ssid);
4601
4602 return ssid;
4603}
4604
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004605
Roshan Pius950bec92016-07-19 09:49:24 -07004606/**
4607 * wpa_supplicant_remove_network - Remove a configured network based on id
4608 * @wpa_s: wpa_supplicant structure for a network interface
4609 * @id: Unique network id to search for
4610 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4611 * could not be removed
4612 *
4613 * This function performs the following operations:
4614 * 1. Removes the network.
4615 * 2. Send network removal notification.
4616 * 3. Update internal state machines.
4617 * 4. Stop any running sched scans.
4618 */
4619int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4620{
Sunil Ravia04bd252022-05-02 22:54:18 -07004621 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004622 int was_disabled;
4623
4624 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004625 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004626 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004627 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004628
Sunil Ravia04bd252022-05-02 22:54:18 -07004629 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004630#ifdef CONFIG_SME
4631 wpa_s->sme.prev_bssid_set = 0;
4632#endif /* CONFIG_SME */
4633 /*
4634 * Invalidate the EAP session cache if the current or
4635 * previously used network is removed.
4636 */
4637 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4638 }
4639
Sunil Ravia04bd252022-05-02 22:54:18 -07004640 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004641 wpa_sm_set_config(wpa_s->wpa, NULL);
4642 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4643
4644 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4645 wpa_s->own_disconnect_req = 1;
4646 wpa_supplicant_deauthenticate(wpa_s,
4647 WLAN_REASON_DEAUTH_LEAVING);
4648 }
4649
4650 was_disabled = ssid->disabled;
4651
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004652 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004653 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004654
4655 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004656 wpa_printf(MSG_DEBUG,
4657 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004658 wpa_supplicant_cancel_sched_scan(wpa_s);
4659 wpa_supplicant_req_scan(wpa_s, 0, 0);
4660 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004661
Roshan Pius950bec92016-07-19 09:49:24 -07004662 return 0;
4663}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004664
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004666/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004667 * wpa_supplicant_remove_all_networks - Remove all configured networks
4668 * @wpa_s: wpa_supplicant structure for a network interface
4669 * Returns: 0 on success (errors are currently ignored)
4670 *
4671 * This function performs the following operations:
4672 * 1. Remove all networks.
4673 * 2. Send network removal notifications.
4674 * 3. Update internal state machines.
4675 * 4. Stop any running sched scans.
4676 */
4677int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4678{
4679 struct wpa_ssid *ssid;
4680
4681 if (wpa_s->sched_scanning)
4682 wpa_supplicant_cancel_sched_scan(wpa_s);
4683
4684 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4685 if (wpa_s->current_ssid) {
4686#ifdef CONFIG_SME
4687 wpa_s->sme.prev_bssid_set = 0;
4688#endif /* CONFIG_SME */
4689 wpa_sm_set_config(wpa_s->wpa, NULL);
4690 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4691 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4692 wpa_s->own_disconnect_req = 1;
4693 wpa_supplicant_deauthenticate(
4694 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4695 }
4696 ssid = wpa_s->conf->ssid;
4697 while (ssid) {
4698 struct wpa_ssid *remove_ssid = ssid;
4699 int id;
4700
4701 id = ssid->id;
4702 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004703 wpas_notify_network_removed(wpa_s, remove_ssid);
4704 wpa_config_remove_network(wpa_s->conf, id);
4705 }
4706 return 0;
4707}
4708
4709
4710/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711 * wpa_supplicant_enable_network - Mark a configured network as enabled
4712 * @wpa_s: wpa_supplicant structure for a network interface
4713 * @ssid: wpa_ssid structure for a configured network or %NULL
4714 *
4715 * Enables the specified network or all networks if no network specified.
4716 */
4717void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4718 struct wpa_ssid *ssid)
4719{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004721 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4722 wpa_supplicant_enable_one_network(wpa_s, ssid);
4723 } else
4724 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004725
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004726 if (wpa_s->reassociate && !wpa_s->disconnected &&
4727 (!wpa_s->current_ssid ||
4728 wpa_s->wpa_state == WPA_DISCONNECTED ||
4729 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004730 if (wpa_s->sched_scanning) {
4731 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4732 "new network to scan filters");
4733 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734 }
4735
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004736 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4737 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004738 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004739 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004740 }
4741}
4742
4743
4744/**
4745 * wpa_supplicant_disable_network - Mark a configured network as disabled
4746 * @wpa_s: wpa_supplicant structure for a network interface
4747 * @ssid: wpa_ssid structure for a configured network or %NULL
4748 *
4749 * Disables the specified network or all networks if no network specified.
4750 */
4751void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4752 struct wpa_ssid *ssid)
4753{
4754 struct wpa_ssid *other_ssid;
4755 int was_disabled;
4756
4757 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004758 if (wpa_s->sched_scanning)
4759 wpa_supplicant_cancel_sched_scan(wpa_s);
4760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4762 other_ssid = other_ssid->next) {
4763 was_disabled = other_ssid->disabled;
4764 if (was_disabled == 2)
4765 continue; /* do not change persistent P2P group
4766 * data */
4767
4768 other_ssid->disabled = 1;
4769
4770 if (was_disabled != other_ssid->disabled)
4771 wpas_notify_network_enabled_changed(
4772 wpa_s, other_ssid);
4773 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004774 if (wpa_s->current_ssid) {
4775 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4776 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004777 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004779 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004781 if (ssid == wpa_s->current_ssid) {
4782 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4783 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004784 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004785 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004786 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004787
4788 was_disabled = ssid->disabled;
4789
4790 ssid->disabled = 1;
4791
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004792 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004793 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004794 if (wpa_s->sched_scanning) {
4795 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4796 "to remove network from filters");
4797 wpa_supplicant_cancel_sched_scan(wpa_s);
4798 wpa_supplicant_req_scan(wpa_s, 0, 0);
4799 }
4800 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 }
4802}
4803
4804
4805/**
4806 * wpa_supplicant_select_network - Attempt association with a network
4807 * @wpa_s: wpa_supplicant structure for a network interface
4808 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4809 */
4810void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4811 struct wpa_ssid *ssid)
4812{
4813
4814 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004815 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004817 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004818 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4819 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004820 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004822 disconnected = 1;
4823 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004825 if (ssid)
4826 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004828 /*
4829 * Mark all other networks disabled or mark all networks enabled if no
4830 * network specified.
4831 */
4832 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4833 other_ssid = other_ssid->next) {
4834 int was_disabled = other_ssid->disabled;
4835 if (was_disabled == 2)
4836 continue; /* do not change persistent P2P group data */
4837
4838 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004839 if (was_disabled && !other_ssid->disabled)
4840 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841
4842 if (was_disabled != other_ssid->disabled)
4843 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4844 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004845
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004846 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4847 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004848 /* We are already associated with the selected network */
4849 wpa_printf(MSG_DEBUG, "Already associated with the "
4850 "selected network - do nothing");
4851 return;
4852 }
4853
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004854 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004855 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004856 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004857 wpa_s->connect_without_scan =
Sunil Ravi640215c2023-06-28 23:08:09 +00004858 (ssid->mode == WPAS_MODE_MESH ||
4859 ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004860
4861 /*
4862 * Don't optimize next scan freqs since a new ESS has been
4863 * selected.
4864 */
4865 os_free(wpa_s->next_scan_freqs);
4866 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004867 } else {
4868 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004869 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871 wpa_s->disconnected = 0;
4872 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004873 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004874 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004875 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004876 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004877 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004878 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004879
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004880 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004881 wpa_supplicant_fast_associate(wpa_s) != 1) {
4882 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004883 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004884 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004885 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004886
4887 if (ssid)
4888 wpas_notify_network_selected(wpa_s, ssid);
4889}
4890
4891
4892/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004893 * wpas_remove_cred - Remove the specified credential and all the network
4894 * entries created based on the removed credential
4895 * @wpa_s: wpa_supplicant structure for a network interface
4896 * @cred: The credential to remove
4897 * Returns: 0 on success, -1 on failure
4898 */
4899int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4900{
4901 struct wpa_ssid *ssid, *next;
4902 int id;
4903
4904 if (!cred) {
4905 wpa_printf(MSG_DEBUG, "Could not find cred");
4906 return -1;
4907 }
4908
4909 id = cred->id;
4910 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4911 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4912 return -1;
4913 }
4914
4915 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4916
4917 /* Remove any network entry created based on the removed credential */
4918 ssid = wpa_s->conf->ssid;
4919 while (ssid) {
4920 next = ssid->next;
4921
4922 if (ssid->parent_cred == cred) {
4923 wpa_printf(MSG_DEBUG,
4924 "Remove network id %d since it used the removed credential",
4925 ssid->id);
4926 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4927 -1) {
4928 wpa_printf(MSG_DEBUG,
4929 "Could not find network id=%d",
4930 ssid->id);
4931 }
4932 }
4933
4934 ssid = next;
4935 }
4936
4937 return 0;
4938}
4939
4940
4941/**
4942 * wpas_remove_cred - Remove all the Interworking credentials
4943 * @wpa_s: wpa_supplicant structure for a network interface
4944 * Returns: 0 on success, -1 on failure
4945 */
4946int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4947{
4948 int res, ret = 0;
4949 struct wpa_cred *cred, *prev;
4950
4951 cred = wpa_s->conf->cred;
4952 while (cred) {
4953 prev = cred;
4954 cred = cred->next;
4955 res = wpas_remove_cred(wpa_s, prev);
4956 if (res < 0) {
4957 wpa_printf(MSG_DEBUG,
4958 "Removal of all credentials failed - failed to remove credential id=%d",
4959 prev->id);
4960 ret = -1;
4961 }
4962 }
4963
4964 return ret;
4965}
4966
4967
4968/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004969 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4970 * @wpa_s: wpa_supplicant structure for a network interface
4971 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4972 * @pkcs11_module_path: PKCS #11 module path or NULL
4973 * Returns: 0 on success; -1 on failure
4974 *
4975 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4976 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4977 * module path fails the paths will be reset to the default value (NULL).
4978 */
4979int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4980 const char *pkcs11_engine_path,
4981 const char *pkcs11_module_path)
4982{
4983 char *pkcs11_engine_path_copy = NULL;
4984 char *pkcs11_module_path_copy = NULL;
4985
4986 if (pkcs11_engine_path != NULL) {
4987 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4988 if (pkcs11_engine_path_copy == NULL)
4989 return -1;
4990 }
4991 if (pkcs11_module_path != NULL) {
4992 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004993 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004994 os_free(pkcs11_engine_path_copy);
4995 return -1;
4996 }
4997 }
4998
4999 os_free(wpa_s->conf->pkcs11_engine_path);
5000 os_free(wpa_s->conf->pkcs11_module_path);
5001 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
5002 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
5003
5004 wpa_sm_set_eapol(wpa_s->wpa, NULL);
5005 eapol_sm_deinit(wpa_s->eapol);
5006 wpa_s->eapol = NULL;
5007 if (wpa_supplicant_init_eapol(wpa_s)) {
5008 /* Error -> Reset paths to the default value (NULL) once. */
5009 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
5010 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
5011 NULL);
5012
5013 return -1;
5014 }
5015 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5016
5017 return 0;
5018}
5019
5020
5021/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005022 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
5023 * @wpa_s: wpa_supplicant structure for a network interface
5024 * @ap_scan: AP scan mode
5025 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
5026 *
5027 */
5028int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5029{
5030
5031 int old_ap_scan;
5032
5033 if (ap_scan < 0 || ap_scan > 2)
5034 return -1;
5035
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005036 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5037 wpa_printf(MSG_INFO,
5038 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5039 }
5040
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005041#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005042 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5043 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5044 wpa_s->wpa_state < WPA_COMPLETED) {
5045 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5046 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005047 return 0;
5048 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005049#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005051 old_ap_scan = wpa_s->conf->ap_scan;
5052 wpa_s->conf->ap_scan = ap_scan;
5053
5054 if (old_ap_scan != wpa_s->conf->ap_scan)
5055 wpas_notify_ap_scan_changed(wpa_s);
5056
5057 return 0;
5058}
5059
5060
5061/**
5062 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5063 * @wpa_s: wpa_supplicant structure for a network interface
5064 * @expire_age: Expiration age in seconds
5065 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5066 *
5067 */
5068int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5069 unsigned int bss_expire_age)
5070{
5071 if (bss_expire_age < 10) {
5072 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5073 bss_expire_age);
5074 return -1;
5075 }
5076 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5077 bss_expire_age);
5078 wpa_s->conf->bss_expiration_age = bss_expire_age;
5079
5080 return 0;
5081}
5082
5083
5084/**
5085 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5086 * @wpa_s: wpa_supplicant structure for a network interface
5087 * @expire_count: number of scans after which an unseen BSS is reclaimed
5088 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5089 *
5090 */
5091int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5092 unsigned int bss_expire_count)
5093{
5094 if (bss_expire_count < 1) {
5095 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5096 bss_expire_count);
5097 return -1;
5098 }
5099 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5100 bss_expire_count);
5101 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5102
5103 return 0;
5104}
5105
5106
5107/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005108 * wpa_supplicant_set_scan_interval - Set scan interval
5109 * @wpa_s: wpa_supplicant structure for a network interface
5110 * @scan_interval: scan interval in seconds
5111 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5112 *
5113 */
5114int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5115 int scan_interval)
5116{
5117 if (scan_interval < 0) {
5118 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5119 scan_interval);
5120 return -1;
5121 }
5122 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5123 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005124 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005125
5126 return 0;
5127}
5128
5129
5130/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005131 * wpa_supplicant_set_debug_params - Set global debug params
5132 * @global: wpa_global structure
5133 * @debug_level: debug level
5134 * @debug_timestamp: determines if show timestamp in debug data
5135 * @debug_show_keys: determines if show keys in debug data
5136 * Returns: 0 if succeed or -1 if debug_level has wrong value
5137 */
5138int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5139 int debug_timestamp, int debug_show_keys)
5140{
5141
5142 int old_level, old_timestamp, old_show_keys;
5143
5144 /* check for allowed debuglevels */
5145 if (debug_level != MSG_EXCESSIVE &&
5146 debug_level != MSG_MSGDUMP &&
5147 debug_level != MSG_DEBUG &&
5148 debug_level != MSG_INFO &&
5149 debug_level != MSG_WARNING &&
5150 debug_level != MSG_ERROR)
5151 return -1;
5152
5153 old_level = wpa_debug_level;
5154 old_timestamp = wpa_debug_timestamp;
5155 old_show_keys = wpa_debug_show_keys;
5156
5157 wpa_debug_level = debug_level;
5158 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5159 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5160
5161 if (wpa_debug_level != old_level)
5162 wpas_notify_debug_level_changed(global);
5163 if (wpa_debug_timestamp != old_timestamp)
5164 wpas_notify_debug_timestamp_changed(global);
5165 if (wpa_debug_show_keys != old_show_keys)
5166 wpas_notify_debug_show_keys_changed(global);
5167
5168 return 0;
5169}
5170
5171
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005172#ifdef CONFIG_OWE
5173static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5174 const u8 *entry_ssid, size_t entry_ssid_len)
5175{
5176 const u8 *owe, *pos, *end;
5177 u8 ssid_len;
5178 struct wpa_bss *bss;
5179
5180 /* Check network profile SSID aganst the SSID in the
5181 * OWE Transition Mode element. */
5182
5183 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5184 if (!bss)
5185 return 0;
5186
5187 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5188 if (!owe)
5189 return 0;
5190
5191 pos = owe + 6;
5192 end = owe + 2 + owe[1];
5193
5194 if (end - pos < ETH_ALEN + 1)
5195 return 0;
5196 pos += ETH_ALEN;
5197 ssid_len = *pos++;
5198 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5199 return 0;
5200
5201 return entry_ssid_len == ssid_len &&
5202 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5203}
5204#endif /* CONFIG_OWE */
5205
5206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005207/**
5208 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5209 * @wpa_s: Pointer to wpa_supplicant data
5210 * Returns: A pointer to the current network structure or %NULL on failure
5211 */
5212struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5213{
5214 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005215 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005216 int res;
5217 size_t ssid_len;
5218 u8 bssid[ETH_ALEN];
5219 int wired;
5220
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005221 res = wpa_drv_get_ssid(wpa_s, ssid);
5222 if (res < 0) {
5223 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5224 "driver");
5225 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005226 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005227 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005228
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005229 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005230 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5231 "driver");
5232 return NULL;
5233 }
5234
5235 wired = wpa_s->conf->ap_scan == 0 &&
5236 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5237
5238 entry = wpa_s->conf->ssid;
5239 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005240 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005242 (!entry->ssid ||
5243 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5244 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005245 (!entry->bssid_set ||
5246 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5247 return entry;
5248#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005249 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005250 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5251 (entry->ssid == NULL || entry->ssid_len == 0) &&
5252 (!entry->bssid_set ||
5253 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5254 return entry;
5255#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005256
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005257#ifdef CONFIG_OWE
5258 if (!wpas_network_disabled(wpa_s, entry) &&
5259 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5260 entry->ssid_len) &&
5261 (!entry->bssid_set ||
5262 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5263 return entry;
5264#endif /* CONFIG_OWE */
5265
Dmitry Shmidt04949592012-07-19 12:16:46 -07005266 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005267 entry->ssid_len == 0 &&
5268 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5269 return entry;
5270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005271 entry = entry->next;
5272 }
5273
5274 return NULL;
5275}
5276
5277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005278static int select_driver(struct wpa_supplicant *wpa_s, int i)
5279{
5280 struct wpa_global *global = wpa_s->global;
5281
5282 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005283 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005284 if (global->drv_priv[i] == NULL) {
5285 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5286 "'%s'", wpa_drivers[i]->name);
5287 return -1;
5288 }
5289 }
5290
5291 wpa_s->driver = wpa_drivers[i];
5292 wpa_s->global_drv_priv = global->drv_priv[i];
5293
5294 return 0;
5295}
5296
5297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005298static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5299 const char *name)
5300{
5301 int i;
5302 size_t len;
5303 const char *pos, *driver = name;
5304
5305 if (wpa_s == NULL)
5306 return -1;
5307
5308 if (wpa_drivers[0] == NULL) {
5309 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5310 "wpa_supplicant");
5311 return -1;
5312 }
5313
5314 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005315 /* Default to first successful driver in the list */
5316 for (i = 0; wpa_drivers[i]; i++) {
5317 if (select_driver(wpa_s, i) == 0)
5318 return 0;
5319 }
5320 /* Drivers have each reported failure, so no wpa_msg() here. */
5321 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005322 }
5323
5324 do {
5325 pos = os_strchr(driver, ',');
5326 if (pos)
5327 len = pos - driver;
5328 else
5329 len = os_strlen(driver);
5330
5331 for (i = 0; wpa_drivers[i]; i++) {
5332 if (os_strlen(wpa_drivers[i]->name) == len &&
5333 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005334 0) {
5335 /* First driver that succeeds wins */
5336 if (select_driver(wpa_s, i) == 0)
5337 return 0;
5338 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005339 }
5340
5341 driver = pos + 1;
5342 } while (pos);
5343
5344 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5345 return -1;
5346}
5347
5348
5349/**
5350 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5351 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5352 * with struct wpa_driver_ops::init()
5353 * @src_addr: Source address of the EAPOL frame
5354 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5355 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005356 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005357 *
5358 * This function is called for each received EAPOL frame. Most driver
5359 * interfaces rely on more generic OS mechanism for receiving frames through
5360 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5361 * take care of received EAPOL frames and deliver them to the core supplicant
5362 * code by calling this function.
5363 */
5364void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005365 const u8 *buf, size_t len,
5366 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005367{
5368 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005369 const u8 *connected_addr = wpa_s->valid_links ?
5370 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005371
Sunil8cd6f4d2022-06-28 18:40:46 +00005372 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5373 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005374 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5375
Hai Shalomc1a21442022-02-04 13:43:00 -08005376 if (wpa_s->own_disconnect_req) {
5377 wpa_printf(MSG_DEBUG,
5378 "Drop received EAPOL frame as we are disconnecting");
5379 return;
5380 }
5381
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005382#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005383 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5384 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005385 if (wpa_s->ignore_auth_resp) {
5386 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5387 return;
5388 }
5389#endif /* CONFIG_TESTING_OPTIONS */
5390
Jouni Malinena05074c2012-12-21 21:35:35 +02005391 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5392 (wpa_s->last_eapol_matches_bssid &&
5393#ifdef CONFIG_AP
5394 !wpa_s->ap_iface &&
5395#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005396 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005397 /*
5398 * There is possible race condition between receiving the
5399 * association event and the EAPOL frame since they are coming
5400 * through different paths from the driver. In order to avoid
5401 * issues in trying to process the EAPOL frame before receiving
5402 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005403 * the association event is received. This may also be needed in
5404 * driver-based roaming case, so also use src_addr != BSSID as a
5405 * trigger if we have previously confirmed that the
5406 * Authenticator uses BSSID as the src_addr (which is not the
5407 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005408 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005409 wpa_dbg(wpa_s, MSG_DEBUG,
5410 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5411 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005412 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005413 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005414 wpabuf_free(wpa_s->pending_eapol_rx);
5415 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5416 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005417 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005418 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5419 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005420 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005421 }
5422 return;
5423 }
5424
Jouni Malinena05074c2012-12-21 21:35:35 +02005425 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005426 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005428#ifdef CONFIG_AP
5429 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005430 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5431 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005432 return;
5433 }
5434#endif /* CONFIG_AP */
5435
5436 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5437 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5438 "no key management is configured");
5439 return;
5440 }
5441
5442 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005443 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005444 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5445 wpa_s->wpa_state != WPA_COMPLETED) &&
5446 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005447 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005448 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005449 int timeout = 10;
5450
5451 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5452 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5453 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5454 /* Use longer timeout for IEEE 802.1X/EAP */
5455 timeout = 70;
5456 }
5457
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005458#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005459 if (wpa_s->current_ssid && wpa_s->current_bss &&
5460 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5461 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5462 /*
5463 * Use shorter timeout if going through WPS AP iteration
5464 * for PIN config method with an AP that does not
5465 * advertise Selected Registrar.
5466 */
5467 struct wpabuf *wps_ie;
5468
5469 wps_ie = wpa_bss_get_vendor_ie_multi(
5470 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5471 if (wps_ie &&
5472 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5473 timeout = 10;
5474 wpabuf_free(wps_ie);
5475 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005476#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005477
5478 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005479 }
5480 wpa_s->eapol_received++;
5481
5482 if (wpa_s->countermeasures) {
5483 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5484 "EAPOL packet");
5485 return;
5486 }
5487
5488#ifdef CONFIG_IBSS_RSN
5489 if (wpa_s->current_ssid &&
5490 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005491 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5492 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005493 return;
5494 }
5495#endif /* CONFIG_IBSS_RSN */
5496
5497 /* Source address of the incoming EAPOL frame could be compared to the
5498 * current BSSID. However, it is possible that a centralized
5499 * Authenticator could be using another MAC address than the BSSID of
5500 * an AP, so just allow any address to be used for now. The replies are
5501 * still sent to the current BSSID (if available), though. */
5502
5503 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5504 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005505 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5506 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005507 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5508 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005509 return;
5510 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005511 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005512 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5514 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005515 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005516 * handshake processing which would normally set portValid. We
5517 * need this to allow the EAPOL state machines to be completed
5518 * without going through EAPOL-Key handshake.
5519 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005520 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005521 }
5522}
5523
5524
Sunil8cd6f4d2022-06-28 18:40:46 +00005525static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5526 const u8 *buf, size_t len)
5527{
5528 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5529 FRAME_ENCRYPTION_UNKNOWN);
5530}
5531
5532
Hai Shalomb755a2a2020-04-23 21:49:02 -07005533static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5534{
5535 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5536 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5537}
5538
5539
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005540int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005542 u8 prev_mac_addr[ETH_ALEN];
5543
5544 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5545
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005546 if ((!wpa_s->p2p_mgmt ||
5547 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5548 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005549 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005550 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5551 wpa_drv_get_mac_addr(wpa_s),
5552 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005553 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005554 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005555 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005556 if (wpa_s->l2 == NULL)
5557 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005558
5559 if (l2_packet_set_packet_filter(wpa_s->l2,
5560 L2_PACKET_FILTER_PKTTYPE))
5561 wpa_dbg(wpa_s, MSG_DEBUG,
5562 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005563
5564 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5565 wpa_msg(wpa_s, MSG_ERROR,
5566 "Failed to get own L2 address");
5567 return -1;
5568 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569 } else {
5570 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5571 if (addr)
5572 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5573 }
5574
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005575 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005576 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005577
Hai Shalomc3565922019-10-28 11:58:20 -07005578#ifdef CONFIG_FST
5579 if (wpa_s->fst)
5580 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5581#endif /* CONFIG_FST */
5582
Sunil Ravi77d572f2023-01-17 23:58:31 +00005583 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5584 wpas_notify_mac_address_changed(wpa_s);
5585
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005586 return 0;
5587}
5588
5589
Dmitry Shmidt04949592012-07-19 12:16:46 -07005590static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5591 const u8 *buf, size_t len)
5592{
5593 struct wpa_supplicant *wpa_s = ctx;
5594 const struct l2_ethhdr *eth;
5595
5596 if (len < sizeof(*eth))
5597 return;
5598 eth = (const struct l2_ethhdr *) buf;
5599
5600 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5601 !(eth->h_dest[0] & 0x01)) {
5602 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5603 " (bridge - not for this interface - ignore)",
5604 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5605 return;
5606 }
5607
5608 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5609 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5610 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005611 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005612}
5613
5614
Hai Shalom899fcc72020-10-19 14:38:18 -07005615int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5616 const char *bridge_ifname)
5617{
5618 if (wpa_s->wpa_state > WPA_SCANNING)
5619 return -EBUSY;
5620
5621 if (bridge_ifname &&
5622 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5623 return -EINVAL;
5624
5625 if (!bridge_ifname)
5626 bridge_ifname = "";
5627
5628 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5629 return 0;
5630
5631 if (wpa_s->l2_br) {
5632 l2_packet_deinit(wpa_s->l2_br);
5633 wpa_s->l2_br = NULL;
5634 }
5635
5636 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5637 sizeof(wpa_s->bridge_ifname));
5638
5639 if (wpa_s->bridge_ifname[0]) {
5640 wpa_dbg(wpa_s, MSG_DEBUG,
5641 "Receiving packets from bridge interface '%s'",
5642 wpa_s->bridge_ifname);
5643 wpa_s->l2_br = l2_packet_init_bridge(
5644 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5645 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5646 if (!wpa_s->l2_br) {
5647 wpa_msg(wpa_s, MSG_ERROR,
5648 "Failed to open l2_packet connection for the bridge interface '%s'",
5649 wpa_s->bridge_ifname);
5650 goto fail;
5651 }
5652 }
5653
5654#ifdef CONFIG_TDLS
5655 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5656 goto fail;
5657#endif /* CONFIG_TDLS */
5658
5659 return 0;
5660fail:
5661 wpa_s->bridge_ifname[0] = 0;
5662 if (wpa_s->l2_br) {
5663 l2_packet_deinit(wpa_s->l2_br);
5664 wpa_s->l2_br = NULL;
5665 }
5666#ifdef CONFIG_TDLS
5667 if (!wpa_s->p2p_mgmt)
5668 wpa_tdls_init(wpa_s->wpa);
5669#endif /* CONFIG_TDLS */
5670 return -EIO;
5671}
5672
5673
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005674/**
5675 * wpa_supplicant_driver_init - Initialize driver interface parameters
5676 * @wpa_s: Pointer to wpa_supplicant data
5677 * Returns: 0 on success, -1 on failure
5678 *
5679 * This function is called to initialize driver interface parameters.
5680 * wpa_drv_init() must have been called before this function to initialize the
5681 * driver interface.
5682 */
5683int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5684{
5685 static int interface_count = 0;
5686
5687 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5688 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005689
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005690 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5691 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005692 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005693 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5694
Hai Shalomb755a2a2020-04-23 21:49:02 -07005695 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5697 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005698 wpa_s->l2_br = l2_packet_init_bridge(
5699 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5700 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005701 if (wpa_s->l2_br == NULL) {
5702 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5703 "connection for the bridge interface '%s'",
5704 wpa_s->bridge_ifname);
5705 return -1;
5706 }
5707 }
5708
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005709 if (wpa_s->conf->ap_scan == 2 &&
5710 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5711 wpa_printf(MSG_INFO,
5712 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5713 }
5714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005715 wpa_clear_keys(wpa_s, NULL);
5716
5717 /* Make sure that TKIP countermeasures are not left enabled (could
5718 * happen if wpa_supplicant is killed during countermeasures. */
5719 wpa_drv_set_countermeasures(wpa_s, 0);
5720
5721 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5722 wpa_drv_flush_pmkid(wpa_s);
5723
5724 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005725 wpa_s->prev_scan_wildcard = 0;
5726
Dmitry Shmidt04949592012-07-19 12:16:46 -07005727 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005728 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5729 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5730 interface_count = 0;
5731 }
Keith Mok4389c282022-11-23 21:36:48 +00005732#ifndef CONFIG_CTRL_IFACE_AIDL
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005733 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005734 wpa_supplicant_delayed_sched_scan(wpa_s,
5735 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005736 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005737 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005738 100000);
Keith Mok4389c282022-11-23 21:36:48 +00005739#endif /* CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005740 interface_count++;
5741 } else
5742 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5743
5744 return 0;
5745}
5746
5747
5748static int wpa_supplicant_daemon(const char *pid_file)
5749{
5750 wpa_printf(MSG_DEBUG, "Daemonize..");
5751 return os_daemonize(pid_file);
5752}
5753
5754
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005755static struct wpa_supplicant *
5756wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005757{
5758 struct wpa_supplicant *wpa_s;
5759
5760 wpa_s = os_zalloc(sizeof(*wpa_s));
5761 if (wpa_s == NULL)
5762 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005763 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005764 wpa_s->scan_interval = 5;
5765 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005766 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005767 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005768 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005769 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005770
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005771 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005772 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005773#ifdef CONFIG_TESTING_OPTIONS
5774 dl_list_init(&wpa_s->drv_signal_override);
5775#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005776 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005778 return wpa_s;
5779}
5780
5781
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005782#ifdef CONFIG_HT_OVERRIDES
5783
5784static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5785 struct ieee80211_ht_capabilities *htcaps,
5786 struct ieee80211_ht_capabilities *htcaps_mask,
5787 const char *ht_mcs)
5788{
5789 /* parse ht_mcs into hex array */
5790 int i;
5791 const char *tmp = ht_mcs;
5792 char *end = NULL;
5793
5794 /* If ht_mcs is null, do not set anything */
5795 if (!ht_mcs)
5796 return 0;
5797
5798 /* This is what we are setting in the kernel */
5799 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5800
5801 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5802
5803 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005804 long v;
5805
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005806 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005807 v = strtol(tmp, &end, 16);
5808
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005809 if (errno == 0) {
5810 wpa_msg(wpa_s, MSG_DEBUG,
5811 "htcap value[%i]: %ld end: %p tmp: %p",
5812 i, v, end, tmp);
5813 if (end == tmp)
5814 break;
5815
5816 htcaps->supported_mcs_set[i] = v;
5817 tmp = end;
5818 } else {
5819 wpa_msg(wpa_s, MSG_ERROR,
5820 "Failed to parse ht-mcs: %s, error: %s\n",
5821 ht_mcs, strerror(errno));
5822 return -1;
5823 }
5824 }
5825
5826 /*
5827 * If we were able to parse any values, then set mask for the MCS set.
5828 */
5829 if (i) {
5830 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5831 IEEE80211_HT_MCS_MASK_LEN - 1);
5832 /* skip the 3 reserved bits */
5833 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5834 0x1f;
5835 }
5836
5837 return 0;
5838}
5839
5840
5841static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5842 struct ieee80211_ht_capabilities *htcaps,
5843 struct ieee80211_ht_capabilities *htcaps_mask,
5844 int disabled)
5845{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005846 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005847
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005848 if (disabled == -1)
5849 return 0;
5850
Hai Shalom74f70d42019-02-11 14:42:39 -08005851 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5852
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005853 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5854 htcaps_mask->ht_capabilities_info |= msk;
5855 if (disabled)
5856 htcaps->ht_capabilities_info &= msk;
5857 else
5858 htcaps->ht_capabilities_info |= msk;
5859
5860 return 0;
5861}
5862
5863
5864static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5865 struct ieee80211_ht_capabilities *htcaps,
5866 struct ieee80211_ht_capabilities *htcaps_mask,
5867 int factor)
5868{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005869 if (factor == -1)
5870 return 0;
5871
Hai Shalom74f70d42019-02-11 14:42:39 -08005872 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5873
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005874 if (factor < 0 || factor > 3) {
5875 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5876 "Must be 0-3 or -1", factor);
5877 return -EINVAL;
5878 }
5879
5880 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5881 htcaps->a_mpdu_params &= ~0x3;
5882 htcaps->a_mpdu_params |= factor & 0x3;
5883
5884 return 0;
5885}
5886
5887
5888static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5889 struct ieee80211_ht_capabilities *htcaps,
5890 struct ieee80211_ht_capabilities *htcaps_mask,
5891 int density)
5892{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005893 if (density == -1)
5894 return 0;
5895
Hai Shalom74f70d42019-02-11 14:42:39 -08005896 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5897
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005898 if (density < 0 || density > 7) {
5899 wpa_msg(wpa_s, MSG_ERROR,
5900 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5901 density);
5902 return -EINVAL;
5903 }
5904
5905 htcaps_mask->a_mpdu_params |= 0x1C;
5906 htcaps->a_mpdu_params &= ~(0x1C);
5907 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5908
5909 return 0;
5910}
5911
5912
5913static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5914 struct ieee80211_ht_capabilities *htcaps,
5915 struct ieee80211_ht_capabilities *htcaps_mask,
5916 int disabled)
5917{
Hai Shalom74f70d42019-02-11 14:42:39 -08005918 if (disabled)
5919 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005920
Paul Stewart092955c2017-02-06 09:13:09 -08005921 set_disable_ht40(htcaps, disabled);
5922 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005923
5924 return 0;
5925}
5926
5927
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005928static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5929 struct ieee80211_ht_capabilities *htcaps,
5930 struct ieee80211_ht_capabilities *htcaps_mask,
5931 int disabled)
5932{
5933 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005934 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5935 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005936
Hai Shalom74f70d42019-02-11 14:42:39 -08005937 if (disabled)
5938 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005939
5940 if (disabled)
5941 htcaps->ht_capabilities_info &= ~msk;
5942 else
5943 htcaps->ht_capabilities_info |= msk;
5944
5945 htcaps_mask->ht_capabilities_info |= msk;
5946
5947 return 0;
5948}
5949
5950
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005951static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5952 struct ieee80211_ht_capabilities *htcaps,
5953 struct ieee80211_ht_capabilities *htcaps_mask,
5954 int disabled)
5955{
5956 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005957 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005958
Hai Shalom74f70d42019-02-11 14:42:39 -08005959 if (disabled)
5960 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005961
5962 if (disabled)
5963 htcaps->ht_capabilities_info &= ~msk;
5964 else
5965 htcaps->ht_capabilities_info |= msk;
5966
5967 htcaps_mask->ht_capabilities_info |= msk;
5968
5969 return 0;
5970}
5971
5972
Hai Shalom74f70d42019-02-11 14:42:39 -08005973static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5974 struct ieee80211_ht_capabilities *htcaps,
5975 struct ieee80211_ht_capabilities *htcaps_mask,
5976 int tx_stbc)
5977{
5978 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5979
5980 if (tx_stbc == -1)
5981 return 0;
5982
5983 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5984
5985 if (tx_stbc < 0 || tx_stbc > 1) {
5986 wpa_msg(wpa_s, MSG_ERROR,
5987 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5988 return -EINVAL;
5989 }
5990
5991 htcaps_mask->ht_capabilities_info |= msk;
5992 htcaps->ht_capabilities_info &= ~msk;
5993 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5994
5995 return 0;
5996}
5997
5998
5999static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
6000 struct ieee80211_ht_capabilities *htcaps,
6001 struct ieee80211_ht_capabilities *htcaps_mask,
6002 int rx_stbc)
6003{
6004 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
6005
6006 if (rx_stbc == -1)
6007 return 0;
6008
6009 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
6010
6011 if (rx_stbc < 0 || rx_stbc > 3) {
6012 wpa_msg(wpa_s, MSG_ERROR,
6013 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
6014 return -EINVAL;
6015 }
6016
6017 htcaps_mask->ht_capabilities_info |= msk;
6018 htcaps->ht_capabilities_info &= ~msk;
6019 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
6020
6021 return 0;
6022}
6023
6024
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006025void wpa_supplicant_apply_ht_overrides(
6026 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6027 struct wpa_driver_associate_params *params)
6028{
6029 struct ieee80211_ht_capabilities *htcaps;
6030 struct ieee80211_ht_capabilities *htcaps_mask;
6031
6032 if (!ssid)
6033 return;
6034
6035 params->disable_ht = ssid->disable_ht;
6036 if (!params->htcaps || !params->htcaps_mask)
6037 return;
6038
6039 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6040 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6041 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6042 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6043 ssid->disable_max_amsdu);
6044 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6045 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6046 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006047 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006048 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006049 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6050 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006051
6052 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006053 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006054 htcaps->ht_capabilities_info |= bit;
6055 htcaps_mask->ht_capabilities_info |= bit;
6056 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006057}
6058
6059#endif /* CONFIG_HT_OVERRIDES */
6060
6061
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006062#ifdef CONFIG_VHT_OVERRIDES
6063void wpa_supplicant_apply_vht_overrides(
6064 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6065 struct wpa_driver_associate_params *params)
6066{
6067 struct ieee80211_vht_capabilities *vhtcaps;
6068 struct ieee80211_vht_capabilities *vhtcaps_mask;
6069
6070 if (!ssid)
6071 return;
6072
6073 params->disable_vht = ssid->disable_vht;
6074
6075 vhtcaps = (void *) params->vhtcaps;
6076 vhtcaps_mask = (void *) params->vhtcaps_mask;
6077
6078 if (!vhtcaps || !vhtcaps_mask)
6079 return;
6080
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006081 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6082 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006083
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006084#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006085 if (ssid->disable_sgi) {
6086 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6087 VHT_CAP_SHORT_GI_160);
6088 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6089 VHT_CAP_SHORT_GI_160);
6090 wpa_msg(wpa_s, MSG_DEBUG,
6091 "disable-sgi override specified, vht-caps: 0x%x",
6092 vhtcaps->vht_capabilities_info);
6093 }
6094
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006095 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006096 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6097 int max_ampdu;
6098
6099 max_ampdu = (ssid->vht_capa &
6100 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6101 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006102
6103 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6104 wpa_set_ampdu_factor(wpa_s,
6105 (void *) params->htcaps,
6106 (void *) params->htcaps_mask,
6107 max_ampdu);
6108 }
6109#endif /* CONFIG_HT_OVERRIDES */
6110
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006111#define OVERRIDE_MCS(i) \
6112 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6113 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006114 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006115 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006116 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6117 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006118 } \
6119 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6120 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006121 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006122 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006123 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6124 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006125 }
6126
6127 OVERRIDE_MCS(1);
6128 OVERRIDE_MCS(2);
6129 OVERRIDE_MCS(3);
6130 OVERRIDE_MCS(4);
6131 OVERRIDE_MCS(5);
6132 OVERRIDE_MCS(6);
6133 OVERRIDE_MCS(7);
6134 OVERRIDE_MCS(8);
6135}
6136#endif /* CONFIG_VHT_OVERRIDES */
6137
6138
Hai Shalomfdcde762020-04-02 11:19:20 -07006139#ifdef CONFIG_HE_OVERRIDES
6140void wpa_supplicant_apply_he_overrides(
6141 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6142 struct wpa_driver_associate_params *params)
6143{
6144 if (!ssid)
6145 return;
6146
6147 params->disable_he = ssid->disable_he;
6148}
6149#endif /* CONFIG_HE_OVERRIDES */
6150
6151
Sunil Ravi77d572f2023-01-17 23:58:31 +00006152void wpa_supplicant_apply_eht_overrides(
6153 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6154 struct wpa_driver_associate_params *params)
6155{
6156 if (!ssid)
6157 return;
6158
6159 params->disable_eht = ssid->disable_eht;
6160}
6161
6162
Dmitry Shmidt04949592012-07-19 12:16:46 -07006163static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6164{
6165#ifdef PCSC_FUNCS
6166 size_t len;
6167
6168 if (!wpa_s->conf->pcsc_reader)
6169 return 0;
6170
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006171 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006172 if (!wpa_s->scard)
6173 return 1;
6174
6175 if (wpa_s->conf->pcsc_pin &&
6176 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6177 scard_deinit(wpa_s->scard);
6178 wpa_s->scard = NULL;
6179 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6180 return -1;
6181 }
6182
6183 len = sizeof(wpa_s->imsi) - 1;
6184 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6185 scard_deinit(wpa_s->scard);
6186 wpa_s->scard = NULL;
6187 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6188 return -1;
6189 }
6190 wpa_s->imsi[len] = '\0';
6191
6192 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6193
6194 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6195 wpa_s->imsi, wpa_s->mnc_len);
6196
6197 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6198 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6199#endif /* PCSC_FUNCS */
6200
6201 return 0;
6202}
6203
6204
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006205int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6206{
6207 char *val, *pos;
6208
6209 ext_password_deinit(wpa_s->ext_pw);
6210 wpa_s->ext_pw = NULL;
6211 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6212
6213 if (!wpa_s->conf->ext_password_backend)
6214 return 0;
6215
6216 val = os_strdup(wpa_s->conf->ext_password_backend);
6217 if (val == NULL)
6218 return -1;
6219 pos = os_strchr(val, ':');
6220 if (pos)
6221 *pos++ = '\0';
6222
6223 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6224
6225 wpa_s->ext_pw = ext_password_init(val, pos);
6226 os_free(val);
6227 if (wpa_s->ext_pw == NULL) {
6228 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6229 return -1;
6230 }
6231 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6232
6233 return 0;
6234}
6235
6236
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006237#ifdef CONFIG_FST
6238
6239static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6240{
6241 struct wpa_supplicant *wpa_s = ctx;
6242
6243 return (is_zero_ether_addr(wpa_s->bssid) ||
6244 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6245}
6246
6247
6248static void wpas_fst_get_channel_info_cb(void *ctx,
6249 enum hostapd_hw_mode *hw_mode,
6250 u8 *channel)
6251{
6252 struct wpa_supplicant *wpa_s = ctx;
6253
6254 if (wpa_s->current_bss) {
6255 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6256 channel);
6257 } else if (wpa_s->hw.num_modes) {
6258 *hw_mode = wpa_s->hw.modes[0].mode;
6259 } else {
6260 WPA_ASSERT(0);
6261 *hw_mode = 0;
6262 }
6263}
6264
6265
6266static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6267{
6268 struct wpa_supplicant *wpa_s = ctx;
6269
6270 *modes = wpa_s->hw.modes;
6271 return wpa_s->hw.num_modes;
6272}
6273
6274
6275static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6276{
6277 struct wpa_supplicant *wpa_s = ctx;
6278
6279 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6280 wpa_s->fst_ies = fst_ies;
6281}
6282
6283
6284static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6285{
6286 struct wpa_supplicant *wpa_s = ctx;
6287
Paul Stewart092955c2017-02-06 09:13:09 -08006288 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6289 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6290 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6291 return -1;
6292 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006293 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006294 wpa_s->own_addr, wpa_s->bssid,
6295 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006296 0);
6297}
6298
6299
6300static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6301{
6302 struct wpa_supplicant *wpa_s = ctx;
6303
6304 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6305 return wpa_s->received_mb_ies;
6306}
6307
6308
6309static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6310 const u8 *buf, size_t size)
6311{
6312 struct wpa_supplicant *wpa_s = ctx;
6313 struct mb_ies_info info;
6314
6315 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6316
6317 if (!mb_ies_info_by_ies(&info, buf, size)) {
6318 wpabuf_free(wpa_s->received_mb_ies);
6319 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6320 }
6321}
6322
6323
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006324static const u8 * wpas_fst_get_peer_first(void *ctx,
6325 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006326 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006327{
6328 struct wpa_supplicant *wpa_s = ctx;
6329
6330 *get_ctx = NULL;
6331 if (!is_zero_ether_addr(wpa_s->bssid))
6332 return (wpa_s->received_mb_ies || !mb_only) ?
6333 wpa_s->bssid : NULL;
6334 return NULL;
6335}
6336
6337
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006338static const u8 * wpas_fst_get_peer_next(void *ctx,
6339 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006340 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006341{
6342 return NULL;
6343}
6344
6345void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6346 struct fst_wpa_obj *iface_obj)
6347{
Sunil8cd6f4d2022-06-28 18:40:46 +00006348 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006349 iface_obj->ctx = wpa_s;
6350 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6351 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6352 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6353 iface_obj->set_ies = wpas_fst_set_ies_cb;
6354 iface_obj->send_action = wpas_fst_send_action_cb;
6355 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6356 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6357 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6358 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6359}
6360#endif /* CONFIG_FST */
6361
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006362static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006363 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006364{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006365 struct wowlan_triggers *triggers;
6366 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006367
6368 if (!wpa_s->conf->wowlan_triggers)
6369 return 0;
6370
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006371 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6372 if (triggers) {
6373 ret = wpa_drv_wowlan(wpa_s, triggers);
6374 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006375 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006376 return ret;
6377}
6378
6379
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006380enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006381{
6382 if (freq < 3000)
6383 return BAND_2_4_GHZ;
6384 if (freq > 50000)
6385 return BAND_60_GHZ;
6386 return BAND_5_GHZ;
6387}
6388
6389
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006390unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006391{
6392 int i;
6393 unsigned int band = 0;
6394
6395 if (freqs) {
6396 /* freqs are specified for the radio work */
6397 for (i = 0; freqs[i]; i++)
6398 band |= wpas_freq_to_band(freqs[i]);
6399 } else {
6400 /*
6401 * freqs are not specified, implies all
6402 * the supported freqs by HW
6403 */
6404 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6405 if (wpa_s->hw.modes[i].num_channels != 0) {
6406 if (wpa_s->hw.modes[i].mode ==
6407 HOSTAPD_MODE_IEEE80211B ||
6408 wpa_s->hw.modes[i].mode ==
6409 HOSTAPD_MODE_IEEE80211G)
6410 band |= BAND_2_4_GHZ;
6411 else if (wpa_s->hw.modes[i].mode ==
6412 HOSTAPD_MODE_IEEE80211A)
6413 band |= BAND_5_GHZ;
6414 else if (wpa_s->hw.modes[i].mode ==
6415 HOSTAPD_MODE_IEEE80211AD)
6416 band |= BAND_60_GHZ;
6417 else if (wpa_s->hw.modes[i].mode ==
6418 HOSTAPD_MODE_IEEE80211ANY)
6419 band = BAND_2_4_GHZ | BAND_5_GHZ |
6420 BAND_60_GHZ;
6421 }
6422 }
6423 }
6424
6425 return band;
6426}
6427
6428
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006429static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6430 const char *rn)
6431{
6432 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6433 struct wpa_radio *radio;
6434
6435 while (rn && iface) {
6436 radio = iface->radio;
6437 if (radio && os_strcmp(rn, radio->name) == 0) {
6438 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6439 wpa_s->ifname, rn);
6440 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6441 return radio;
6442 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006443
6444 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006445 }
6446
6447 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6448 wpa_s->ifname, rn ? rn : "N/A");
6449 radio = os_zalloc(sizeof(*radio));
6450 if (radio == NULL)
6451 return NULL;
6452
6453 if (rn)
6454 os_strlcpy(radio->name, rn, sizeof(radio->name));
6455 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006456 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006457 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6458
6459 return radio;
6460}
6461
6462
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006463static void radio_work_free(struct wpa_radio_work *work)
6464{
6465 if (work->wpa_s->scan_work == work) {
6466 /* This should not really happen. */
6467 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6468 work->type, work, work->started);
6469 work->wpa_s->scan_work = NULL;
6470 }
6471
6472#ifdef CONFIG_P2P
6473 if (work->wpa_s->p2p_scan_work == work) {
6474 /* This should not really happen. */
6475 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6476 work->type, work, work->started);
6477 work->wpa_s->p2p_scan_work = NULL;
6478 }
6479#endif /* CONFIG_P2P */
6480
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006481 if (work->started) {
6482 work->wpa_s->radio->num_active_works--;
6483 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006484 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006485 work->type, work,
6486 work->wpa_s->radio->num_active_works);
6487 }
6488
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006489 dl_list_del(&work->list);
6490 os_free(work);
6491}
6492
6493
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006494static int radio_work_is_connect(struct wpa_radio_work *work)
6495{
6496 return os_strcmp(work->type, "sme-connect") == 0 ||
6497 os_strcmp(work->type, "connect") == 0;
6498}
6499
6500
6501static int radio_work_is_scan(struct wpa_radio_work *work)
6502{
6503 return os_strcmp(work->type, "scan") == 0 ||
6504 os_strcmp(work->type, "p2p-scan") == 0;
6505}
6506
6507
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006508static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6509{
6510 struct wpa_radio_work *active_work = NULL;
6511 struct wpa_radio_work *tmp;
6512
6513 /* Get the active work to know the type and band. */
6514 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6515 if (tmp->started) {
6516 active_work = tmp;
6517 break;
6518 }
6519 }
6520
6521 if (!active_work) {
6522 /* No active work, start one */
6523 radio->num_active_works = 0;
6524 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6525 list) {
6526 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006527 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006528 (((struct wpa_driver_scan_params *)
6529 tmp->ctx)->only_new_results ||
6530 tmp->wpa_s->clear_driver_scan_cache))
6531 continue;
6532 return tmp;
6533 }
6534 return NULL;
6535 }
6536
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006537 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006538 /*
6539 * If the active work is either connect or sme-connect,
6540 * do not parallelize them with other radio works.
6541 */
6542 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6543 "Do not parallelize radio work with %s",
6544 active_work->type);
6545 return NULL;
6546 }
6547
6548 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6549 if (tmp->started)
6550 continue;
6551
6552 /*
6553 * If connect or sme-connect are enqueued, parallelize only
6554 * those operations ahead of them in the queue.
6555 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006556 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006557 break;
6558
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006559 /* Serialize parallel scan and p2p_scan operations on the same
6560 * interface since the driver_nl80211 mechanism for tracking
6561 * scan cookies does not yet have support for this. */
6562 if (active_work->wpa_s == tmp->wpa_s &&
6563 radio_work_is_scan(active_work) &&
6564 radio_work_is_scan(tmp)) {
6565 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6566 "Do not start work '%s' when another work '%s' is already scheduled",
6567 tmp->type, active_work->type);
6568 continue;
6569 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006570 /*
6571 * Check that the radio works are distinct and
6572 * on different bands.
6573 */
6574 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6575 (active_work->bands != tmp->bands)) {
6576 /*
6577 * If a scan has to be scheduled through nl80211 scan
6578 * interface and if an external scan is already running,
6579 * do not schedule the scan since it is likely to get
6580 * rejected by kernel.
6581 */
6582 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006583 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006584 (((struct wpa_driver_scan_params *)
6585 tmp->ctx)->only_new_results ||
6586 tmp->wpa_s->clear_driver_scan_cache))
6587 continue;
6588
6589 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6590 "active_work:%s new_work:%s",
6591 active_work->type, tmp->type);
6592 return tmp;
6593 }
6594 }
6595
6596 /* Did not find a radio work to schedule in parallel. */
6597 return NULL;
6598}
6599
6600
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006601static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6602{
6603 struct wpa_radio *radio = eloop_ctx;
6604 struct wpa_radio_work *work;
6605 struct os_reltime now, diff;
6606 struct wpa_supplicant *wpa_s;
6607
6608 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006609 if (work == NULL) {
6610 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006611 return;
6612 }
6613
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006614 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6615 radio_list);
6616
6617 if (!(wpa_s &&
6618 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6619 if (work->started)
6620 return; /* already started and still in progress */
6621
Hai Shalom60840252021-02-19 19:02:11 -08006622 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006623 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6624 return;
6625 }
6626 } else {
6627 work = NULL;
6628 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6629 /* get the work to schedule next */
6630 work = radio_work_get_next_work(radio);
6631 }
6632 if (!work)
6633 return;
6634 }
6635
6636 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006637 os_get_reltime(&now);
6638 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006639 wpa_dbg(wpa_s, MSG_DEBUG,
6640 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006641 work->type, work, diff.sec, diff.usec);
6642 work->started = 1;
6643 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006644 radio->num_active_works++;
6645
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006646 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006647
6648 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6649 radio->num_active_works < MAX_ACTIVE_WORKS)
6650 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006651}
6652
6653
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006654/*
6655 * This function removes both started and pending radio works running on
6656 * the provided interface's radio.
6657 * Prior to the removal of the radio work, its callback (cb) is called with
6658 * deinit set to be 1. Each work's callback is responsible for clearing its
6659 * internal data and restoring to a correct state.
6660 * @wpa_s: wpa_supplicant data
6661 * @type: type of works to be removed
6662 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6663 * this interface's works.
6664 */
6665void radio_remove_works(struct wpa_supplicant *wpa_s,
6666 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006667{
6668 struct wpa_radio_work *work, *tmp;
6669 struct wpa_radio *radio = wpa_s->radio;
6670
6671 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6672 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006673 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006674 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006675
6676 /* skip other ifaces' works */
6677 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006678 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006679
6680 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6681 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006682 work->cb(work, 1);
6683 radio_work_free(work);
6684 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006685
6686 /* in case we removed the started work */
6687 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006688}
6689
6690
Roshan Pius3a1667e2018-07-03 15:17:14 -07006691void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6692{
6693 struct wpa_radio_work *work;
6694 struct wpa_radio *radio = wpa_s->radio;
6695
6696 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6697 if (work->ctx != ctx)
6698 continue;
6699 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6700 work->type, work, work->started ? " (started)" : "");
6701 radio_work_free(work);
6702 break;
6703 }
6704}
6705
6706
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006707static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6708{
6709 struct wpa_radio *radio = wpa_s->radio;
6710
6711 if (!radio)
6712 return;
6713
6714 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6715 wpa_s->ifname, radio->name);
6716 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006717 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006718 /* If the interface that triggered the external scan was removed, the
6719 * external scan is no longer running. */
6720 if (wpa_s == radio->external_scan_req_interface)
6721 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006722 wpa_s->radio = NULL;
6723 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006724 return; /* Interfaces remain for this radio */
6725
6726 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006727 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006728 os_free(radio);
6729}
6730
6731
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006732void radio_work_check_next(struct wpa_supplicant *wpa_s)
6733{
6734 struct wpa_radio *radio = wpa_s->radio;
6735
6736 if (dl_list_empty(&radio->work))
6737 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006738 if (wpa_s->ext_work_in_progress) {
6739 wpa_printf(MSG_DEBUG,
6740 "External radio work in progress - delay start of pending item");
6741 return;
6742 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006743 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6744 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6745}
6746
6747
6748/**
6749 * radio_add_work - Add a radio work item
6750 * @wpa_s: Pointer to wpa_supplicant data
6751 * @freq: Frequency of the offchannel operation in MHz or 0
6752 * @type: Unique identifier for each type of work
6753 * @next: Force as the next work to be executed
6754 * @cb: Callback function for indicating when radio is available
6755 * @ctx: Context pointer for the work (work->ctx in cb())
6756 * Returns: 0 on success, -1 on failure
6757 *
6758 * This function is used to request time for an operation that requires
6759 * exclusive radio control. Once the radio is available, the registered callback
6760 * function will be called. radio_work_done() must be called once the exclusive
6761 * radio operation has been completed, so that the radio is freed for other
6762 * operations. The special case of deinit=1 is used to free the context data
6763 * during interface removal. That does not allow the callback function to start
6764 * the radio operation, i.e., it must free any resources allocated for the radio
6765 * work and return.
6766 *
6767 * The @freq parameter can be used to indicate a single channel on which the
6768 * offchannel operation will occur. This may allow multiple radio work
6769 * operations to be performed in parallel if they apply for the same channel.
6770 * Setting this to 0 indicates that the work item may use multiple channels or
6771 * requires exclusive control of the radio.
6772 */
6773int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6774 const char *type, int next,
6775 void (*cb)(struct wpa_radio_work *work, int deinit),
6776 void *ctx)
6777{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006778 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006779 struct wpa_radio_work *work;
6780 int was_empty;
6781
6782 work = os_zalloc(sizeof(*work));
6783 if (work == NULL)
6784 return -1;
6785 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6786 os_get_reltime(&work->time);
6787 work->freq = freq;
6788 work->type = type;
6789 work->wpa_s = wpa_s;
6790 work->cb = cb;
6791 work->ctx = ctx;
6792
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006793 if (freq)
6794 work->bands = wpas_freq_to_band(freq);
6795 else if (os_strcmp(type, "scan") == 0 ||
6796 os_strcmp(type, "p2p-scan") == 0)
6797 work->bands = wpas_get_bands(wpa_s,
6798 ((struct wpa_driver_scan_params *)
6799 ctx)->freqs);
6800 else
6801 work->bands = wpas_get_bands(wpa_s, NULL);
6802
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006803 was_empty = dl_list_empty(&wpa_s->radio->work);
6804 if (next)
6805 dl_list_add(&wpa_s->radio->work, &work->list);
6806 else
6807 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6808 if (was_empty) {
6809 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6810 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006811 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6812 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6813 wpa_dbg(wpa_s, MSG_DEBUG,
6814 "Try to schedule a radio work (num_active_works=%u)",
6815 radio->num_active_works);
6816 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006817 }
6818
6819 return 0;
6820}
6821
6822
6823/**
6824 * radio_work_done - Indicate that a radio work item has been completed
6825 * @work: Completed work
6826 *
6827 * This function is called once the callback function registered with
6828 * radio_add_work() has completed its work.
6829 */
6830void radio_work_done(struct wpa_radio_work *work)
6831{
6832 struct wpa_supplicant *wpa_s = work->wpa_s;
6833 struct os_reltime now, diff;
6834 unsigned int started = work->started;
6835
6836 os_get_reltime(&now);
6837 os_reltime_sub(&now, &work->time, &diff);
6838 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6839 work->type, work, started ? "done" : "canceled",
6840 diff.sec, diff.usec);
6841 radio_work_free(work);
6842 if (started)
6843 radio_work_check_next(wpa_s);
6844}
6845
6846
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006847struct wpa_radio_work *
6848radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006849{
6850 struct wpa_radio_work *work;
6851 struct wpa_radio *radio = wpa_s->radio;
6852
6853 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6854 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006855 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006856 }
6857
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006858 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006859}
6860
6861
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006862static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006863 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006864{
6865 const char *ifname, *driver, *rn;
6866
6867 driver = iface->driver;
6868next_driver:
6869 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6870 return -1;
6871
6872 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6873 if (wpa_s->drv_priv == NULL) {
6874 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006875 int level = MSG_ERROR;
6876
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006877 pos = driver ? os_strchr(driver, ',') : NULL;
6878 if (pos) {
6879 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6880 "driver interface - try next driver wrapper");
6881 driver = pos + 1;
6882 goto next_driver;
6883 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006884
6885#ifdef CONFIG_MATCH_IFACE
6886 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6887 level = MSG_DEBUG;
6888#endif /* CONFIG_MATCH_IFACE */
6889 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006890 return -1;
6891 }
6892 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6893 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6894 "driver_param '%s'", wpa_s->conf->driver_param);
6895 return -1;
6896 }
6897
6898 ifname = wpa_drv_get_ifname(wpa_s);
6899 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6900 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6901 "interface name with '%s'", ifname);
6902 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6903 }
6904
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006905 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006906 if (rn && rn[0] == '\0')
6907 rn = NULL;
6908
6909 wpa_s->radio = radio_add_interface(wpa_s, rn);
6910 if (wpa_s->radio == NULL)
6911 return -1;
6912
6913 return 0;
6914}
6915
6916
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006917#ifdef CONFIG_GAS_SERVER
6918
6919static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6920 unsigned int freq, const u8 *dst,
6921 const u8 *src, const u8 *bssid,
6922 const u8 *data, size_t data_len,
6923 enum offchannel_send_action_result result)
6924{
6925 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6926 " result=%s",
6927 freq, MAC2STR(dst),
6928 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6929 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6930 "FAILED"));
6931 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6932 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6933}
6934
6935
6936static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6937 struct wpabuf *buf, unsigned int wait_time)
6938{
6939 struct wpa_supplicant *wpa_s = ctx;
6940 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6941
6942 if (wait_time > wpa_s->max_remain_on_chan)
6943 wait_time = wpa_s->max_remain_on_chan;
6944
6945 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6946 wpabuf_head(buf), wpabuf_len(buf),
6947 wait_time, wpas_gas_server_tx_status, 0);
6948}
6949
6950#endif /* CONFIG_GAS_SERVER */
6951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006952static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006953 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006955 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006956 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006957 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006958
6959 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6960 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6961 iface->confname ? iface->confname : "N/A",
6962 iface->driver ? iface->driver : "default",
6963 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6964 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6965
6966 if (iface->confname) {
6967#ifdef CONFIG_BACKEND_FILE
6968 wpa_s->confname = os_rel2abs_path(iface->confname);
6969 if (wpa_s->confname == NULL) {
6970 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6971 "for configuration file '%s'.",
6972 iface->confname);
6973 return -1;
6974 }
6975 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6976 iface->confname, wpa_s->confname);
6977#else /* CONFIG_BACKEND_FILE */
6978 wpa_s->confname = os_strdup(iface->confname);
6979#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00006980 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006981 if (wpa_s->conf == NULL) {
6982 wpa_printf(MSG_ERROR, "Failed to read or parse "
6983 "configuration '%s'.", wpa_s->confname);
6984 return -1;
6985 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006986 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006987 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00006988 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006989 wpa_printf(MSG_ERROR,
6990 "Failed to read or parse configuration '%s'.",
6991 wpa_s->confanother);
6992 return -1;
6993 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006994
6995 /*
6996 * Override ctrl_interface and driver_param if set on command
6997 * line.
6998 */
6999 if (iface->ctrl_interface) {
7000 os_free(wpa_s->conf->ctrl_interface);
7001 wpa_s->conf->ctrl_interface =
7002 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007003 if (!wpa_s->conf->ctrl_interface) {
7004 wpa_printf(MSG_ERROR,
7005 "Failed to duplicate control interface '%s'.",
7006 iface->ctrl_interface);
7007 return -1;
7008 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007009 }
7010
7011 if (iface->driver_param) {
7012 os_free(wpa_s->conf->driver_param);
7013 wpa_s->conf->driver_param =
7014 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007015 if (!wpa_s->conf->driver_param) {
7016 wpa_printf(MSG_ERROR,
7017 "Failed to duplicate driver param '%s'.",
7018 iface->driver_param);
7019 return -1;
7020 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007021 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007022
7023 if (iface->p2p_mgmt && !iface->ctrl_interface) {
7024 os_free(wpa_s->conf->ctrl_interface);
7025 wpa_s->conf->ctrl_interface = NULL;
7026 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007027 } else
7028 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7029 iface->driver_param);
7030
7031 if (wpa_s->conf == NULL) {
7032 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7033 return -1;
7034 }
7035
7036 if (iface->ifname == NULL) {
7037 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7038 return -1;
7039 }
7040 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7041 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7042 iface->ifname);
7043 return -1;
7044 }
7045 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007046#ifdef CONFIG_MATCH_IFACE
7047 wpa_s->matched = iface->matched;
7048#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007049
7050 if (iface->bridge_ifname) {
7051 if (os_strlen(iface->bridge_ifname) >=
7052 sizeof(wpa_s->bridge_ifname)) {
7053 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7054 "name '%s'.", iface->bridge_ifname);
7055 return -1;
7056 }
7057 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7058 sizeof(wpa_s->bridge_ifname));
7059 }
7060
7061 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007062 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7063 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007064
7065 /* Initialize driver interface and register driver event handler before
7066 * L2 receive handler so that association events are processed before
7067 * EAPOL-Key packets if both become available for the same select()
7068 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007069 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007070 return -1;
7071
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007072 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7073 return -1;
7074
7075 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7076 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7077 NULL);
7078 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7079
7080 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7081 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7082 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7083 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7084 "dot11RSNAConfigPMKLifetime");
7085 return -1;
7086 }
7087
7088 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7089 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7090 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7091 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7092 "dot11RSNAConfigPMKReauthThreshold");
7093 return -1;
7094 }
7095
7096 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7097 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7098 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7099 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7100 "dot11RSNAConfigSATimeout");
7101 return -1;
7102 }
7103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007104 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7105 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007106 &wpa_s->hw.flags,
7107 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007108 if (wpa_s->hw.modes) {
7109 u16 i;
7110
7111 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7112 if (wpa_s->hw.modes[i].vht_capab) {
7113 wpa_s->hw_capab = CAPAB_VHT;
7114 break;
7115 }
7116
7117 if (wpa_s->hw.modes[i].ht_capab &
7118 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7119 wpa_s->hw_capab = CAPAB_HT40;
7120 else if (wpa_s->hw.modes[i].ht_capab &&
7121 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7122 wpa_s->hw_capab = CAPAB_HT;
7123 }
7124 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007125
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007126 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7127 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007128 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007130 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007131 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007132 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007133 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007134 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007135 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007136 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007137 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7138 wpa_s->max_sched_scan_plan_interval =
7139 capa.max_sched_scan_plan_interval;
7140 wpa_s->max_sched_scan_plan_iterations =
7141 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007142 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7143 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7145 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007146 wpa_s->extended_capa = capa.extended_capa;
7147 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7148 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007149 wpa_s->num_multichan_concurrent =
7150 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007151 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007152 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007153
7154 if (capa.mac_addr_rand_scan_supported)
7155 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7156 if (wpa_s->sched_scan_supported &&
7157 capa.mac_addr_rand_sched_scan_supported)
7158 wpa_s->mac_addr_rand_supported |=
7159 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007160
7161 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7162 if (wpa_s->extended_capa &&
7163 wpa_s->extended_capa_len >= 3 &&
7164 wpa_s->extended_capa[2] & 0x40)
7165 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007166 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007167#ifdef CONFIG_PASN
7168 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7169#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007170 if (wpa_s->max_remain_on_chan == 0)
7171 wpa_s->max_remain_on_chan = 1000;
7172
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007173 /*
7174 * Only take p2p_mgmt parameters when P2P Device is supported.
7175 * Doing it here as it determines whether l2_packet_init() will be done
7176 * during wpa_supplicant_driver_init().
7177 */
7178 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7179 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007180
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007181 if (wpa_s->num_multichan_concurrent == 0)
7182 wpa_s->num_multichan_concurrent = 1;
7183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007184 if (wpa_supplicant_driver_init(wpa_s) < 0)
7185 return -1;
7186
7187#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007188 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007189 return -1;
7190#endif /* CONFIG_TDLS */
7191
7192 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7193 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7194 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7195 return -1;
7196 }
7197
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007198#ifdef CONFIG_FST
7199 if (wpa_s->conf->fst_group_id) {
7200 struct fst_iface_cfg cfg;
7201 struct fst_wpa_obj iface_obj;
7202
7203 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7204 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7205 sizeof(cfg.group_id));
7206 cfg.priority = wpa_s->conf->fst_priority;
7207 cfg.llt = wpa_s->conf->fst_llt;
7208
7209 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7210 &iface_obj, &cfg);
7211 if (!wpa_s->fst) {
7212 wpa_msg(wpa_s, MSG_ERROR,
7213 "FST: Cannot attach iface %s to group %s",
7214 wpa_s->ifname, cfg.group_id);
7215 return -1;
7216 }
7217 }
7218#endif /* CONFIG_FST */
7219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007220 if (wpas_wps_init(wpa_s))
7221 return -1;
7222
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007223#ifdef CONFIG_GAS_SERVER
7224 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7225 if (!wpa_s->gas_server) {
7226 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7227 return -1;
7228 }
7229#endif /* CONFIG_GAS_SERVER */
7230
7231#ifdef CONFIG_DPP
7232 if (wpas_dpp_init(wpa_s) < 0)
7233 return -1;
7234#endif /* CONFIG_DPP */
7235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007236 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7237 return -1;
7238 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7239
7240 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7241 if (wpa_s->ctrl_iface == NULL) {
7242 wpa_printf(MSG_ERROR,
7243 "Failed to initialize control interface '%s'.\n"
7244 "You may have another wpa_supplicant process "
7245 "already running or the file was\n"
7246 "left by an unclean termination of wpa_supplicant "
7247 "in which case you will need\n"
7248 "to manually remove this file before starting "
7249 "wpa_supplicant again.\n",
7250 wpa_s->conf->ctrl_interface);
7251 return -1;
7252 }
7253
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007254 wpa_s->gas = gas_query_init(wpa_s);
7255 if (wpa_s->gas == NULL) {
7256 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7257 return -1;
7258 }
7259
Roshan Pius3a1667e2018-07-03 15:17:14 -07007260 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7261 wpa_s->p2p_mgmt) &&
7262 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007263 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7264 return -1;
7265 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007266
7267 if (wpa_bss_init(wpa_s) < 0)
7268 return -1;
7269
Paul Stewart092955c2017-02-06 09:13:09 -08007270#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7271#ifdef CONFIG_MESH
7272 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7273#endif /* CONFIG_MESH */
7274#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7275
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007276 /*
7277 * Set Wake-on-WLAN triggers, if configured.
7278 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7279 * have effect anyway when the interface is down).
7280 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007281 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007282 return -1;
7283
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007284#ifdef CONFIG_EAP_PROXY
7285{
7286 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007287 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7288 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007289 if (wpa_s->mnc_len > 0) {
7290 wpa_s->imsi[len] = '\0';
7291 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7292 wpa_s->imsi, wpa_s->mnc_len);
7293 } else {
7294 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7295 }
7296}
7297#endif /* CONFIG_EAP_PROXY */
7298
Dmitry Shmidt04949592012-07-19 12:16:46 -07007299 if (pcsc_reader_init(wpa_s) < 0)
7300 return -1;
7301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007302 if (wpas_init_ext_pw(wpa_s) < 0)
7303 return -1;
7304
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007305 wpas_rrm_reset(wpa_s);
7306
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007307 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7308
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007309#ifdef CONFIG_HS20
7310 hs20_init(wpa_s);
7311#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007312#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007313 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007314 if ((wpa_s->conf->oce & OCE_STA) &&
7315 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7316 wpa_s->enable_oce = OCE_STA;
7317 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7318 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7319 /* TODO: Need to add STA-CFON support */
7320 wpa_printf(MSG_ERROR,
7321 "OCE STA-CFON feature is not yet supported");
7322 }
7323 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007324 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7325#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007326
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007327 wpa_supplicant_set_default_scan_ies(wpa_s);
7328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007329 return 0;
7330}
7331
7332
7333static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007334 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007335{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007336 struct wpa_global *global = wpa_s->global;
7337 struct wpa_supplicant *iface, *prev;
7338
Jimmy Chen0e73c002021-08-18 13:21:30 +08007339 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007340 wpas_p2p_group_remove(wpa_s, "*");
7341
7342 iface = global->ifaces;
7343 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007344 if (iface->p2pdev == wpa_s)
7345 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007346 if (iface == wpa_s || iface->parent != wpa_s) {
7347 iface = iface->next;
7348 continue;
7349 }
7350 wpa_printf(MSG_DEBUG,
7351 "Remove remaining child interface %s from parent %s",
7352 iface->ifname, wpa_s->ifname);
7353 prev = iface;
7354 iface = iface->next;
7355 wpa_supplicant_remove_iface(global, prev, terminate);
7356 }
7357
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007358 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007359 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007360 /*
7361 * Don't deauthenticate if WoWLAN is enable and not explicitly
7362 * been configured to disconnect.
7363 */
7364 if (!wpa_drv_get_wowlan(wpa_s) ||
7365 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007366 wpa_supplicant_deauthenticate(
7367 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007368
Hai Shalomfdcde762020-04-02 11:19:20 -07007369 wpa_drv_set_countermeasures(wpa_s, 0);
7370 wpa_clear_keys(wpa_s, NULL);
7371 } else {
7372 wpa_msg(wpa_s, MSG_INFO,
7373 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7374 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007375 }
7376
7377 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007378 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007379
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007380 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007381 radio_remove_interface(wpa_s);
7382
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007383#ifdef CONFIG_FST
7384 if (wpa_s->fst) {
7385 fst_detach(wpa_s->fst);
7386 wpa_s->fst = NULL;
7387 }
7388 if (wpa_s->received_mb_ies) {
7389 wpabuf_free(wpa_s->received_mb_ies);
7390 wpa_s->received_mb_ies = NULL;
7391 }
7392#endif /* CONFIG_FST */
7393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007394 if (wpa_s->drv_priv)
7395 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007396
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007397 if (notify)
7398 wpas_notify_iface_removed(wpa_s);
7399
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007400 if (terminate)
7401 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007402
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007403 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7404 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007405
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007406#ifdef CONFIG_MESH
7407 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007408 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007409 wpa_s->ifmsh = NULL;
7410 }
7411#endif /* CONFIG_MESH */
7412
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007413 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007414 wpa_config_free(wpa_s->conf);
7415 wpa_s->conf = NULL;
7416 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007417
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007418 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007419 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007420
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007421 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007422}
7423
7424
Dmitry Shmidte4663042016-04-04 10:07:49 -07007425#ifdef CONFIG_MATCH_IFACE
7426
7427/**
7428 * wpa_supplicant_match_iface - Match an interface description to a name
7429 * @global: Pointer to global data from wpa_supplicant_init()
7430 * @ifname: Name of the interface to match
7431 * Returns: Pointer to the created interface description or %NULL on failure
7432 */
7433struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7434 const char *ifname)
7435{
7436 int i;
7437 struct wpa_interface *iface, *miface;
7438
7439 for (i = 0; i < global->params.match_iface_count; i++) {
7440 miface = &global->params.match_ifaces[i];
7441 if (!miface->ifname ||
7442 fnmatch(miface->ifname, ifname, 0) == 0) {
7443 iface = os_zalloc(sizeof(*iface));
7444 if (!iface)
7445 return NULL;
7446 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007447 if (!miface->ifname)
7448 iface->matched = WPA_IFACE_MATCHED_NULL;
7449 else
7450 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007451 iface->ifname = ifname;
7452 return iface;
7453 }
7454 }
7455
7456 return NULL;
7457}
7458
7459
7460/**
7461 * wpa_supplicant_match_existing - Match existing interfaces
7462 * @global: Pointer to global data from wpa_supplicant_init()
7463 * Returns: 0 on success, -1 on failure
7464 */
7465static int wpa_supplicant_match_existing(struct wpa_global *global)
7466{
7467 struct if_nameindex *ifi, *ifp;
7468 struct wpa_supplicant *wpa_s;
7469 struct wpa_interface *iface;
7470
7471 ifp = if_nameindex();
7472 if (!ifp) {
7473 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7474 return -1;
7475 }
7476
7477 for (ifi = ifp; ifi->if_name; ifi++) {
7478 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7479 if (wpa_s)
7480 continue;
7481 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7482 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007483 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007484 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007485 }
7486 }
7487
7488 if_freenameindex(ifp);
7489 return 0;
7490}
7491
7492#endif /* CONFIG_MATCH_IFACE */
7493
7494
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007495/**
7496 * wpa_supplicant_add_iface - Add a new network interface
7497 * @global: Pointer to global data from wpa_supplicant_init()
7498 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007499 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007500 * Returns: Pointer to the created interface or %NULL on failure
7501 *
7502 * This function is used to add new network interfaces for %wpa_supplicant.
7503 * This can be called before wpa_supplicant_run() to add interfaces before the
7504 * main event loop has been started. In addition, new interfaces can be added
7505 * dynamically while %wpa_supplicant is already running. This could happen,
7506 * e.g., when a hotplug network adapter is inserted.
7507 */
7508struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007509 struct wpa_interface *iface,
7510 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007511{
7512 struct wpa_supplicant *wpa_s;
7513 struct wpa_interface t_iface;
7514 struct wpa_ssid *ssid;
7515
7516 if (global == NULL || iface == NULL)
7517 return NULL;
7518
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007519 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007520 if (wpa_s == NULL)
7521 return NULL;
7522
7523 wpa_s->global = global;
7524
7525 t_iface = *iface;
7526 if (global->params.override_driver) {
7527 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7528 "('%s' -> '%s')",
7529 iface->driver, global->params.override_driver);
7530 t_iface.driver = global->params.override_driver;
7531 }
7532 if (global->params.override_ctrl_interface) {
7533 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7534 "ctrl_interface ('%s' -> '%s')",
7535 iface->ctrl_interface,
7536 global->params.override_ctrl_interface);
7537 t_iface.ctrl_interface =
7538 global->params.override_ctrl_interface;
7539 }
7540 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7541 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7542 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007543 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007544 return NULL;
7545 }
7546
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007547 /* Notify the control interfaces about new iface */
7548 if (wpas_notify_iface_added(wpa_s)) {
7549 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7550 return NULL;
7551 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007552
Jimmy Chene2206be2022-07-10 10:25:21 +08007553 /* Notify the control interfaces about new networks */
7554 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7555 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007556 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007557 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7558 && os_strncmp((const char *) ssid->ssid,
7559 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7560 wpas_notify_persistent_group_added(wpa_s, ssid);
7561 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007562 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007563
7564 wpa_s->next = global->ifaces;
7565 global->ifaces = wpa_s;
7566
7567 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007568 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007569
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007570#ifdef CONFIG_P2P
7571 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007572 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007573 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007574 wpas_p2p_add_p2pdev_interface(
7575 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007576 wpa_printf(MSG_INFO,
7577 "P2P: Failed to enable P2P Device interface");
7578 /* Try to continue without. P2P will be disabled. */
7579 }
7580#endif /* CONFIG_P2P */
7581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007582 return wpa_s;
7583}
7584
7585
7586/**
7587 * wpa_supplicant_remove_iface - Remove a network interface
7588 * @global: Pointer to global data from wpa_supplicant_init()
7589 * @wpa_s: Pointer to the network interface to be removed
7590 * Returns: 0 if interface was removed, -1 if interface was not found
7591 *
7592 * This function can be used to dynamically remove network interfaces from
7593 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7594 * addition, this function is used to remove all remaining interfaces when
7595 * %wpa_supplicant is terminated.
7596 */
7597int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007598 struct wpa_supplicant *wpa_s,
7599 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007600{
7601 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007602#ifdef CONFIG_MESH
7603 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7604 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007605 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007606#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007607
7608 /* Remove interface from the global list of interfaces */
7609 prev = global->ifaces;
7610 if (prev == wpa_s) {
7611 global->ifaces = wpa_s->next;
7612 } else {
7613 while (prev && prev->next != wpa_s)
7614 prev = prev->next;
7615 if (prev == NULL)
7616 return -1;
7617 prev->next = wpa_s->next;
7618 }
7619
7620 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7621
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007622#ifdef CONFIG_MESH
7623 if (mesh_if_created) {
7624 ifname = os_strdup(wpa_s->ifname);
7625 if (ifname == NULL) {
7626 wpa_dbg(wpa_s, MSG_ERROR,
7627 "mesh: Failed to malloc ifname");
7628 return -1;
7629 }
7630 }
7631#endif /* CONFIG_MESH */
7632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007633 if (global->p2p_group_formation == wpa_s)
7634 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007635 if (global->p2p_invite_group == wpa_s)
7636 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007637 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007638
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007639#ifdef CONFIG_MESH
7640 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007641 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007642 os_free(ifname);
7643 }
7644#endif /* CONFIG_MESH */
7645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007646 return 0;
7647}
7648
7649
7650/**
7651 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7652 * @wpa_s: Pointer to the network interface
7653 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7654 */
7655const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7656{
7657 const char *eapol_method;
7658
7659 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7660 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7661 return "NO-EAP";
7662 }
7663
7664 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7665 if (eapol_method == NULL)
7666 return "UNKNOWN-EAP";
7667
7668 return eapol_method;
7669}
7670
7671
7672/**
7673 * wpa_supplicant_get_iface - Get a new network interface
7674 * @global: Pointer to global data from wpa_supplicant_init()
7675 * @ifname: Interface name
7676 * Returns: Pointer to the interface or %NULL if not found
7677 */
7678struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7679 const char *ifname)
7680{
7681 struct wpa_supplicant *wpa_s;
7682
7683 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7684 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7685 return wpa_s;
7686 }
7687 return NULL;
7688}
7689
7690
7691#ifndef CONFIG_NO_WPA_MSG
7692static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7693{
7694 struct wpa_supplicant *wpa_s = ctx;
7695 if (wpa_s == NULL)
7696 return NULL;
7697 return wpa_s->ifname;
7698}
7699#endif /* CONFIG_NO_WPA_MSG */
7700
7701
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007702#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7703#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7704#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7705
7706/* Periodic cleanup tasks */
7707static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7708{
7709 struct wpa_global *global = eloop_ctx;
7710 struct wpa_supplicant *wpa_s;
7711
7712 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7713 wpas_periodic, global, NULL);
7714
7715#ifdef CONFIG_P2P
7716 if (global->p2p)
7717 p2p_expire_peers(global->p2p);
7718#endif /* CONFIG_P2P */
7719
7720 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7721 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7722#ifdef CONFIG_AP
7723 ap_periodic(wpa_s);
7724#endif /* CONFIG_AP */
7725 }
7726}
7727
7728
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007729/**
7730 * wpa_supplicant_init - Initialize %wpa_supplicant
7731 * @params: Parameters for %wpa_supplicant
7732 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7733 *
7734 * This function is used to initialize %wpa_supplicant. After successful
7735 * initialization, the returned data pointer can be used to add and remove
7736 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7737 */
7738struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7739{
7740 struct wpa_global *global;
7741 int ret, i;
7742
7743 if (params == NULL)
7744 return NULL;
7745
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007746#ifdef CONFIG_DRIVER_NDIS
7747 {
7748 void driver_ndis_init_ops(void);
7749 driver_ndis_init_ops();
7750 }
7751#endif /* CONFIG_DRIVER_NDIS */
7752
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007753#ifndef CONFIG_NO_WPA_MSG
7754 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7755#endif /* CONFIG_NO_WPA_MSG */
7756
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007757 if (params->wpa_debug_file_path)
7758 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007759 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007760 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007761 if (params->wpa_debug_syslog)
7762 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007763 if (params->wpa_debug_tracing) {
7764 ret = wpa_debug_open_linux_tracing();
7765 if (ret) {
7766 wpa_printf(MSG_ERROR,
7767 "Failed to enable trace logging");
7768 return NULL;
7769 }
7770 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771
7772 ret = eap_register_methods();
7773 if (ret) {
7774 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7775 if (ret == -2)
7776 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7777 "the same EAP type.");
7778 return NULL;
7779 }
7780
7781 global = os_zalloc(sizeof(*global));
7782 if (global == NULL)
7783 return NULL;
7784 dl_list_init(&global->p2p_srv_bonjour);
7785 dl_list_init(&global->p2p_srv_upnp);
7786 global->params.daemonize = params->daemonize;
7787 global->params.wait_for_monitor = params->wait_for_monitor;
7788 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007789
7790 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007791 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007792 if (!global->params.pid_file) {
7793 wpa_supplicant_deinit(global);
7794 return NULL;
7795 }
7796 }
7797
7798 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007799 global->params.ctrl_interface =
7800 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007801 if (!global->params.ctrl_interface) {
7802 wpa_supplicant_deinit(global);
7803 return NULL;
7804 }
7805 }
7806
7807 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007808 global->params.ctrl_interface_group =
7809 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007810 if (!global->params.ctrl_interface_group) {
7811 wpa_supplicant_deinit(global);
7812 return NULL;
7813 }
7814 }
7815
7816 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007817 global->params.override_driver =
7818 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007819 if (!global->params.override_driver) {
7820 wpa_supplicant_deinit(global);
7821 return NULL;
7822 }
7823 }
7824
7825 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007826 global->params.override_ctrl_interface =
7827 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007828 if (!global->params.override_ctrl_interface) {
7829 wpa_supplicant_deinit(global);
7830 return NULL;
7831 }
7832 }
7833
Dmitry Shmidte4663042016-04-04 10:07:49 -07007834#ifdef CONFIG_MATCH_IFACE
7835 global->params.match_iface_count = params->match_iface_count;
7836 if (params->match_iface_count) {
7837 global->params.match_ifaces =
7838 os_calloc(params->match_iface_count,
7839 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007840 if (!global->params.match_ifaces) {
7841 wpa_printf(MSG_ERROR,
7842 "Failed to allocate match interfaces");
7843 wpa_supplicant_deinit(global);
7844 return NULL;
7845 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007846 os_memcpy(global->params.match_ifaces,
7847 params->match_ifaces,
7848 params->match_iface_count *
7849 sizeof(struct wpa_interface));
7850 }
7851#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007852#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007853 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007854 global->params.conf_p2p_dev =
7855 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007856 if (!global->params.conf_p2p_dev) {
7857 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7858 wpa_supplicant_deinit(global);
7859 return NULL;
7860 }
7861 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007862#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007863 wpa_debug_level = global->params.wpa_debug_level =
7864 params->wpa_debug_level;
7865 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7866 params->wpa_debug_show_keys;
7867 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7868 params->wpa_debug_timestamp;
7869
Hai Shalomfdcde762020-04-02 11:19:20 -07007870 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007871
7872 if (eloop_init()) {
7873 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7874 wpa_supplicant_deinit(global);
7875 return NULL;
7876 }
7877
Jouni Malinen75ecf522011-06-27 15:19:46 -07007878 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007879
7880 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7881 if (global->ctrl_iface == NULL) {
7882 wpa_supplicant_deinit(global);
7883 return NULL;
7884 }
7885
7886 if (wpas_notify_supplicant_initialized(global)) {
7887 wpa_supplicant_deinit(global);
7888 return NULL;
7889 }
7890
7891 for (i = 0; wpa_drivers[i]; i++)
7892 global->drv_count++;
7893 if (global->drv_count == 0) {
7894 wpa_printf(MSG_ERROR, "No drivers enabled");
7895 wpa_supplicant_deinit(global);
7896 return NULL;
7897 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007898 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007899 if (global->drv_priv == NULL) {
7900 wpa_supplicant_deinit(global);
7901 return NULL;
7902 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007903
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007904#ifdef CONFIG_WIFI_DISPLAY
7905 if (wifi_display_init(global) < 0) {
7906 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7907 wpa_supplicant_deinit(global);
7908 return NULL;
7909 }
7910#endif /* CONFIG_WIFI_DISPLAY */
7911
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007912 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7913 wpas_periodic, global, NULL);
7914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007915 return global;
7916}
7917
7918
7919/**
7920 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7921 * @global: Pointer to global data from wpa_supplicant_init()
7922 * Returns: 0 after successful event loop run, -1 on failure
7923 *
7924 * This function starts the main event loop and continues running as long as
7925 * there are any remaining events. In most cases, this function is running as
7926 * long as the %wpa_supplicant process in still in use.
7927 */
7928int wpa_supplicant_run(struct wpa_global *global)
7929{
7930 struct wpa_supplicant *wpa_s;
7931
7932 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007933 (wpa_supplicant_daemon(global->params.pid_file) ||
7934 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007935 return -1;
7936
Dmitry Shmidte4663042016-04-04 10:07:49 -07007937#ifdef CONFIG_MATCH_IFACE
7938 if (wpa_supplicant_match_existing(global))
7939 return -1;
7940#endif
7941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007942 if (global->params.wait_for_monitor) {
7943 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007944 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007945 wpa_supplicant_ctrl_iface_wait(
7946 wpa_s->ctrl_iface);
7947 }
7948
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07007949#ifdef CONFIG_AIDL
Gabriel Biren7a30e7f2023-06-02 20:11:28 +00007950 // If daemonize is enabled, initialize AIDL here.
7951 if (global->params.daemonize) {
7952 global->aidl = wpas_aidl_init(global);
7953 if (!global->aidl)
7954 return -1;
7955 }
Kiran Kumar Lokerea9f98eb2023-03-17 13:01:12 -07007956#endif /* CONFIG_AIDL */
7957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007958 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7959 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7960
7961 eloop_run();
7962
7963 return 0;
7964}
7965
7966
7967/**
7968 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7969 * @global: Pointer to global data from wpa_supplicant_init()
7970 *
7971 * This function is called to deinitialize %wpa_supplicant and to free all
7972 * allocated resources. Remaining network interfaces will also be removed.
7973 */
7974void wpa_supplicant_deinit(struct wpa_global *global)
7975{
7976 int i;
7977
7978 if (global == NULL)
7979 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007980
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007981 eloop_cancel_timeout(wpas_periodic, global, NULL);
7982
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007983#ifdef CONFIG_WIFI_DISPLAY
7984 wifi_display_deinit(global);
7985#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007986
7987 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007988 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007989
7990 if (global->ctrl_iface)
7991 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7992
7993 wpas_notify_supplicant_deinitialized(global);
7994
7995 eap_peer_unregister_methods();
7996#ifdef CONFIG_AP
7997 eap_server_unregister_methods();
7998#endif /* CONFIG_AP */
7999
8000 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
8001 if (!global->drv_priv[i])
8002 continue;
8003 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
8004 }
8005 os_free(global->drv_priv);
8006
8007 random_deinit();
8008
8009 eloop_destroy();
8010
8011 if (global->params.pid_file) {
8012 os_daemonize_terminate(global->params.pid_file);
8013 os_free(global->params.pid_file);
8014 }
8015 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008016 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008017 os_free(global->params.override_driver);
8018 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07008019#ifdef CONFIG_MATCH_IFACE
8020 os_free(global->params.match_ifaces);
8021#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008022#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07008023 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008024#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008025
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07008026 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008027 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008028 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008030 os_free(global);
8031 wpa_debug_close_syslog();
8032 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07008033 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008034}
8035
8036
8037void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8038{
8039 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8040 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8041 char country[3];
8042 country[0] = wpa_s->conf->country[0];
8043 country[1] = wpa_s->conf->country[1];
8044 country[2] = '\0';
8045 if (wpa_drv_set_country(wpa_s, country) < 0) {
8046 wpa_printf(MSG_ERROR, "Failed to set country code "
8047 "'%s'", country);
8048 }
8049 }
8050
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008051 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8052 wpas_init_ext_pw(wpa_s);
8053
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008054 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8055 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8056
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008057 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8058 struct wpa_driver_capa capa;
8059 int res = wpa_drv_get_capa(wpa_s, &capa);
8060
8061 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8062 wpa_printf(MSG_ERROR,
8063 "Failed to update wowlan_triggers to '%s'",
8064 wpa_s->conf->wowlan_triggers);
8065 }
8066
Hai Shalom81f62d82019-07-22 12:10:00 -07008067 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8068 wpa_supplicant_set_default_scan_ies(wpa_s);
8069
Hai Shalom899fcc72020-10-19 14:38:18 -07008070#ifdef CONFIG_BGSCAN
8071 /*
8072 * We default to global bgscan parameters only when per-network bgscan
8073 * parameters aren't set. Only bother resetting bgscan parameters if
8074 * this is the case.
8075 */
8076 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8077 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8078 wpa_s->wpa_state == WPA_COMPLETED)
8079 wpa_supplicant_reset_bgscan(wpa_s);
8080#endif /* CONFIG_BGSCAN */
8081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008082#ifdef CONFIG_WPS
8083 wpas_wps_update_config(wpa_s);
8084#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008085 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008086 wpa_s->conf->changed_parameters = 0;
8087}
8088
8089
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008090void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008091{
8092 int i;
8093
8094 for (i = 0; i < *num_freqs; i++) {
8095 if (freqs[i] == freq)
8096 return;
8097 }
8098
8099 freqs[*num_freqs] = freq;
8100 (*num_freqs)++;
8101}
8102
8103
8104static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8105{
8106 struct wpa_bss *bss, *cbss;
8107 const int max_freqs = 10;
8108 int *freqs;
8109 int num_freqs = 0;
8110
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008111 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008112 if (freqs == NULL)
8113 return NULL;
8114
8115 cbss = wpa_s->current_bss;
8116
8117 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8118 if (bss == cbss)
8119 continue;
8120 if (bss->ssid_len == cbss->ssid_len &&
8121 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008122 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008123 add_freq(freqs, &num_freqs, bss->freq);
8124 if (num_freqs == max_freqs)
8125 break;
8126 }
8127 }
8128
8129 if (num_freqs == 0) {
8130 os_free(freqs);
8131 freqs = NULL;
8132 }
8133
8134 return freqs;
8135}
8136
8137
8138void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8139{
8140 int timeout;
8141 int count;
8142 int *freqs = NULL;
8143
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008144 wpas_connect_work_done(wpa_s);
8145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008146 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008147 * Remove possible authentication timeout since the connection failed.
8148 */
8149 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8150
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008151 /*
Hai Shalom60840252021-02-19 19:02:11 -08008152 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008153 * generated based on local request to disconnect.
8154 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008155 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008156 wpa_s->own_disconnect_req = 0;
8157 wpa_dbg(wpa_s, MSG_DEBUG,
8158 "Ignore connection failure due to local request to disconnect");
8159 return;
8160 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008161 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008162 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8163 "indication since interface has been put into "
8164 "disconnected state");
8165 return;
8166 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008167 if (wpa_s->auto_reconnect_disabled) {
8168 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8169 "indication since auto connect is disabled");
8170 return;
8171 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008172
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008173 /*
Hai Shalom60840252021-02-19 19:02:11 -08008174 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008175 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008176 */
Hai Shalom60840252021-02-19 19:02:11 -08008177 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008178 if (count == 1 && wpa_s->current_bss) {
8179 /*
Hai Shalom60840252021-02-19 19:02:11 -08008180 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008181 * another BSS available for the same ESS, we should try that
8182 * next. Otherwise, we may as well try this one once more
8183 * before allowing other, likely worse, ESSes to be considered.
8184 */
8185 freqs = get_bss_freqs_in_ess(wpa_s);
8186 if (freqs) {
8187 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8188 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008189 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008190 /*
8191 * On the next scan, go through only the known channels
8192 * used in this ESS based on previous scans to speed up
8193 * common load balancing use case.
8194 */
8195 os_free(wpa_s->next_scan_freqs);
8196 wpa_s->next_scan_freqs = freqs;
8197 }
8198 }
8199
Hai Shalom899fcc72020-10-19 14:38:18 -07008200 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008201
Hai Shalom899fcc72020-10-19 14:38:18 -07008202 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008203 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8204 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008205 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008206 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008207 /*
8208 * Multiple consecutive connection failures mean that other APs are
8209 * either not available or have already been tried, so we can start
8210 * increasing the delay here to avoid constant scanning.
8211 */
8212 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008213 case 1:
8214 timeout = 100;
8215 break;
8216 case 2:
8217 timeout = 500;
8218 break;
8219 case 3:
8220 timeout = 1000;
8221 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008222 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008223 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008224 break;
8225 default:
8226 timeout = 10000;
8227 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008228 }
8229
Hai Shalom899fcc72020-10-19 14:38:18 -07008230 wpa_dbg(wpa_s, MSG_DEBUG,
8231 "Consecutive connection failures: %d --> request scan in %d ms",
8232 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008234 /*
8235 * TODO: if more than one possible AP is available in scan results,
8236 * could try the other ones before requesting a new scan.
8237 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008238
8239 /* speed up the connection attempt with normal scan */
8240 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008241 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8242 1000 * (timeout % 1000));
8243}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008244
8245
Hai Shalomce48b4a2018-09-05 11:41:35 -07008246#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008247
8248void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8249{
8250 struct wpa_ssid *ssid = wpa_s->current_ssid;
8251 const u8 *realm, *username, *rrk;
8252 size_t realm_len, username_len, rrk_len;
8253 u16 next_seq_num;
8254
8255 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8256 * Check for ERP keys existing to limit when this can be done since
8257 * the rejection response is not protected and such triggers should
8258 * really not allow internal state to be modified unless required to
8259 * avoid significant issues in functionality. In addition, drop
8260 * externally configure PMKSA entries even without ERP keys since it
8261 * is possible for an external component to add PMKSA entries for FILS
8262 * authentication without restoring previously generated ERP keys.
8263 *
8264 * In this case, this is needed to allow recovery from cases where the
8265 * AP or authentication server has dropped PMKSAs and ERP keys. */
8266 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8267 return;
8268
8269 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8270 &username, &username_len,
8271 &realm, &realm_len, &next_seq_num,
8272 &rrk, &rrk_len) != 0 ||
8273 !realm) {
8274 wpa_dbg(wpa_s, MSG_DEBUG,
8275 "FILS: Drop external PMKSA cache entry");
8276 wpa_sm_aborted_external_cached(wpa_s->wpa);
8277 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8278 return;
8279 }
8280
8281 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8282 wpa_sm_aborted_cached(wpa_s->wpa);
8283 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8284}
8285
8286
Hai Shalomce48b4a2018-09-05 11:41:35 -07008287void fils_connection_failure(struct wpa_supplicant *wpa_s)
8288{
8289 struct wpa_ssid *ssid = wpa_s->current_ssid;
8290 const u8 *realm, *username, *rrk;
8291 size_t realm_len, username_len, rrk_len;
8292 u16 next_seq_num;
8293
8294 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8295 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8296 &username, &username_len,
8297 &realm, &realm_len, &next_seq_num,
8298 &rrk, &rrk_len) != 0 ||
8299 !realm)
8300 return;
8301
8302 wpa_hexdump_ascii(MSG_DEBUG,
8303 "FILS: Store last connection failure realm",
8304 realm, realm_len);
8305 os_free(wpa_s->last_con_fail_realm);
8306 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8307 if (wpa_s->last_con_fail_realm) {
8308 wpa_s->last_con_fail_realm_len = realm_len;
8309 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8310 }
8311}
8312#endif /* CONFIG_FILS */
8313
8314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008315int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8316{
8317 return wpa_s->conf->ap_scan == 2 ||
8318 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8319}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008320
Dmitry Shmidt04949592012-07-19 12:16:46 -07008321
Gabriel Biren57ededa2021-09-03 16:08:50 +00008322#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008323int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8324 struct wpa_ssid *ssid,
8325 const char *field,
8326 const char *value)
8327{
8328#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008329 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008330
8331 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8332 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8333 (const u8 *) value, os_strlen(value));
8334
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008335 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008336 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008337#else /* IEEE8021X_EAPOL */
8338 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8339 return -1;
8340#endif /* IEEE8021X_EAPOL */
8341}
8342
8343int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8344 struct wpa_ssid *ssid,
8345 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008346 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008347{
8348#ifdef IEEE8021X_EAPOL
8349 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008350 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008351
8352 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008353 case WPA_CTRL_REQ_EAP_IDENTITY:
8354 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008355 os_free(eap->imsi_identity);
8356 if (value == NULL)
8357 return -1;
8358 identity = os_strchr(value, ':');
8359 if (identity == NULL) {
8360 /* plain identity */
8361 eap->identity = (u8 *)os_strdup(value);
8362 eap->identity_len = os_strlen(value);
8363 } else {
8364 /* have both plain identity and encrypted identity */
8365 imsi_identity = value;
8366 *identity++ = '\0';
8367 /* plain identity */
8368 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8369 eap->imsi_identity_len = strlen(imsi_identity);
8370 /* encrypted identity */
8371 eap->identity = (u8 *)dup_binstr(identity,
8372 value_len - strlen(imsi_identity) - 1);
8373 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8374 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008375 eap->pending_req_identity = 0;
8376 if (ssid == wpa_s->current_ssid)
8377 wpa_s->reassociate = 1;
8378 break;
8379 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008380 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008381 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008382 if (!eap->password)
8383 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008384 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008385 eap->pending_req_password = 0;
8386 if (ssid == wpa_s->current_ssid)
8387 wpa_s->reassociate = 1;
8388 break;
8389 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008390 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008391 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008392 if (!eap->new_password)
8393 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008394 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008395 eap->pending_req_new_password = 0;
8396 if (ssid == wpa_s->current_ssid)
8397 wpa_s->reassociate = 1;
8398 break;
8399 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008400 str_clear_free(eap->cert.pin);
8401 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008402 if (!eap->cert.pin)
8403 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008404 eap->pending_req_pin = 0;
8405 if (ssid == wpa_s->current_ssid)
8406 wpa_s->reassociate = 1;
8407 break;
8408 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008409 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008410 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008411 if (!eap->otp)
8412 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008413 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008414 os_free(eap->pending_req_otp);
8415 eap->pending_req_otp = NULL;
8416 eap->pending_req_otp_len = 0;
8417 break;
8418 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008419 str_clear_free(eap->cert.private_key_passwd);
8420 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008421 if (!eap->cert.private_key_passwd)
8422 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008423 eap->pending_req_passphrase = 0;
8424 if (ssid == wpa_s->current_ssid)
8425 wpa_s->reassociate = 1;
8426 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008427 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008428 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008429 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008430 if (!eap->external_sim_resp)
8431 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008432 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008433 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008434 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8435 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8436 return -1;
8437 ssid->mem_only_psk = 1;
8438 if (ssid->passphrase)
8439 wpa_config_update_psk(ssid);
8440 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8441 wpa_supplicant_req_scan(wpa_s, 0, 0);
8442 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008443 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8444 if (eap->pending_ext_cert_check != PENDING_CHECK)
8445 return -1;
8446 if (os_strcmp(value, "good") == 0)
8447 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8448 else if (os_strcmp(value, "bad") == 0)
8449 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8450 else
8451 return -1;
8452 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008453 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008454 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008455 return -1;
8456 }
8457
8458 return 0;
8459#else /* IEEE8021X_EAPOL */
8460 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8461 return -1;
8462#endif /* IEEE8021X_EAPOL */
8463}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008464#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008465
8466
8467int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8468{
Hai Shalomfdcde762020-04-02 11:19:20 -07008469#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008470 int i;
8471 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008472#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008473
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008474 if (wpa_s->p2p_mgmt)
8475 return 1; /* no normal network profiles on p2p_mgmt interface */
8476
Dmitry Shmidt04949592012-07-19 12:16:46 -07008477 if (ssid == NULL)
8478 return 1;
8479
8480 if (ssid->disabled)
8481 return 1;
8482
Hai Shalomfdcde762020-04-02 11:19:20 -07008483#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008484 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008485 drv_enc = wpa_s->drv_enc;
8486 else
8487 drv_enc = (unsigned int) -1;
8488
8489 for (i = 0; i < NUM_WEP_KEYS; i++) {
8490 size_t len = ssid->wep_key_len[i];
8491 if (len == 0)
8492 continue;
8493 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8494 continue;
8495 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8496 continue;
8497 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8498 continue;
8499 return 1; /* invalid WEP key */
8500 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008501#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008502
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008503 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008504 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008505 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008506 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008507 return 1;
8508
Sunil Ravi89eba102022-09-13 21:04:37 -07008509#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008510#ifdef CRYPTO_RSA_OAEP_SHA256
8511 if (ssid->eap.imsi_privacy_cert) {
8512 struct crypto_rsa_key *key;
8513 bool failed = false;
8514
8515 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8516 if (!key)
8517 failed = true;
8518 crypto_rsa_key_free(key);
8519 if (failed) {
8520 wpa_printf(MSG_DEBUG,
8521 "Invalid imsi_privacy_cert (%s) - disable network",
8522 ssid->eap.imsi_privacy_cert);
8523 return 1;
8524 }
8525 }
8526#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008527#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008528
Dmitry Shmidt04949592012-07-19 12:16:46 -07008529 return 0;
8530}
8531
8532
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008533int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8534{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008535 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8536 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8537 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8538 /*
8539 * Driver does not support BIP -- ignore pmf=1 default
8540 * since the connection with PMF would fail and the
8541 * configuration does not require PMF to be enabled.
8542 */
8543 return NO_MGMT_FRAME_PROTECTION;
8544 }
8545
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008546 if (ssid &&
8547 (ssid->key_mgmt &
8548 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8549 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8550 /*
8551 * Do not use the default PMF value for non-RSN networks
8552 * since PMF is available only with RSN and pmf=2
8553 * configuration would otherwise prevent connections to
8554 * all open networks.
8555 */
8556 return NO_MGMT_FRAME_PROTECTION;
8557 }
8558
Sunil Ravi77d572f2023-01-17 23:58:31 +00008559#ifdef CONFIG_OCV
8560 /* Enable PMF if OCV is being enabled */
8561 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8562 ssid && ssid->ocv)
8563 return MGMT_FRAME_PROTECTION_OPTIONAL;
8564#endif /* CONFIG_OCV */
8565
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008566 return wpa_s->conf->pmf;
8567 }
8568
8569 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008570}
8571
8572
Sunil Ravi77d572f2023-01-17 23:58:31 +00008573#ifdef CONFIG_SAE
8574bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8575 struct wpa_ssid *ssid,
8576 const struct wpa_ie_data *ie)
8577{
8578 return wpa_s->conf->sae_check_mfp &&
8579 (!(ie->capabilities &
8580 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8581 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8582}
8583#endif /* CONFIG_SAE */
8584
8585
Hai Shalomc1a21442022-02-04 13:43:00 -08008586int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8587{
8588 if (wpa_s->current_ssid == NULL ||
8589 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8590 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8591 return 0;
8592 return wpa_sm_pmf_enabled(wpa_s->wpa);
8593}
8594
8595
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008596int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008597{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008598 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008599 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008600 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008601 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008602 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008603}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008604
8605
Sunil Ravi77d572f2023-01-17 23:58:31 +00008606void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8607 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008608{
8609 struct wpa_ssid *ssid = wpa_s->current_ssid;
8610 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008611 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008612
8613 if (ssid == NULL) {
8614 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8615 "SSID block");
8616 return;
8617 }
8618
8619 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8620 return;
8621
8622 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008623
8624#ifdef CONFIG_P2P
8625 if (ssid->p2p_group &&
8626 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8627 /*
8628 * Skip the wait time since there is a short timeout on the
8629 * connection to a P2P group.
8630 */
8631 return;
8632 }
8633#endif /* CONFIG_P2P */
8634
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008635 if (ssid->auth_failures > 50)
8636 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008637 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008638 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008639 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008640 dur = 90;
8641 else if (ssid->auth_failures > 3)
8642 dur = 60;
8643 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008644 dur = 30;
8645 else if (ssid->auth_failures > 1)
8646 dur = 20;
8647 else
8648 dur = 10;
8649
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008650 if (ssid->auth_failures > 1 &&
8651 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8652 dur += os_random() % (ssid->auth_failures * 10);
8653
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008654 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008655 if (now.sec + dur <= ssid->disabled_until.sec)
8656 return;
8657
8658 ssid->disabled_until.sec = now.sec + dur;
8659
8660 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008661 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008662 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008663 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008664
8665 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8666 int msg_len = snprintf(NULL, 0, format_str,
8667 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8668 ssid->auth_failures, dur, reason) + 1;
8669 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308670 if (!msg)
8671 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008672 snprintf(msg, msg_len, format_str,
8673 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8674 ssid->auth_failures, dur, reason);
8675 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8676 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008677
8678 if (bssid)
8679 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008680}
8681
8682
8683void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8684 struct wpa_ssid *ssid, int clear_failures)
8685{
8686 if (ssid == NULL)
8687 return;
8688
8689 if (ssid->disabled_until.sec) {
8690 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8691 "id=%d ssid=\"%s\"",
8692 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8693 }
8694 ssid->disabled_until.sec = 0;
8695 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008696 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008697 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008698 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8699 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8700 " ignored to allow a lower priority BSS, if any, to be tried next",
8701 MAC2STR(ssid->disabled_due_to));
8702 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8703 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8704 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008705}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008706
8707
8708int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8709{
8710 size_t i;
8711
8712 if (wpa_s->disallow_aps_bssid == NULL)
8713 return 0;
8714
8715 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8716 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8717 bssid, ETH_ALEN) == 0)
8718 return 1;
8719 }
8720
8721 return 0;
8722}
8723
8724
8725int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8726 size_t ssid_len)
8727{
8728 size_t i;
8729
8730 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8731 return 0;
8732
8733 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8734 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8735 if (ssid_len == s->ssid_len &&
8736 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8737 return 1;
8738 }
8739
8740 return 0;
8741}
8742
8743
8744/**
8745 * wpas_request_connection - Request a new connection
8746 * @wpa_s: Pointer to the network interface
8747 *
8748 * This function is used to request a new connection to be found. It will mark
8749 * the interface to allow reassociation and request a new scan to find a
8750 * suitable network to connect to.
8751 */
8752void wpas_request_connection(struct wpa_supplicant *wpa_s)
8753{
8754 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008755 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008756 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008757 wpa_s->disconnected = 0;
8758 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008759 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008760
8761 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8762 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008763 else
8764 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008765}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008766
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008767
Roshan Pius02242d72016-08-09 15:31:48 -07008768/**
8769 * wpas_request_disconnection - Request disconnection
8770 * @wpa_s: Pointer to the network interface
8771 *
8772 * This function is used to request disconnection from the currently connected
8773 * network. This will stop any ongoing scans and initiate deauthentication.
8774 */
8775void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8776{
8777#ifdef CONFIG_SME
8778 wpa_s->sme.prev_bssid_set = 0;
8779#endif /* CONFIG_SME */
8780 wpa_s->reassociate = 0;
8781 wpa_s->disconnected = 1;
8782 wpa_supplicant_cancel_sched_scan(wpa_s);
8783 wpa_supplicant_cancel_scan(wpa_s);
8784 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8785 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008786 radio_remove_works(wpa_s, "connect", 0);
8787 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008788 wpa_s->roam_in_progress = false;
8789#ifdef CONFIG_WNM
8790 wpa_s->bss_trans_mgmt_in_progress = false;
8791#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008792}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008793
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008794
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008795void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8796 struct wpa_used_freq_data *freqs_data,
8797 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008798{
8799 unsigned int i;
8800
8801 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8802 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008803 for (i = 0; i < len; i++) {
8804 struct wpa_used_freq_data *cur = &freqs_data[i];
8805 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8806 i, cur->freq, cur->flags);
8807 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008808}
8809
8810
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008811/*
8812 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008813 * are using the same radio as the current interface, and in addition, get
8814 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008815 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008816int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8817 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008818 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008819{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008820 struct wpa_supplicant *ifs;
8821 u8 bssid[ETH_ALEN];
8822 int freq;
8823 unsigned int idx = 0, i;
8824
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008825 wpa_dbg(wpa_s, MSG_DEBUG,
8826 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008827 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008828
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008829 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8830 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008831 if (idx == len)
8832 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008833
Sunil Ravi77d572f2023-01-17 23:58:31 +00008834 if (exclude_current && ifs == wpa_s)
8835 continue;
8836
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008837 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8838 continue;
8839
8840 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008841 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8842 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008843 freq = ifs->current_ssid->frequency;
8844 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8845 freq = ifs->assoc_freq;
8846 else
8847 continue;
8848
8849 /* Hold only distinct freqs */
8850 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008851 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008852 break;
8853
8854 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008855 freqs_data[idx++].freq = freq;
8856
8857 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008858 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008859 WPA_FREQ_USED_BY_P2P_CLIENT :
8860 WPA_FREQ_USED_BY_INFRA_STATION;
8861 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008862 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008863
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008864 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008865 return idx;
8866}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008867
8868
8869/*
8870 * Find the operating frequencies of any of the virtual interfaces that
8871 * are using the same radio as the current interface.
8872 */
8873int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008874 int *freq_array, unsigned int len,
8875 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008876{
8877 struct wpa_used_freq_data *freqs_data;
8878 int num, i;
8879
8880 os_memset(freq_array, 0, sizeof(int) * len);
8881
8882 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8883 if (!freqs_data)
8884 return -1;
8885
Sunil Ravi77d572f2023-01-17 23:58:31 +00008886 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8887 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008888 for (i = 0; i < num; i++)
8889 freq_array[i] = freqs_data[i].freq;
8890
8891 os_free(freqs_data);
8892
8893 return num;
8894}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008895
8896
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008897struct wpa_supplicant *
8898wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8899{
8900 switch (frame) {
8901#ifdef CONFIG_P2P
8902 case VENDOR_ELEM_PROBE_REQ_P2P:
8903 case VENDOR_ELEM_PROBE_RESP_P2P:
8904 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8905 case VENDOR_ELEM_BEACON_P2P_GO:
8906 case VENDOR_ELEM_P2P_PD_REQ:
8907 case VENDOR_ELEM_P2P_PD_RESP:
8908 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8909 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8910 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8911 case VENDOR_ELEM_P2P_INV_REQ:
8912 case VENDOR_ELEM_P2P_INV_RESP:
8913 case VENDOR_ELEM_P2P_ASSOC_REQ:
8914 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008915 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008916#endif /* CONFIG_P2P */
8917 default:
8918 return wpa_s;
8919 }
8920}
8921
8922
8923void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8924{
8925 unsigned int i;
8926 char buf[30];
8927
8928 wpa_printf(MSG_DEBUG, "Update vendor elements");
8929
8930 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8931 if (wpa_s->vendor_elem[i]) {
8932 int res;
8933
8934 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8935 if (!os_snprintf_error(sizeof(buf), res)) {
8936 wpa_hexdump_buf(MSG_DEBUG, buf,
8937 wpa_s->vendor_elem[i]);
8938 }
8939 }
8940 }
8941
8942#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008943 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008944 wpa_s->global->p2p &&
8945 !wpa_s->global->p2p_disabled)
8946 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8947#endif /* CONFIG_P2P */
8948}
8949
8950
8951int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8952 const u8 *elem, size_t len)
8953{
8954 u8 *ie, *end;
8955
8956 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8957 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8958
8959 for (; ie + 1 < end; ie += 2 + ie[1]) {
8960 if (ie + len > end)
8961 break;
8962 if (os_memcmp(ie, elem, len) != 0)
8963 continue;
8964
8965 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8966 wpabuf_free(wpa_s->vendor_elem[frame]);
8967 wpa_s->vendor_elem[frame] = NULL;
8968 } else {
8969 os_memmove(ie, ie + len, end - (ie + len));
8970 wpa_s->vendor_elem[frame]->used -= len;
8971 }
8972 wpas_vendor_elem_update(wpa_s);
8973 return 0;
8974 }
8975
8976 return -1;
8977}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008978
8979
8980struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008981 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008982 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008983{
8984 u16 i;
8985
Hai Shalomc1a21442022-02-04 13:43:00 -08008986 if (!modes)
8987 return NULL;
8988
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008989 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008990 if (modes[i].mode != mode ||
8991 !modes[i].num_channels || !modes[i].channels)
8992 continue;
8993 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8994 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008995 return &modes[i];
8996 }
8997
8998 return NULL;
8999}
9000
9001
Hai Shalomc1a21442022-02-04 13:43:00 -08009002struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
9003 u16 num_modes, int freq)
9004{
9005 int i, j;
9006
9007 for (i = 0; i < num_modes; i++) {
9008 for (j = 0; j < modes[i].num_channels; j++) {
9009 if (freq == modes[i].channels[j].freq)
9010 return &modes[i];
9011 }
9012 }
9013
9014 return NULL;
9015}
9016
9017
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009018static struct
9019wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
9020 const u8 *bssid)
9021{
9022 struct wpa_bss_tmp_disallowed *bss;
9023
9024 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
9025 struct wpa_bss_tmp_disallowed, list) {
9026 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
9027 return bss;
9028 }
9029
9030 return NULL;
9031}
9032
9033
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009034static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
9035{
9036 struct wpa_bss_tmp_disallowed *tmp;
9037 unsigned int num_bssid = 0;
9038 u8 *bssids;
9039 int ret;
9040
9041 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9042 if (!bssids)
9043 return -1;
9044 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9045 struct wpa_bss_tmp_disallowed, list) {
9046 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9047 ETH_ALEN);
9048 num_bssid++;
9049 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009050 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009051 os_free(bssids);
9052 return ret;
9053}
9054
9055
9056static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9057{
9058 struct wpa_supplicant *wpa_s = eloop_ctx;
9059 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9060
9061 /* Make sure the bss is not already freed */
9062 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9063 struct wpa_bss_tmp_disallowed, list) {
9064 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009065 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009066 wpa_set_driver_tmp_disallow_list(wpa_s);
9067 break;
9068 }
9069 }
9070}
9071
9072
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009073void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009074 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009075{
9076 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009077
9078 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9079 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009080 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009081 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009082 }
9083
9084 bss = os_malloc(sizeof(*bss));
9085 if (!bss) {
9086 wpa_printf(MSG_DEBUG,
9087 "Failed to allocate memory for temp disallow BSS");
9088 return;
9089 }
9090
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009091 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9092 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009093 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009094
9095finish:
9096 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009097 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9098 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009099}
9100
9101
Hai Shalom74f70d42019-02-11 14:42:39 -08009102int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9103 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009104{
Hai Shalom74f70d42019-02-11 14:42:39 -08009105 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009106
9107 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9108 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009109 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9110 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009111 break;
9112 }
9113 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009114 if (!disallowed)
9115 return 0;
9116
9117 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009118 bss->level > disallowed->rssi_threshold) {
9119 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9120 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009121 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009122 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009123
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009124 return 1;
9125}
Hai Shalom81f62d82019-07-22 12:10:00 -07009126
9127
9128int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9129 unsigned int type, const u8 *addr,
9130 const u8 *mask)
9131{
9132 if ((addr && !mask) || (!addr && mask)) {
9133 wpa_printf(MSG_INFO,
9134 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9135 return -1;
9136 }
9137
9138 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9139 wpa_printf(MSG_INFO,
9140 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9141 return -1;
9142 }
9143
9144 if (type & MAC_ADDR_RAND_SCAN) {
9145 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9146 addr, mask))
9147 return -1;
9148 }
9149
9150 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9151 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9152 addr, mask))
9153 return -1;
9154
9155 if (wpa_s->sched_scanning && !wpa_s->pno)
9156 wpas_scan_restart_sched_scan(wpa_s);
9157 }
9158
9159 if (type & MAC_ADDR_RAND_PNO) {
9160 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9161 addr, mask))
9162 return -1;
9163
9164 if (wpa_s->pno) {
9165 wpas_stop_pno(wpa_s);
9166 wpas_start_pno(wpa_s);
9167 }
9168 }
9169
9170 return 0;
9171}
9172
9173
9174int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9175 unsigned int type)
9176{
9177 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9178 if (wpa_s->pno) {
9179 if (type & MAC_ADDR_RAND_PNO) {
9180 wpas_stop_pno(wpa_s);
9181 wpas_start_pno(wpa_s);
9182 }
9183 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9184 wpas_scan_restart_sched_scan(wpa_s);
9185 }
9186
9187 return 0;
9188}
Hai Shalomfdcde762020-04-02 11:19:20 -07009189
9190
9191int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9192 struct wpa_signal_info *si)
9193{
9194 int res;
9195
9196 if (!wpa_s->driver->signal_poll)
9197 return -1;
9198
9199 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9200
9201#ifdef CONFIG_TESTING_OPTIONS
9202 if (res == 0) {
9203 struct driver_signal_override *dso;
9204
9205 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9206 struct driver_signal_override, list) {
9207 if (os_memcmp(wpa_s->bssid, dso->bssid,
9208 ETH_ALEN) != 0)
9209 continue;
9210 wpa_printf(MSG_DEBUG,
9211 "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 +00009212 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009213 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009214 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009215 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009216 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009217 dso->si_avg_beacon_signal,
9218 si->current_noise,
9219 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009220 si->data.signal = dso->si_current_signal;
9221 si->data.avg_signal = dso->si_avg_signal;
9222 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009223 si->current_noise = dso->si_current_noise;
9224 break;
9225 }
9226 }
9227#endif /* CONFIG_TESTING_OPTIONS */
9228
9229 return res;
9230}
9231
9232
9233struct wpa_scan_results *
9234wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9235{
9236 struct wpa_scan_results *scan_res;
9237#ifdef CONFIG_TESTING_OPTIONS
9238 size_t idx;
9239#endif /* CONFIG_TESTING_OPTIONS */
9240
9241 if (!wpa_s->driver->get_scan_results2)
9242 return NULL;
9243
9244 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9245
9246#ifdef CONFIG_TESTING_OPTIONS
9247 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9248 struct driver_signal_override *dso;
9249 struct wpa_scan_res *res = scan_res->res[idx];
9250
9251 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9252 struct driver_signal_override, list) {
9253 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9254 continue;
9255 wpa_printf(MSG_DEBUG,
9256 "Override driver scan signal level %d->%d for "
9257 MACSTR,
9258 res->level, dso->scan_level,
9259 MAC2STR(res->bssid));
9260 res->flags |= WPA_SCAN_QUAL_INVALID;
9261 if (dso->scan_level < 0)
9262 res->flags |= WPA_SCAN_LEVEL_DBM;
9263 else
9264 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9265 res->level = dso->scan_level;
9266 break;
9267 }
9268 }
9269#endif /* CONFIG_TESTING_OPTIONS */
9270
9271 return scan_res;
9272}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009273
9274
9275static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9276{
9277 int i;
9278
9279 if (!wpa_s->valid_links)
9280 return false;
9281
9282 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9283 if (!(wpa_s->valid_links & BIT(i)))
9284 continue;
9285
9286 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9287 return true;
9288 }
9289
9290 return false;
9291}
9292
9293
9294int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9295 unsigned int wait, const u8 *dst, const u8 *src,
9296 const u8 *bssid, const u8 *data, size_t data_len,
9297 int no_cck)
9298{
9299 if (!wpa_s->driver->send_action)
9300 return -1;
9301
9302 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9303 if (wpas_ap_link_address(wpa_s, dst))
9304 dst = wpa_s->ap_mld_addr;
9305
9306 if (wpas_ap_link_address(wpa_s, bssid))
9307 bssid = wpa_s->ap_mld_addr;
9308 }
9309
9310 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9311 bssid, data, data_len, no_cck);
9312}