blob: 521ff901b5d7766ea95693ff95afa58dd3281441 [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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080075"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070077const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080078"This software may be distributed under the terms of the BSD license.\n"
79"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080#ifdef EAP_TLS_OPENSSL
81"\nThis product includes software developed by the OpenSSL Project\n"
82"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
83#endif /* EAP_TLS_OPENSSL */
84;
85
86#ifndef CONFIG_NO_STDOUT_DEBUG
87/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070088const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080089"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080091"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070092"\n"
93"Redistribution and use in source and binary forms, with or without\n"
94"modification, are permitted provided that the following conditions are\n"
95"met:\n"
96"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070097const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098"1. Redistributions of source code must retain the above copyright\n"
99" notice, this list of conditions and the following disclaimer.\n"
100"\n"
101"2. Redistributions in binary form must reproduce the above copyright\n"
102" notice, this list of conditions and the following disclaimer in the\n"
103" documentation and/or other materials provided with the distribution.\n"
104"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700105const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
107" names of its contributors may be used to endorse or promote products\n"
108" derived from this software without specific prior written permission.\n"
109"\n"
110"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
111"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
112"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
113"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700114const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
116"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
117"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
118"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
119"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
120"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
121"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
122"\n";
123#endif /* CONFIG_NO_STDOUT_DEBUG */
124
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700125
126static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
127#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
128static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
129#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700130#ifdef CONFIG_OWE
131static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
132#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700133
134
Hai Shalomfdcde762020-04-02 11:19:20 -0700135#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136/* Configure default/group WEP keys for static WEP */
137int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
138{
139 int i, set = 0;
140
141 for (i = 0; i < NUM_WEP_KEYS; i++) {
142 if (ssid->wep_key_len[i] == 0)
143 continue;
144
145 set = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000146 wpa_drv_set_key(wpa_s, -1, WPA_ALG_WEP, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700147 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700148 ssid->wep_key[i], ssid->wep_key_len[i],
149 i == ssid->wep_tx_keyidx ?
150 KEY_FLAG_GROUP_RX_TX_DEFAULT :
151 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700152 }
153
154 return set;
155}
Hai Shalomfdcde762020-04-02 11:19:20 -0700156#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700157
158
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700159int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
160 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161{
162 u8 key[32];
163 size_t keylen;
164 enum wpa_alg alg;
165 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800166 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167
168 /* IBSS/WPA-None uses only one key (Group) for both receiving and
169 * sending unicast and multicast packets. */
170
171 if (ssid->mode != WPAS_MODE_IBSS) {
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
173 "IBSS/ad-hoc) for WPA-None", ssid->mode);
174 return -1;
175 }
176
177 if (!ssid->psk_set) {
178 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
179 "WPA-None");
180 return -1;
181 }
182
183 switch (wpa_s->group_cipher) {
184 case WPA_CIPHER_CCMP:
185 os_memcpy(key, ssid->psk, 16);
186 keylen = 16;
187 alg = WPA_ALG_CCMP;
188 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700189 case WPA_CIPHER_GCMP:
190 os_memcpy(key, ssid->psk, 16);
191 keylen = 16;
192 alg = WPA_ALG_GCMP;
193 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194 case WPA_CIPHER_TKIP:
195 /* WPA-None uses the same Michael MIC key for both TX and RX */
196 os_memcpy(key, ssid->psk, 16 + 8);
197 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
198 keylen = 32;
199 alg = WPA_ALG_TKIP;
200 break;
201 default:
202 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
203 "WPA-None", wpa_s->group_cipher);
204 return -1;
205 }
206
207 /* TODO: should actually remember the previously used seq#, both for TX
208 * and RX from each STA.. */
209
Sunil Ravi77d572f2023-01-17 23:58:31 +0000210 ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
Hai Shalomfdcde762020-04-02 11:19:20 -0700211 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800212 os_memset(key, 0, sizeof(key));
213 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214}
215
216
217static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
218{
219 struct wpa_supplicant *wpa_s = eloop_ctx;
220 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700221 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
222 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
223 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224 bssid = wpa_s->pending_bssid;
225 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
226 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800227 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700228 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800230 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 wpa_s->reassociate = 1;
232
233 /*
234 * If we timed out, the AP or the local radio may be busy.
235 * So, wait a second until scanning again.
236 */
237 wpa_supplicant_req_scan(wpa_s, 1, 0);
238}
239
240
241/**
242 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
243 * @wpa_s: Pointer to wpa_supplicant data
244 * @sec: Number of seconds after which to time out authentication
245 * @usec: Number of microseconds after which to time out authentication
246 *
247 * This function is used to schedule a timeout for the current authentication
248 * attempt.
249 */
250void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
251 int sec, int usec)
252{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700253 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
255 return;
256
257 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
258 "%d usec", sec, usec);
259 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700260 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
262}
263
264
Roshan Pius3a1667e2018-07-03 15:17:14 -0700265/*
266 * wpas_auth_timeout_restart - Restart and change timeout for authentication
267 * @wpa_s: Pointer to wpa_supplicant data
268 * @sec_diff: difference in seconds applied to original timeout value
269 */
270void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
271{
272 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
273
274 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
275 wpa_dbg(wpa_s, MSG_DEBUG,
276 "Authentication timeout restart: %d sec", new_sec);
277 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
278 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
279 wpa_s, NULL);
280 }
281}
282
283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284/**
285 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
286 * @wpa_s: Pointer to wpa_supplicant data
287 *
288 * This function is used to cancel authentication timeout scheduled with
289 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
290 * been completed.
291 */
292void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
293{
294 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
295 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800296 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700297 os_free(wpa_s->last_con_fail_realm);
298 wpa_s->last_con_fail_realm = NULL;
299 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300}
301
302
303/**
304 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
305 * @wpa_s: Pointer to wpa_supplicant data
306 *
307 * This function is used to configure EAPOL state machine based on the selected
308 * authentication mode.
309 */
310void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
311{
312#ifdef IEEE8021X_EAPOL
313 struct eapol_config eapol_conf;
314 struct wpa_ssid *ssid = wpa_s->current_ssid;
315
316#ifdef CONFIG_IBSS_RSN
317 if (ssid->mode == WPAS_MODE_IBSS &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
319 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
320 /*
321 * RSN IBSS authentication is per-STA and we can disable the
322 * per-BSSID EAPOL authentication.
323 */
324 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700325 eapol_sm_notify_eap_success(wpa_s->eapol, true);
326 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327 return;
328 }
329#endif /* CONFIG_IBSS_RSN */
330
Hai Shalome21d4e82020-04-29 16:34:06 -0700331 eapol_sm_notify_eap_success(wpa_s->eapol, false);
332 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
335 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
336 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
337 else
338 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
339
340 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
341 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
342 eapol_conf.accept_802_1x_keys = 1;
343 eapol_conf.required_keys = 0;
344 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
345 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
346 }
347 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
348 eapol_conf.required_keys |=
349 EAPOL_REQUIRE_KEY_BROADCAST;
350 }
351
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700352 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353 eapol_conf.required_keys = 0;
354 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700355 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356 eapol_conf.workaround = ssid->eap_workaround;
357 eapol_conf.eap_disabled =
358 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
360 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700361 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800362
363#ifdef CONFIG_WPS
364 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
365 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
366 if (wpa_s->current_bss) {
367 struct wpabuf *ie;
368 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
369 WPS_IE_VENDOR_TYPE);
370 if (ie) {
371 if (wps_is_20(ie))
372 eapol_conf.wps |=
373 EAPOL_PEER_IS_WPS20_AP;
374 wpabuf_free(ie);
375 }
376 }
377 }
378#endif /* CONFIG_WPS */
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700381
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800382#ifdef CONFIG_MACSEC
383 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
384 ieee802_1x_create_preshared_mka(wpa_s, ssid);
385 else
386 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
387#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800388#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389}
390
391
392/**
393 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
394 * @wpa_s: Pointer to wpa_supplicant data
395 * @ssid: Configuration data for the network
396 *
397 * This function is used to configure WPA state machine and related parameters
398 * to a mode where WPA is not enabled. This is called as part of the
399 * authentication configuration when the selected network does not use WPA.
400 */
401void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
402 struct wpa_ssid *ssid)
403{
Hai Shalomfdcde762020-04-02 11:19:20 -0700404#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700406#endif /* CONFIG_WEP */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000407 struct wpa_sm_mlo mlo;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408
409 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
410 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
411 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
412 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
413 else
414 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
415 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
416 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700417 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700419 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
420 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700421 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
422 wpa_s->group_cipher = WPA_CIPHER_NONE;
423 wpa_s->mgmt_group_cipher = 0;
424
Hai Shalomfdcde762020-04-02 11:19:20 -0700425#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700426 for (i = 0; i < NUM_WEP_KEYS; i++) {
427 if (ssid->wep_key_len[i] > 5) {
428 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
429 wpa_s->group_cipher = WPA_CIPHER_WEP104;
430 break;
431 } else if (ssid->wep_key_len[i] > 0) {
432 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
433 wpa_s->group_cipher = WPA_CIPHER_WEP40;
434 break;
435 }
436 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700437#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
442 wpa_s->pairwise_cipher);
443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
445 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700446
447 pmksa_cache_clear_current(wpa_s->wpa);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000448 os_memset(&mlo, 0, sizeof(mlo));
449 wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450}
451
452
Dmitry Shmidt04949592012-07-19 12:16:46 -0700453void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800454{
455 int i;
456 if (wpa_s->hw.modes == NULL)
457 return;
458
459 for (i = 0; i < wpa_s->hw.num_modes; i++) {
460 os_free(wpa_s->hw.modes[i].channels);
461 os_free(wpa_s->hw.modes[i].rates);
462 }
463
464 os_free(wpa_s->hw.modes);
465 wpa_s->hw.modes = NULL;
466}
467
468
Hai Shalomc1a21442022-02-04 13:43:00 -0800469static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
470 struct wpa_bss_tmp_disallowed *bss)
471{
472 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
473 dl_list_del(&bss->list);
474 os_free(bss);
475}
476
477
Hai Shalom74f70d42019-02-11 14:42:39 -0800478void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800479{
480 struct wpa_bss_tmp_disallowed *bss, *prev;
481
482 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800483 struct wpa_bss_tmp_disallowed, list)
484 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800485}
486
487
Paul Stewart092955c2017-02-06 09:13:09 -0800488void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
489{
490 struct fils_hlp_req *req;
491
492 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
493 list)) != NULL) {
494 dl_list_del(&req->list);
495 wpabuf_free(req->pkt);
496 os_free(req);
497 }
498}
499
500
Hai Shalomfdcde762020-04-02 11:19:20 -0700501void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
502{
503 struct wpa_supplicant *wpa_s = eloop_ctx;
504
505 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
506 return;
507 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
508 wpa_bss_flush(wpa_s);
509}
510
511
512#ifdef CONFIG_TESTING_OPTIONS
513void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
514{
515 struct driver_signal_override *dso;
516
517 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
518 struct driver_signal_override, list))) {
519 dl_list_del(&dso->list);
520 os_free(dso);
521 }
522}
523#endif /* CONFIG_TESTING_OPTIONS */
524
525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
527{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700528 int i;
529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700530 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700531 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532 scard_deinit(wpa_s->scard);
533 wpa_s->scard = NULL;
534 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
535 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
536 l2_packet_deinit(wpa_s->l2);
537 wpa_s->l2 = NULL;
538 if (wpa_s->l2_br) {
539 l2_packet_deinit(wpa_s->l2_br);
540 wpa_s->l2_br = NULL;
541 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800542#ifdef CONFIG_TESTING_OPTIONS
543 l2_packet_deinit(wpa_s->l2_test);
544 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800545 os_free(wpa_s->get_pref_freq_list_override);
546 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700547 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
548 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800549 os_free(wpa_s->extra_sae_rejected_groups);
550 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700551 wpabuf_free(wpa_s->rsne_override_eapol);
552 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800553 wpabuf_free(wpa_s->rsnxe_override_assoc);
554 wpa_s->rsnxe_override_assoc = NULL;
555 wpabuf_free(wpa_s->rsnxe_override_eapol);
556 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700557 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800558#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 if (wpa_s->conf != NULL) {
561 struct wpa_ssid *ssid;
562 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
563 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564 }
565
566 os_free(wpa_s->confname);
567 wpa_s->confname = NULL;
568
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700569 os_free(wpa_s->confanother);
570 wpa_s->confanother = NULL;
571
Hai Shalomce48b4a2018-09-05 11:41:35 -0700572 os_free(wpa_s->last_con_fail_realm);
573 wpa_s->last_con_fail_realm = NULL;
574 wpa_s->last_con_fail_realm_len = 0;
575
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 wpa_sm_set_eapol(wpa_s->wpa, NULL);
577 eapol_sm_deinit(wpa_s->eapol);
578 wpa_s->eapol = NULL;
579
580 rsn_preauth_deinit(wpa_s->wpa);
581
582#ifdef CONFIG_TDLS
583 wpa_tdls_deinit(wpa_s->wpa);
584#endif /* CONFIG_TDLS */
585
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800586 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800588 ptksa_cache_deinit(wpa_s->ptksa);
589 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590 wpa_sm_deinit(wpa_s->wpa);
591 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800592 wpa_bssid_ignore_clear(wpa_s);
593
594#ifdef CONFIG_PASN
595 wpas_pasn_auth_stop(wpa_s);
596#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597
598 wpa_bss_deinit(wpa_s);
599
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700600 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 wpa_supplicant_cancel_scan(wpa_s);
602 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800603 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
604#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
605 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
606 wpa_s, NULL);
607#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700609 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700610 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612 wpas_wps_deinit(wpa_s);
613
614 wpabuf_free(wpa_s->pending_eapol_rx);
615 wpa_s->pending_eapol_rx = NULL;
616
617#ifdef CONFIG_IBSS_RSN
618 ibss_rsn_deinit(wpa_s->ibss_rsn);
619 wpa_s->ibss_rsn = NULL;
620#endif /* CONFIG_IBSS_RSN */
621
622 sme_deinit(wpa_s);
623
624#ifdef CONFIG_AP
625 wpa_supplicant_ap_deinit(wpa_s);
626#endif /* CONFIG_AP */
627
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800630#ifdef CONFIG_OFFCHANNEL
631 offchannel_deinit(wpa_s);
632#endif /* CONFIG_OFFCHANNEL */
633
634 wpa_supplicant_cancel_sched_scan(wpa_s);
635
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700636 os_free(wpa_s->next_scan_freqs);
637 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800638
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800639 os_free(wpa_s->manual_scan_freqs);
640 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700641 os_free(wpa_s->select_network_scan_freqs);
642 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800643
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700644 os_free(wpa_s->manual_sched_scan_freqs);
645 wpa_s->manual_sched_scan_freqs = NULL;
646
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800647 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
648
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700649 /*
650 * Need to remove any pending gas-query radio work before the
651 * gas_query_deinit() call because gas_query::work has not yet been set
652 * for works that have not been started. gas_query_free() will be unable
653 * to cancel such pending radio works and once the pending gas-query
654 * radio work eventually gets removed, the deinit notification call to
655 * gas_query_start_cb() would result in dereferencing freed memory.
656 */
657 if (wpa_s->radio)
658 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800659 gas_query_deinit(wpa_s->gas);
660 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700661 gas_server_deinit(wpa_s->gas_server);
662 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800663
664 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700665
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700666 ieee802_1x_dealloc_kay_sm(wpa_s);
667
Dmitry Shmidt04949592012-07-19 12:16:46 -0700668 os_free(wpa_s->bssid_filter);
669 wpa_s->bssid_filter = NULL;
670
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800671 os_free(wpa_s->disallow_aps_bssid);
672 wpa_s->disallow_aps_bssid = NULL;
673 os_free(wpa_s->disallow_aps_ssid);
674 wpa_s->disallow_aps_ssid = NULL;
675
Dmitry Shmidt04949592012-07-19 12:16:46 -0700676 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700677#ifdef CONFIG_WNM
678 wnm_deallocate_memory(wpa_s);
679#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700680
681 ext_password_deinit(wpa_s->ext_pw);
682 wpa_s->ext_pw = NULL;
683
684 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800685 wpa_s->last_gas_resp = NULL;
686 wpabuf_free(wpa_s->prev_gas_resp);
687 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700688
689 os_free(wpa_s->last_scan_res);
690 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800691
692#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700693 if (wpa_s->drv_priv)
694 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700695 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800696#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700697
698 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
699 wpabuf_free(wpa_s->vendor_elem[i]);
700 wpa_s->vendor_elem[i] = NULL;
701 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800702
703 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800704
705 wpa_s->sched_scan_plans_num = 0;
706 os_free(wpa_s->sched_scan_plans);
707 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800708
709#ifdef CONFIG_MBO
710 wpa_s->non_pref_chan_num = 0;
711 os_free(wpa_s->non_pref_chan);
712 wpa_s->non_pref_chan = NULL;
713#endif /* CONFIG_MBO */
714
715 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700716
717 wpabuf_free(wpa_s->lci);
718 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800719 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800720
721#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
722#ifdef CONFIG_MESH
723 {
724 struct external_pmksa_cache *entry;
725
726 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
727 struct external_pmksa_cache,
728 list)) != NULL) {
729 dl_list_del(&entry->list);
730 os_free(entry->pmksa_cache);
731 os_free(entry);
732 }
733 }
734#endif /* CONFIG_MESH */
735#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
736
737 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800738
739 wpabuf_free(wpa_s->ric_ies);
740 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700741
742#ifdef CONFIG_DPP
743 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700744 dpp_global_deinit(wpa_s->dpp);
745 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700746#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800747
748#ifdef CONFIG_PASN
749 wpas_pasn_auth_stop(wpa_s);
750#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800751 wpas_scs_deinit(wpa_s);
752 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753}
754
755
756/**
757 * wpa_clear_keys - Clear keys configured for the driver
758 * @wpa_s: Pointer to wpa_supplicant data
759 * @addr: Previously used BSSID or %NULL if not available
760 *
761 * This function clears the encryption keys that has been previously configured
762 * for the driver.
763 */
764void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
765{
Hai Shalomc3565922019-10-28 11:58:20 -0700766 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767
768 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800769 for (i = 0; i < max; i++) {
770 if (wpa_s->keys_cleared & BIT(i))
771 continue;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000772 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700773 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800774 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700775 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
776 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800777 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700778 if (!(wpa_s->keys_cleared & BIT(0)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000779 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
780 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -0700781 if (!(wpa_s->keys_cleared & BIT(15)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000782 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
783 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 /* MLME-SETPROTECTION.request(None) */
785 wpa_drv_mlme_setprotection(
786 wpa_s, addr,
787 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
788 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
789 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800790 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791}
792
793
794/**
795 * wpa_supplicant_state_txt - Get the connection state name as a text string
796 * @state: State (wpa_state; WPA_*)
797 * Returns: The state name as a printable text string
798 */
799const char * wpa_supplicant_state_txt(enum wpa_states state)
800{
801 switch (state) {
802 case WPA_DISCONNECTED:
803 return "DISCONNECTED";
804 case WPA_INACTIVE:
805 return "INACTIVE";
806 case WPA_INTERFACE_DISABLED:
807 return "INTERFACE_DISABLED";
808 case WPA_SCANNING:
809 return "SCANNING";
810 case WPA_AUTHENTICATING:
811 return "AUTHENTICATING";
812 case WPA_ASSOCIATING:
813 return "ASSOCIATING";
814 case WPA_ASSOCIATED:
815 return "ASSOCIATED";
816 case WPA_4WAY_HANDSHAKE:
817 return "4WAY_HANDSHAKE";
818 case WPA_GROUP_HANDSHAKE:
819 return "GROUP_HANDSHAKE";
820 case WPA_COMPLETED:
821 return "COMPLETED";
822 default:
823 return "UNKNOWN";
824 }
825}
826
827
828#ifdef CONFIG_BGSCAN
829
Hai Shalom899fcc72020-10-19 14:38:18 -0700830static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
831{
832 if (wpa_s->bgscan_ssid) {
833 bgscan_deinit(wpa_s);
834 wpa_s->bgscan_ssid = NULL;
835 }
836}
837
838
839/**
840 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
841 * @wpa_s: Pointer to the wpa_supplicant data
842 *
843 * Stop, start, or reconfigure the scan parameters depending on the method.
844 */
845void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800847 const char *name;
848
849 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
850 name = wpa_s->current_ssid->bgscan;
851 else
852 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700853 if (!name || name[0] == '\0') {
854 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800855 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700856 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800857 if (wpas_driver_bss_selection(wpa_s))
858 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800859#ifdef CONFIG_P2P
860 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
861 return;
862#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863
864 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800865 if (wpa_s->current_ssid) {
866 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700867 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
868 "bgscan");
869 /*
870 * Live without bgscan; it is only used as a roaming
871 * optimization, so the initial connection is not
872 * affected.
873 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700874 } else {
875 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700877 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
878 0);
879 if (scan_res) {
880 bgscan_notify_scan(wpa_s, scan_res);
881 wpa_scan_results_free(scan_res);
882 }
883 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 } else
885 wpa_s->bgscan_ssid = NULL;
886}
887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888#endif /* CONFIG_BGSCAN */
889
890
Dmitry Shmidt04949592012-07-19 12:16:46 -0700891static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
892{
893 if (autoscan_init(wpa_s, 0))
894 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
895}
896
897
898static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
899{
900 autoscan_deinit(wpa_s);
901}
902
903
904void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
905{
906 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
907 wpa_s->wpa_state == WPA_SCANNING) {
908 autoscan_deinit(wpa_s);
909 wpa_supplicant_start_autoscan(wpa_s);
910 }
911}
912
913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914/**
915 * wpa_supplicant_set_state - Set current connection state
916 * @wpa_s: Pointer to wpa_supplicant data
917 * @state: The new connection state
918 *
919 * This function is called whenever the connection state changes, e.g.,
920 * association is completed for WPA/WPA2 4-Way Handshake is started.
921 */
922void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
923 enum wpa_states state)
924{
925 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700926#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700927 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700928#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929
930 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
931 wpa_supplicant_state_txt(wpa_s->wpa_state),
932 wpa_supplicant_state_txt(state));
933
Hai Shalom74f70d42019-02-11 14:42:39 -0800934 if (state == WPA_COMPLETED &&
935 os_reltime_initialized(&wpa_s->roam_start)) {
936 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
937 wpa_s->roam_start.sec = 0;
938 wpa_s->roam_start.usec = 0;
939 wpas_notify_auth_changed(wpa_s);
940 wpas_notify_roam_time(wpa_s);
941 wpas_notify_roam_complete(wpa_s);
942 } else if (state == WPA_DISCONNECTED &&
943 os_reltime_initialized(&wpa_s->roam_start)) {
944 wpa_s->roam_start.sec = 0;
945 wpa_s->roam_start.usec = 0;
946 wpa_s->roam_time.sec = 0;
947 wpa_s->roam_time.usec = 0;
948 wpas_notify_roam_complete(wpa_s);
949 }
950
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800951 if (state == WPA_INTERFACE_DISABLED) {
952 /* Assure normal scan when interface is restored */
953 wpa_s->normal_scans = 0;
954 }
955
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700956 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800957 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700958 /* Reinitialize normal_scan counter */
959 wpa_s->normal_scans = 0;
960 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800961
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700962#ifdef CONFIG_P2P
963 /*
964 * P2PS client has to reply to Probe Request frames received on the
965 * group operating channel. Enable Probe Request frame reporting for
966 * P2P connected client in case p2p_cli_probe configuration property is
967 * set to 1.
968 */
969 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
970 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
971 wpa_s->current_ssid->p2p_group) {
972 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
973 wpa_dbg(wpa_s, MSG_DEBUG,
974 "P2P: Enable CLI Probe Request RX reporting");
975 wpa_s->p2p_cli_probe =
976 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
977 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
978 wpa_dbg(wpa_s, MSG_DEBUG,
979 "P2P: Disable CLI Probe Request RX reporting");
980 wpa_s->p2p_cli_probe = 0;
981 wpa_drv_probe_req_report(wpa_s, 0);
982 }
983 }
984#endif /* CONFIG_P2P */
985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986 if (state != WPA_SCANNING)
987 wpa_supplicant_notify_scanning(wpa_s, 0);
988
989 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700990 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700991 int fils_hlp_sent = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -0700992 char mld_addr[50];
993
994 mld_addr[0] = '\0';
995 if (wpa_s->valid_links)
996 os_snprintf(mld_addr, sizeof(mld_addr),
997 " ap_mld_addr=" MACSTR,
998 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700999
1000#ifdef CONFIG_SME
1001 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1002 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1003 fils_hlp_sent = 1;
1004#endif /* CONFIG_SME */
1005 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1006 wpa_auth_alg_fils(wpa_s->auth_alg))
1007 fils_hlp_sent = 1;
1008
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001009#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001011 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001012 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001014 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001015 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001017 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001018 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001020 wpa_drv_set_operstate(wpa_s, 1);
1021#ifndef IEEE8021X_EAPOL
1022 wpa_drv_set_supp_port(wpa_s, 1);
1023#endif /* IEEE8021X_EAPOL */
1024 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001025 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001027
1028 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001029
1030#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1031 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001032 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001033#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001034#ifdef CONFIG_OWE
1035 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1036 wpas_update_owe_connect_params(wpa_s);
1037#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001038#ifdef CONFIG_HS20
1039 hs20_configure_frame_filters(wpa_s);
1040#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001041 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1042 state == WPA_ASSOCIATED) {
1043 wpa_s->new_connection = 1;
1044 wpa_drv_set_operstate(wpa_s, 0);
1045#ifndef IEEE8021X_EAPOL
1046 wpa_drv_set_supp_port(wpa_s, 0);
1047#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001048 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 }
1050 wpa_s->wpa_state = state;
1051
1052#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001053 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1054 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001055 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056 wpa_supplicant_stop_bgscan(wpa_s);
1057#endif /* CONFIG_BGSCAN */
1058
Hai Shalom5f92bc92019-04-18 11:54:11 -07001059 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001060 wpa_supplicant_stop_autoscan(wpa_s);
1061
1062 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1063 wpa_supplicant_start_autoscan(wpa_s);
1064
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001065 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1066 wmm_ac_notify_disassoc(wpa_s);
1067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 if (wpa_s->wpa_state != old_state) {
1069 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1070
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001071 /*
1072 * Notify the P2P Device interface about a state change in one
1073 * of the interfaces.
1074 */
1075 wpas_p2p_indicate_state_change(wpa_s);
1076
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001077 if (wpa_s->wpa_state == WPA_COMPLETED ||
1078 old_state == WPA_COMPLETED)
1079 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001080#ifdef CONFIG_DPP2
1081 if (wpa_s->wpa_state == WPA_COMPLETED)
1082 wpas_dpp_connected(wpa_s);
1083#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084 }
Hai Shalomc3565922019-10-28 11:58:20 -07001085#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1086 if (update_fils_connect_params)
1087 wpas_update_fils_connect_params(wpa_s);
1088#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089}
1090
1091
1092void wpa_supplicant_terminate_proc(struct wpa_global *global)
1093{
1094 int pending = 0;
1095#ifdef CONFIG_WPS
1096 struct wpa_supplicant *wpa_s = global->ifaces;
1097 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001098 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001099 if (wpas_wps_terminate_pending(wpa_s) == 1)
1100 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001101#ifdef CONFIG_P2P
1102 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1103 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1104 wpas_p2p_disconnect(wpa_s);
1105#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001106 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107 }
1108#endif /* CONFIG_WPS */
1109 if (pending)
1110 return;
1111 eloop_terminate();
1112}
1113
1114
1115static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1116{
1117 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 wpa_supplicant_terminate_proc(global);
1119}
1120
1121
1122void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1123{
1124 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001125 enum wpa_states new_state;
1126
1127 if (old_state == WPA_SCANNING)
1128 new_state = WPA_SCANNING;
1129 else
1130 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001131
1132 wpa_s->pairwise_cipher = 0;
1133 wpa_s->group_cipher = 0;
1134 wpa_s->mgmt_group_cipher = 0;
1135 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001136 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001138 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139
1140 if (wpa_s->wpa_state != old_state)
1141 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1142}
1143
1144
1145/**
1146 * wpa_supplicant_reload_configuration - Reload configuration data
1147 * @wpa_s: Pointer to wpa_supplicant data
1148 * Returns: 0 on success or -1 if configuration parsing failed
1149 *
1150 * This function can be used to request that the configuration data is reloaded
1151 * (e.g., after configuration file change). This function is reloading
1152 * configuration only for one interface, so this may need to be called multiple
1153 * times if %wpa_supplicant is controlling multiple interfaces and all
1154 * interfaces need reconfiguration.
1155 */
1156int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1157{
1158 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 int reconf_ctrl;
1160 int old_ap_scan;
1161
1162 if (wpa_s->confname == NULL)
1163 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001164 conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 if (conf == NULL) {
1166 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1167 "file '%s' - exiting", wpa_s->confname);
1168 return -1;
1169 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001170 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001171 !wpa_config_read(wpa_s->confanother, conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001172 wpa_msg(wpa_s, MSG_ERROR,
1173 "Failed to parse the configuration file '%s' - exiting",
1174 wpa_s->confanother);
1175 return -1;
1176 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001178 conf->changed_parameters = (unsigned int) -1;
1179
1180 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1181 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1182 os_strcmp(conf->ctrl_interface,
1183 wpa_s->conf->ctrl_interface) != 0);
1184
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001185 if (reconf_ctrl) {
1186 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001187 wpa_s->ctrl_iface = NULL;
1188 }
1189
1190 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001191 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001192 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1193 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001194 wpa_supplicant_deauthenticate(wpa_s,
1195 WLAN_REASON_DEAUTH_LEAVING);
1196 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197
1198 /*
1199 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001200 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001201 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001202 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1203 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1204 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001205 /*
1206 * Clear forced success to clear EAP state for next
1207 * authentication.
1208 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001209 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 }
1211 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1212 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001213 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1215 rsn_preauth_deinit(wpa_s->wpa);
1216
1217 old_ap_scan = wpa_s->conf->ap_scan;
1218 wpa_config_free(wpa_s->conf);
1219 wpa_s->conf = conf;
1220 if (old_ap_scan != wpa_s->conf->ap_scan)
1221 wpas_notify_ap_scan_changed(wpa_s);
1222
1223 if (reconf_ctrl)
1224 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1225
1226 wpa_supplicant_update_config(wpa_s);
1227
1228 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001229 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 wpa_s->reassociate = 1;
1231 wpa_supplicant_req_scan(wpa_s, 0, 0);
1232 }
Hai Shalom60840252021-02-19 19:02:11 -08001233 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001234 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1235 return 0;
1236}
1237
1238
1239static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1240{
1241 struct wpa_global *global = signal_ctx;
1242 struct wpa_supplicant *wpa_s;
1243 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1244 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1245 sig);
1246 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1247 wpa_supplicant_terminate_proc(global);
1248 }
1249 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001250
1251 if (wpa_debug_reopen_file() < 0) {
1252 /* Ignore errors since we cannot really do much to fix this */
1253 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1254 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255}
1256
1257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1259 struct wpa_ssid *ssid,
1260 struct wpa_ie_data *ie)
1261{
1262 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1263 if (ret) {
1264 if (ret == -2) {
1265 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1266 "from association info");
1267 }
1268 return -1;
1269 }
1270
1271 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1272 "cipher suites");
1273 if (!(ie->group_cipher & ssid->group_cipher)) {
1274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1275 "cipher 0x%x (mask 0x%x) - reject",
1276 ie->group_cipher, ssid->group_cipher);
1277 return -1;
1278 }
1279 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1280 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1281 "cipher 0x%x (mask 0x%x) - reject",
1282 ie->pairwise_cipher, ssid->pairwise_cipher);
1283 return -1;
1284 }
1285 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1286 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1287 "management 0x%x (mask 0x%x) - reject",
1288 ie->key_mgmt, ssid->key_mgmt);
1289 return -1;
1290 }
1291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001292 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001293 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1295 "that does not support management frame protection - "
1296 "reject");
1297 return -1;
1298 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299
1300 return 0;
1301}
1302
1303
Hai Shalom021b0b52019-04-10 11:17:58 -07001304static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1305 int freq)
1306{
1307 if (!ie->has_group)
1308 ie->group_cipher = wpa_default_rsn_cipher(freq);
1309 if (!ie->has_pairwise)
1310 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1311 return (ie->group_cipher & ssid->group_cipher) &&
1312 (ie->pairwise_cipher & ssid->pairwise_cipher);
1313}
1314
1315
Hai Shalomc1a21442022-02-04 13:43:00 -08001316void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1317 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1318{
1319 int sel;
1320
1321 sel = ie->mgmt_group_cipher;
1322 if (ssid->group_mgmt_cipher)
1323 sel &= ssid->group_mgmt_cipher;
1324 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1325 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1326 sel = 0;
1327 wpa_dbg(wpa_s, MSG_DEBUG,
1328 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1329 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1330 if (sel & WPA_CIPHER_AES_128_CMAC) {
1331 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: using MGMT group cipher AES-128-CMAC");
1334 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1335 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1336 wpa_dbg(wpa_s, MSG_DEBUG,
1337 "WPA: using MGMT group cipher BIP-GMAC-128");
1338 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1339 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1340 wpa_dbg(wpa_s, MSG_DEBUG,
1341 "WPA: using MGMT group cipher BIP-GMAC-256");
1342 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1343 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1344 wpa_dbg(wpa_s, MSG_DEBUG,
1345 "WPA: using MGMT group cipher BIP-CMAC-256");
1346 } else {
1347 wpa_s->mgmt_group_cipher = 0;
1348 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1349 }
1350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1351 wpa_s->mgmt_group_cipher);
1352 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1353 wpas_get_ssid_pmf(wpa_s, ssid));
1354}
1355
Sunil Ravi77d572f2023-01-17 23:58:31 +00001356/**
1357 * wpa_supplicant_get_psk - Get PSK from config or external database
1358 * @wpa_s: Pointer to wpa_supplicant data
1359 * @bss: Scan results for the selected BSS, or %NULL if not available
1360 * @ssid: Configuration data for the selected network
1361 * @psk: Buffer for the PSK
1362 * Returns: 0 on success or -1 if configuration parsing failed
1363 *
1364 * This function obtains the PSK for a network, either included inline in the
1365 * config or retrieved from an external database.
1366 */
1367static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
1368 struct wpa_bss *bss, struct wpa_ssid *ssid,
1369 u8 *psk)
1370{
1371 if (ssid->psk_set) {
1372 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1373 ssid->psk, PMK_LEN);
1374 os_memcpy(psk, ssid->psk, PMK_LEN);
1375 return 0;
1376 }
1377
1378#ifndef CONFIG_NO_PBKDF2
1379 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
1380 if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1381 4096, psk, PMK_LEN) != 0) {
1382 wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
1383 return -1;
1384 }
1385 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1386 psk, PMK_LEN);
1387 return 0;
1388 }
1389#endif /* CONFIG_NO_PBKDF2 */
1390
1391#ifdef CONFIG_EXT_PASSWORD
1392 if (ssid->ext_psk) {
1393 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1394 ssid->ext_psk);
1395 char pw_str[64 + 1];
1396
1397 if (!pw) {
1398 wpa_msg(wpa_s, MSG_INFO,
1399 "EXT PW: No PSK found from external storage");
1400 return -1;
1401 }
1402
1403 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1404 wpa_msg(wpa_s, MSG_INFO,
1405 "EXT PW: Unexpected PSK length %d in external storage",
1406 (int) wpabuf_len(pw));
1407 ext_password_free(pw);
1408 return -1;
1409 }
1410
1411 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1412 pw_str[wpabuf_len(pw)] = '\0';
1413
1414#ifndef CONFIG_NO_PBKDF2
1415 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1416 {
1417 if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1418 4096, psk, PMK_LEN) != 0) {
1419 wpa_msg(wpa_s, MSG_WARNING,
1420 "Error in pbkdf2_sha1()");
1421 forced_memzero(pw_str, sizeof(pw_str));
1422 ext_password_free(pw);
1423 return -1;
1424 }
1425 wpa_hexdump_key(MSG_MSGDUMP,
1426 "PSK (from external passphrase)",
1427 psk, PMK_LEN);
1428 } else
1429#endif /* CONFIG_NO_PBKDF2 */
1430 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1431 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1432 wpa_msg(wpa_s, MSG_INFO,
1433 "EXT PW: Invalid PSK hex string");
1434 forced_memzero(pw_str, sizeof(pw_str));
1435 ext_password_free(pw);
1436 return -1;
1437 }
1438 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
1439 psk, PMK_LEN);
1440 } else {
1441 wpa_msg(wpa_s, MSG_INFO,
1442 "EXT PW: No suitable PSK available");
1443 forced_memzero(pw_str, sizeof(pw_str));
1444 ext_password_free(pw);
1445 return -1;
1446 }
1447
1448 forced_memzero(pw_str, sizeof(pw_str));
1449 ext_password_free(pw);
1450
1451 return 0;
1452 }
1453#endif /* CONFIG_EXT_PASSWORD */
1454
1455 return -1;
1456}
1457
Hai Shalomc1a21442022-02-04 13:43:00 -08001458
Sunil Ravi89eba102022-09-13 21:04:37 -07001459static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1460 struct wpa_ssid *ssid)
1461{
1462 int akm_count = wpa_s->max_num_akms;
1463 u8 capab = 0;
1464
1465 if (akm_count < 2)
1466 return;
1467
1468 akm_count--;
1469 wpa_s->allowed_key_mgmts = 0;
1470 switch (wpa_s->key_mgmt) {
1471 case WPA_KEY_MGMT_PSK:
1472 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1473 akm_count--;
1474 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1475 }
1476 if (!akm_count)
1477 break;
1478 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1479 akm_count--;
1480 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1481 }
1482 if (!akm_count)
1483 break;
1484 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1485 wpa_s->allowed_key_mgmts |=
1486 WPA_KEY_MGMT_PSK_SHA256;
1487 break;
1488 case WPA_KEY_MGMT_PSK_SHA256:
1489 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1490 akm_count--;
1491 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1492 }
1493 if (!akm_count)
1494 break;
1495 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1496 akm_count--;
1497 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1498 }
1499 if (!akm_count)
1500 break;
1501 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1502 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1503 break;
1504 case WPA_KEY_MGMT_SAE:
1505 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1506 akm_count--;
1507 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1508 }
1509 if (!akm_count)
1510 break;
1511 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1512 akm_count--;
1513 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1514 }
1515 if (!akm_count)
1516 break;
1517 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1518 wpa_s->allowed_key_mgmts |=
1519 WPA_KEY_MGMT_PSK_SHA256;
1520 break;
1521 case WPA_KEY_MGMT_SAE_EXT_KEY:
1522 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1523 akm_count--;
1524 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1525 }
1526 if (!akm_count)
1527 break;
1528 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1529 akm_count--;
1530 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1531 }
1532 if (!akm_count)
1533 break;
1534 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1535 wpa_s->allowed_key_mgmts |=
1536 WPA_KEY_MGMT_PSK_SHA256;
1537 break;
1538 default:
1539 return;
1540 }
1541
Sunil Ravi77d572f2023-01-17 23:58:31 +00001542 if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
1543 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001544 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1545#ifdef CONFIG_SAE_PK
1546 if (ssid->sae_pk)
1547 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1548#endif /* CONFIG_SAE_PK */
1549
1550 if (!((wpa_s->allowed_key_mgmts &
1551 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1552 return;
1553
1554 if (!wpa_s->rsnxe_len) {
1555 wpa_s->rsnxe_len = 3;
1556 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1557 wpa_s->rsnxe[1] = 1;
1558 wpa_s->rsnxe[2] = 0;
1559 }
1560
1561 wpa_s->rsnxe[2] |= capab;
1562}
1563
1564
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001565/**
1566 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1567 * @wpa_s: Pointer to wpa_supplicant data
1568 * @bss: Scan results for the selected BSS, or %NULL if not available
1569 * @ssid: Configuration data for the selected network
1570 * @wpa_ie: Buffer for the WPA/RSN IE
1571 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1572 * used buffer length in case the functions returns success.
Sunil Ravi77d572f2023-01-17 23:58:31 +00001573 * @skip_default_rsne: Whether to skip setting of the default RSNE/RSNXE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574 * Returns: 0 on success or -1 on failure
1575 *
1576 * This function is used to configure authentication and encryption parameters
1577 * based on the network configuration and scan result for the selected BSS (if
1578 * available).
1579 */
1580int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1581 struct wpa_bss *bss, struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001582 u8 *wpa_ie, size_t *wpa_ie_len,
1583 bool skip_default_rsne)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584{
1585 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001586 int sel, proto;
1587 enum sae_pwe sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001588 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589
1590 if (bss) {
1591 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1592 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001593 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001594 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001595 } else {
1596 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1597 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598
1599 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1600 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001601 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602 (ie.key_mgmt & ssid->key_mgmt)) {
1603 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1604 proto = WPA_PROTO_RSN;
1605 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001606 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 (ie.group_cipher & ssid->group_cipher) &&
1608 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1609 (ie.key_mgmt & ssid->key_mgmt)) {
1610 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1611 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001612#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001613 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1614 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1615 (ie.group_cipher & ssid->group_cipher) &&
1616 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1617 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001618 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001619 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001620 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1621 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1622 (ie.group_cipher & ssid->group_cipher) &&
1623 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1624 (ie.key_mgmt & ssid->key_mgmt)) {
1625 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1626 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001627#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 } else if (bss) {
1629 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001630 wpa_dbg(wpa_s, MSG_DEBUG,
1631 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1632 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1633 ssid->key_mgmt);
1634 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1635 MAC2STR(bss->bssid),
1636 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1637 bss_wpa ? " WPA" : "",
1638 bss_rsn ? " RSN" : "",
1639 bss_osen ? " OSEN" : "");
1640 if (bss_rsn) {
1641 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1642 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1643 wpa_dbg(wpa_s, MSG_DEBUG,
1644 "Could not parse RSN element");
1645 } else {
1646 wpa_dbg(wpa_s, MSG_DEBUG,
1647 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1648 ie.pairwise_cipher, ie.group_cipher,
1649 ie.key_mgmt);
1650 }
1651 }
1652 if (bss_wpa) {
1653 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1654 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1655 wpa_dbg(wpa_s, MSG_DEBUG,
1656 "Could not parse WPA element");
1657 } else {
1658 wpa_dbg(wpa_s, MSG_DEBUG,
1659 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1660 ie.pairwise_cipher, ie.group_cipher,
1661 ie.key_mgmt);
1662 }
1663 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001664 return -1;
1665 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001666 if (ssid->proto & WPA_PROTO_OSEN)
1667 proto = WPA_PROTO_OSEN;
1668 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669 proto = WPA_PROTO_RSN;
1670 else
1671 proto = WPA_PROTO_WPA;
1672 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1673 os_memset(&ie, 0, sizeof(ie));
1674 ie.group_cipher = ssid->group_cipher;
1675 ie.pairwise_cipher = ssid->pairwise_cipher;
1676 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001677 ie.mgmt_group_cipher = 0;
1678 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1679 if (ssid->group_mgmt_cipher &
1680 WPA_CIPHER_BIP_GMAC_256)
1681 ie.mgmt_group_cipher =
1682 WPA_CIPHER_BIP_GMAC_256;
1683 else if (ssid->group_mgmt_cipher &
1684 WPA_CIPHER_BIP_CMAC_256)
1685 ie.mgmt_group_cipher =
1686 WPA_CIPHER_BIP_CMAC_256;
1687 else if (ssid->group_mgmt_cipher &
1688 WPA_CIPHER_BIP_GMAC_128)
1689 ie.mgmt_group_cipher =
1690 WPA_CIPHER_BIP_GMAC_128;
1691 else
1692 ie.mgmt_group_cipher =
1693 WPA_CIPHER_AES_128_CMAC;
1694 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001695#ifdef CONFIG_OWE
1696 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1697 !ssid->owe_only &&
1698 !bss_wpa && !bss_rsn && !bss_osen) {
1699 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1700 wpa_s->wpa_proto = 0;
1701 *wpa_ie_len = 0;
1702 return 0;
1703 }
1704#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1706 "based on configuration");
1707 } else
1708 proto = ie.proto;
1709 }
1710
1711 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1712 "pairwise %d key_mgmt %d proto %d",
1713 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714 if (ssid->ieee80211w) {
1715 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1716 ie.mgmt_group_cipher);
1717 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1721 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001722 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723
1724 if (bss || !wpa_s->ap_ies_from_associnfo) {
1725 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1726 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1727 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001728 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1729 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1730 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731 return -1;
1732 }
1733
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001734#ifdef CONFIG_NO_WPA
1735 wpa_s->group_cipher = WPA_CIPHER_NONE;
1736 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1737#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001738 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001739 wpa_dbg(wpa_s, MSG_DEBUG,
1740 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1741 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001742 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1743 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1745 "cipher");
1746 return -1;
1747 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001748 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1749 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750
1751 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001752 wpa_dbg(wpa_s, MSG_DEBUG,
1753 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1754 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001755 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1756 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1758 "cipher");
1759 return -1;
1760 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001761 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1762 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001763#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764
1765 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001766#ifdef CONFIG_SAE
Sunil Ravi77d572f2023-01-17 23:58:31 +00001767 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) ||
1768 wpas_is_sae_avoided(wpa_s, ssid, &ie))
Sunil Ravi89eba102022-09-13 21:04:37 -07001769 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1770 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001771#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001772#ifdef CONFIG_IEEE80211R
1773 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1774 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1775 sel &= ~WPA_KEY_MGMT_FT;
1776#endif /* CONFIG_IEEE80211R */
1777 wpa_dbg(wpa_s, MSG_DEBUG,
1778 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1779 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001781#ifdef CONFIG_IEEE80211R
1782#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001783 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1784 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001785 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1786 wpa_dbg(wpa_s, MSG_DEBUG,
1787 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001788 if (!ssid->ft_eap_pmksa_caching &&
1789 pmksa_cache_get_current(wpa_s->wpa)) {
1790 /* PMKSA caching with FT may have interoperability
1791 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001792 wpa_dbg(wpa_s, MSG_DEBUG,
1793 "WPA: Disable PMKSA caching for FT/802.1X connection");
1794 pmksa_cache_clear_current(wpa_s->wpa);
1795 }
1796#endif /* CONFIG_SHA384 */
1797#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001798#ifdef CONFIG_SUITEB192
1799 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1800 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1801 wpa_dbg(wpa_s, MSG_DEBUG,
1802 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1803#endif /* CONFIG_SUITEB192 */
1804#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001805 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1806 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1807 wpa_dbg(wpa_s, MSG_DEBUG,
1808 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001809#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001810#ifdef CONFIG_FILS
1811#ifdef CONFIG_IEEE80211R
1812 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1813 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1814 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001815#endif /* CONFIG_IEEE80211R */
1816 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1817 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1818 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001819#ifdef CONFIG_IEEE80211R
1820 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1821 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1822 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1823#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001824 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1825 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1826 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1827#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001829 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1830 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1832 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001833 if (!ssid->ft_eap_pmksa_caching &&
1834 pmksa_cache_get_current(wpa_s->wpa)) {
1835 /* PMKSA caching with FT may have interoperability
1836 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001837 wpa_dbg(wpa_s, MSG_DEBUG,
1838 "WPA: Disable PMKSA caching for FT/802.1X connection");
1839 pmksa_cache_clear_current(wpa_s->wpa);
1840 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001841#endif /* CONFIG_IEEE80211R */
1842#ifdef CONFIG_DPP
1843 } else if (sel & WPA_KEY_MGMT_DPP) {
1844 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1845 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1846#endif /* CONFIG_DPP */
1847#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001848 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1849 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1850 wpa_dbg(wpa_s, MSG_DEBUG,
1851 "RSN: using KEY_MGMT FT/SAE (ext key)");
1852 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1853 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1854 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001855 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1856 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1857 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1858 } else if (sel & WPA_KEY_MGMT_SAE) {
1859 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1860 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1861#endif /* CONFIG_SAE */
1862#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1864 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1865 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1866#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1868 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1869 wpa_dbg(wpa_s, MSG_DEBUG,
1870 "WPA: using KEY_MGMT 802.1X with SHA256");
1871 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1872 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1873 wpa_dbg(wpa_s, MSG_DEBUG,
1874 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001875 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1876 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1877 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1878 } else if (sel & WPA_KEY_MGMT_PSK) {
1879 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1880 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1881 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1882 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1883 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001884#ifdef CONFIG_HS20
1885 } else if (sel & WPA_KEY_MGMT_OSEN) {
1886 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1887 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1888#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001889#ifdef CONFIG_OWE
1890 } else if (sel & WPA_KEY_MGMT_OWE) {
1891 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1892 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1893#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001894 } else {
1895 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1896 "authenticated key management type");
1897 return -1;
1898 }
1899
1900 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1901 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1902 wpa_s->pairwise_cipher);
1903 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1904
Hai Shalomc3565922019-10-28 11:58:20 -07001905 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001906 (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED ||
1907 (bss && is_6ghz_freq(bss->freq)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07001908 wpa_msg(wpa_s, MSG_INFO,
1909 "RSN: Management frame protection required but the selected AP does not enable it");
1910 return -1;
1911 }
1912
Hai Shalomc1a21442022-02-04 13:43:00 -08001913 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001914#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001915 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1916 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1917 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001918#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001919 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001920 if ((ssid->sae_password_id ||
1921 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001922 sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
1923 sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
1924 if (bss && is_6ghz_freq(bss->freq) &&
1925 sae_pwe == SAE_PWE_HUNT_AND_PECK) {
1926 wpa_dbg(wpa_s, MSG_DEBUG,
1927 "RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
1928 sae_pwe = SAE_PWE_BOTH;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001929 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001930 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001931#ifdef CONFIG_SAE_PK
1932 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1933 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1934 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1935 ((ssid->sae_password &&
1936 sae_pk_valid_password(ssid->sae_password)) ||
1937 (!ssid->sae_password && ssid->passphrase &&
1938 sae_pk_valid_password(ssid->passphrase))));
1939#endif /* CONFIG_SAE_PK */
Sunil Ravi77d572f2023-01-17 23:58:31 +00001940 if (bss && is_6ghz_freq(bss->freq) &&
1941 wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
1942 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
1943 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1944 MGMT_FRAME_PROTECTION_REQUIRED);
1945 }
Hai Shalomb755a2a2020-04-23 21:49:02 -07001946#ifdef CONFIG_TESTING_OPTIONS
1947 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1948 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001949 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1950 wpa_s->oci_freq_override_eapol);
1951 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1952 wpa_s->oci_freq_override_eapol_g2);
1953 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1954 wpa_s->oci_freq_override_ft_assoc);
1955 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1956 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001957 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1958 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001959#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001960
1961 /* Extended Key ID is only supported in infrastructure BSS so far */
1962 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1963 (ssid->proto & WPA_PROTO_RSN) &&
1964 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1965 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1966 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1967 int use_ext_key_id = 0;
1968
1969 wpa_msg(wpa_s, MSG_DEBUG,
1970 "WPA: Enable Extended Key ID support");
1971 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1972 wpa_s->conf->extended_key_id);
1973 if (bss_rsn &&
1974 wpa_s->conf->extended_key_id &&
1975 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1976 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1977 use_ext_key_id = 1;
1978 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1979 use_ext_key_id);
1980 } else {
1981 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1982 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1983 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984
Sunil Ravi77d572f2023-01-17 23:58:31 +00001985 if (!skip_default_rsne) {
1986 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
1987 wpa_ie_len)) {
1988 wpa_msg(wpa_s, MSG_WARNING,
1989 "RSN: Failed to generate RSNE/WPA IE");
1990 return -1;
1991 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992
Sunil Ravi77d572f2023-01-17 23:58:31 +00001993 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1994 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1995 &wpa_s->rsnxe_len)) {
1996 wpa_msg(wpa_s, MSG_WARNING,
1997 "RSN: Failed to generate RSNXE");
1998 return -1;
1999 }
Hai Shalomc3565922019-10-28 11:58:20 -07002000 }
2001
Hai Shalom021b0b52019-04-10 11:17:58 -07002002 if (0) {
2003#ifdef CONFIG_DPP
2004 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
2005 /* Use PMK from DPP network introduction (PMKSA entry) */
2006 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002007#ifdef CONFIG_DPP2
2008 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
2009#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002010#endif /* CONFIG_DPP */
2011 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002012 int psk_set = 0;
2013
Sunil Ravi77d572f2023-01-17 23:58:31 +00002014 if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) {
2015 u8 psk[PMK_LEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07002016
Sunil Ravi77d572f2023-01-17 23:58:31 +00002017 if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
2018 psk) == 0) {
2019 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
2020 NULL);
2021 psk_set = 1;
2022 }
2023 forced_memzero(psk, sizeof(psk));
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002024 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002025
Roshan Pius3a1667e2018-07-03 15:17:14 -07002026 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00002027 (ssid->sae_password || ssid->passphrase || ssid->ext_psk))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002028 psk_set = 1;
2029
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002030 if (!psk_set) {
2031 wpa_msg(wpa_s, MSG_INFO,
2032 "No PSK available for association");
Sunil Ravi77d572f2023-01-17 23:58:31 +00002033 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002034 return -1;
2035 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002036#ifdef CONFIG_OWE
2037 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2038 /* OWE Diffie-Hellman exchange in (Re)Association
2039 * Request/Response frames set the PMK, so do not override it
2040 * here. */
2041#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002042 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2044
Hai Shalomfdcde762020-04-02 11:19:20 -07002045 if (ssid->mode != WPAS_MODE_IBSS &&
2046 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2047 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2048 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2049 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2050 wpa_msg(wpa_s, MSG_INFO,
2051 "Disable PTK0 rekey support - replaced with reconnect");
2052 wpa_s->deny_ptk0_rekey = 1;
2053 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2054 } else {
2055 wpa_s->deny_ptk0_rekey = 0;
2056 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2057 }
2058
Winnie Chen4138eec2022-11-10 16:32:53 +08002059#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302060 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002061 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2062 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002063 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2064 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302065 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2066 wpa_dbg(wpa_s, MSG_INFO,
2067 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2068 }
Sunil Ravif42be322022-11-04 03:31:21 +00002069#else
2070 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2071 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2072 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002073#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 return 0;
2076}
2077
2078
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002079static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
2080{
Hai Shalomc1a21442022-02-04 13:43:00 -08002081 bool scs = true, mscs = true;
2082
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002083 *pos = 0x00;
2084
2085 switch (idx) {
2086 case 0: /* Bits 0-7 */
2087 break;
2088 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002089 if (wpa_s->conf->coloc_intf_reporting) {
2090 /* Bit 13 - Collocated Interference Reporting */
2091 *pos |= 0x20;
2092 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002093 break;
2094 case 2: /* Bits 16-23 */
2095#ifdef CONFIG_WNM
2096 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002097 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002098 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002099#endif /* CONFIG_WNM */
2100 break;
2101 case 3: /* Bits 24-31 */
2102#ifdef CONFIG_WNM
2103 *pos |= 0x02; /* Bit 25 - SSID List */
2104#endif /* CONFIG_WNM */
2105#ifdef CONFIG_INTERWORKING
2106 if (wpa_s->conf->interworking)
2107 *pos |= 0x80; /* Bit 31 - Interworking */
2108#endif /* CONFIG_INTERWORKING */
2109 break;
2110 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002111#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002112 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002113 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002114#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002115 break;
2116 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002117#ifdef CONFIG_HS20
2118 if (wpa_s->conf->hs20)
2119 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2120#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002121#ifdef CONFIG_MBO
2122 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2123#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002124 break;
2125 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002126#ifdef CONFIG_TESTING_OPTIONS
2127 if (wpa_s->disable_scs_support)
2128 scs = false;
2129#endif /* CONFIG_TESTING_OPTIONS */
2130 if (scs)
2131 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002132 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002133 case 7: /* Bits 56-63 */
2134 break;
2135 case 8: /* Bits 64-71 */
2136 if (wpa_s->conf->ftm_responder)
2137 *pos |= 0x40; /* Bit 70 - FTM responder */
2138 if (wpa_s->conf->ftm_initiator)
2139 *pos |= 0x80; /* Bit 71 - FTM initiator */
2140 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002141 case 9: /* Bits 72-79 */
2142#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002143 if (!wpa_s->disable_fils)
2144 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002145#endif /* CONFIG_FILS */
2146 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002147 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002148#ifdef CONFIG_TESTING_OPTIONS
2149 if (wpa_s->disable_mscs_support)
2150 mscs = false;
2151#endif /* CONFIG_TESTING_OPTIONS */
2152 if (mscs)
2153 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002154 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002155 }
2156}
2157
2158
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002159int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002160{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002161 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002162 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002163
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002164 if (len < wpa_s->extended_capa_len)
2165 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002166 if (buflen < (size_t) len + 2) {
2167 wpa_printf(MSG_INFO,
2168 "Not enough room for building extended capabilities element");
2169 return -1;
2170 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002171
2172 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002173 *pos++ = len;
2174 for (i = 0; i < len; i++, pos++) {
2175 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002176
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002177 if (i < wpa_s->extended_capa_len) {
2178 *pos &= ~wpa_s->extended_capa_mask[i];
2179 *pos |= wpa_s->extended_capa[i];
2180 }
2181 }
2182
2183 while (len > 0 && buf[1 + len] == 0) {
2184 len--;
2185 buf[1] = len;
2186 }
2187 if (len == 0)
2188 return 0;
2189
2190 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002191}
2192
2193
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002194static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2195 struct wpa_bss *test_bss)
2196{
2197 struct wpa_bss *bss;
2198
2199 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2200 if (bss == test_bss)
2201 return 1;
2202 }
2203
2204 return 0;
2205}
2206
2207
2208static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2209 struct wpa_ssid *test_ssid)
2210{
2211 struct wpa_ssid *ssid;
2212
2213 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2214 if (ssid == test_ssid)
2215 return 1;
2216 }
2217
2218 return 0;
2219}
2220
2221
2222int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2223 struct wpa_ssid *test_ssid)
2224{
2225 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2226 return 0;
2227
2228 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2229}
2230
2231
2232void wpas_connect_work_free(struct wpa_connect_work *cwork)
2233{
2234 if (cwork == NULL)
2235 return;
2236 os_free(cwork);
2237}
2238
2239
2240void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2241{
2242 struct wpa_connect_work *cwork;
2243 struct wpa_radio_work *work = wpa_s->connect_work;
2244
2245 if (!work)
2246 return;
2247
2248 wpa_s->connect_work = NULL;
2249 cwork = work->ctx;
2250 work->ctx = NULL;
2251 wpas_connect_work_free(cwork);
2252 radio_work_done(work);
2253}
2254
2255
Sunil Ravi77d572f2023-01-17 23:58:31 +00002256int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
2257 enum wpas_mac_addr_style style,
2258 struct wpa_ssid *ssid)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002259{
2260 struct os_reltime now;
2261 u8 addr[ETH_ALEN];
2262
2263 os_get_reltime(&now);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002264 /* Random addresses are valid within a given ESS so check
2265 * expiration/value only when continuing to use the same ESS. */
2266 if (wpa_s->last_mac_addr_style == style && wpa_s->reassoc_same_ess) {
2267 if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
2268 /* Pregenerated addresses do not expire but their value
2269 * might have changed, so let's check that. */
2270 if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
2271 ETH_ALEN) == 0)
2272 return 0;
2273 } else if ((wpa_s->last_mac_addr_change.sec != 0 ||
2274 wpa_s->last_mac_addr_change.usec != 0) &&
2275 !os_reltime_expired(
2276 &now,
2277 &wpa_s->last_mac_addr_change,
2278 wpa_s->conf->rand_addr_lifetime)) {
2279 wpa_msg(wpa_s, MSG_DEBUG,
2280 "Previously selected random MAC address has not yet expired");
2281 return 0;
2282 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002283 }
2284
2285 switch (style) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002286 case WPAS_MAC_ADDR_STYLE_RANDOM:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002287 if (random_mac_addr(addr) < 0)
2288 return -1;
2289 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002290 case WPAS_MAC_ADDR_STYLE_RANDOM_SAME_OUI:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002291 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2292 if (random_mac_addr_keep_oui(addr) < 0)
2293 return -1;
2294 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002295 case WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS:
2296 if (!ssid) {
2297 wpa_msg(wpa_s, MSG_INFO,
2298 "Invalid 'ssid' for address policy 3");
2299 return -1;
2300 }
2301 os_memcpy(addr, ssid->mac_value, ETH_ALEN);
2302 break;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002303 default:
2304 return -1;
2305 }
2306
2307 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2308 wpa_msg(wpa_s, MSG_INFO,
2309 "Failed to set random MAC address");
2310 return -1;
2311 }
2312
2313 os_get_reltime(&wpa_s->last_mac_addr_change);
2314 wpa_s->mac_addr_changed = 1;
2315 wpa_s->last_mac_addr_style = style;
2316
2317 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2318 wpa_msg(wpa_s, MSG_INFO,
2319 "Could not update MAC address information");
2320 return -1;
2321 }
2322
2323 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2324 MAC2STR(addr));
2325
Sunil Ravi77d572f2023-01-17 23:58:31 +00002326 return 1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002327}
2328
2329
2330int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2331{
2332 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2333 !wpa_s->conf->preassoc_mac_addr)
2334 return 0;
2335
Sunil Ravi77d572f2023-01-17 23:58:31 +00002336 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
2337 NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002338}
2339
2340
Sunil Ravi89eba102022-09-13 21:04:37 -07002341void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
Hai Shalomc3565922019-10-28 11:58:20 -07002342{
2343#ifdef CONFIG_SAE
2344 int *groups = conf->sae_groups;
2345 int default_groups[] = { 19, 20, 21, 0 };
2346 const char *password;
2347
2348 if (!groups || groups[0] <= 0)
2349 groups = default_groups;
2350
2351 password = ssid->sae_password;
2352 if (!password)
2353 password = ssid->passphrase;
2354
Hai Shalom899fcc72020-10-19 14:38:18 -07002355 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002356 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002357 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002358 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002359 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002360 /* PT derivation not needed */
2361 sae_deinit_pt(ssid->pt);
2362 ssid->pt = NULL;
2363 return;
2364 }
2365
2366 if (ssid->pt)
2367 return; /* PT already derived */
2368 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2369 (const u8 *) password, os_strlen(password),
2370 ssid->sae_password_id);
2371#endif /* CONFIG_SAE */
2372}
2373
2374
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002375static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2376{
2377#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2378 os_free(wpa_s->sme.sae_rejected_groups);
2379 wpa_s->sme.sae_rejected_groups = NULL;
2380#ifdef CONFIG_TESTING_OPTIONS
2381 if (wpa_s->extra_sae_rejected_groups) {
2382 int i, *groups = wpa_s->extra_sae_rejected_groups;
2383
2384 for (i = 0; groups[i]; i++) {
2385 wpa_printf(MSG_DEBUG,
2386 "TESTING: Indicate rejection of an extra SAE group %d",
2387 groups[i]);
2388 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2389 groups[i]);
2390 }
2391 }
2392#endif /* CONFIG_TESTING_OPTIONS */
2393#endif /* CONFIG_SAE && CONFIG_SME */
2394}
2395
2396
Hai Shalom60840252021-02-19 19:02:11 -08002397int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2398{
2399 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2400 wpa_msg(wpa_s, MSG_INFO,
2401 "Could not restore permanent MAC address");
2402 return -1;
2403 }
2404 wpa_s->mac_addr_changed = 0;
2405 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2406 wpa_msg(wpa_s, MSG_INFO,
2407 "Could not update MAC address information");
2408 return -1;
2409 }
2410 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2411 return 0;
2412}
2413
2414
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002415static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417/**
2418 * wpa_supplicant_associate - Request association
2419 * @wpa_s: Pointer to wpa_supplicant data
2420 * @bss: Scan results for the selected BSS, or %NULL if not available
2421 * @ssid: Configuration data for the selected network
2422 *
2423 * This function is used to request %wpa_supplicant to associate with a BSS.
2424 */
2425void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2426 struct wpa_bss *bss, struct wpa_ssid *ssid)
2427{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002428 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002429 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002430
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002431 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002432 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002433
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002434 /*
2435 * If we are starting a new connection, any previously pending EAPOL
2436 * RX cannot be valid anymore.
2437 */
2438 wpabuf_free(wpa_s->pending_eapol_rx);
2439 wpa_s->pending_eapol_rx = NULL;
2440
Sunil Ravi77d572f2023-01-17 23:58:31 +00002441 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002442 rand_style = wpa_s->conf->mac_addr;
2443 else
2444 rand_style = ssid->mac_addr;
2445
Sunil Ravia04bd252022-05-02 22:54:18 -07002446 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002447 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002448 wmm_ac_clear_saved_tspecs(wpa_s);
2449 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002450 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002451#ifdef CONFIG_TESTING_OPTIONS
2452 wpa_s->testing_resend_assoc = 0;
2453#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002454
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002455 if (wpa_s->last_ssid == ssid) {
2456 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002457 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002458 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2459 wmm_ac_save_tspecs(wpa_s);
2460 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002461 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2462 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002463 }
Hai Shalomc3565922019-10-28 11:58:20 -07002464 } else {
2465#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002466 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002467#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002468 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002469#ifdef CONFIG_SAE
2470 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2471#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002472
Sunil Ravi77d572f2023-01-17 23:58:31 +00002473 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2474 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2475
2476 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002477 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002478 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2479 status > 0) /* MAC changed */
2480 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2481 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2482 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002483 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002484 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002485 }
2486 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487
2488#ifdef CONFIG_IBSS_RSN
2489 ibss_rsn_deinit(wpa_s->ibss_rsn);
2490 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002491#else /* CONFIG_IBSS_RSN */
2492 if (ssid->mode == WPAS_MODE_IBSS &&
2493 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2494 wpa_msg(wpa_s, MSG_INFO,
2495 "IBSS RSN not supported in the build");
2496 return;
2497 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498#endif /* CONFIG_IBSS_RSN */
2499
2500 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2501 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2502#ifdef CONFIG_AP
2503 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2504 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2505 "mode");
2506 return;
2507 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002508 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2509 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002510 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2511 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002512 return;
2513 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 wpa_s->current_bss = bss;
2515#else /* CONFIG_AP */
2516 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2517 "the build");
2518#endif /* CONFIG_AP */
2519 return;
2520 }
2521
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002522 if (ssid->mode == WPAS_MODE_MESH) {
2523#ifdef CONFIG_MESH
2524 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2525 wpa_msg(wpa_s, MSG_INFO,
2526 "Driver does not support mesh mode");
2527 return;
2528 }
2529 if (bss)
2530 ssid->frequency = bss->freq;
2531 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2532 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2533 return;
2534 }
2535 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002536#else /* CONFIG_MESH */
2537 wpa_msg(wpa_s, MSG_ERROR,
2538 "mesh mode support not included in the build");
2539#endif /* CONFIG_MESH */
2540 return;
2541 }
2542
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002543 /*
2544 * Set WPA state machine configuration to match the selected network now
2545 * so that the information is available before wpas_start_assoc_cb()
2546 * gets called. This is needed at least for RSN pre-authentication where
2547 * candidate APs are added to a list based on scan result processing
2548 * before completion of the first association.
2549 */
2550 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2551
2552#ifdef CONFIG_DPP
2553 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2554 return;
2555#endif /* CONFIG_DPP */
2556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557#ifdef CONFIG_TDLS
2558 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002559 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560#endif /* CONFIG_TDLS */
2561
Hai Shalomc3565922019-10-28 11:58:20 -07002562#ifdef CONFIG_MBO
2563 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2564#endif /* CONFIG_MBO */
2565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002567 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002568 sme_authenticate(wpa_s, bss, ssid);
2569 return;
2570 }
2571
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002572 if (wpa_s->connect_work) {
2573 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2574 return;
2575 }
2576
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002577 if (radio_work_pending(wpa_s, "connect")) {
2578 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2579 return;
2580 }
2581
Dmitry Shmidt29333592017-01-09 12:27:11 -08002582#ifdef CONFIG_SME
2583 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2584 /* Clear possibly set auth_alg, if any, from last attempt. */
2585 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2586 }
2587#endif /* CONFIG_SME */
2588
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002589 wpas_abort_ongoing_scan(wpa_s);
2590
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002591 cwork = os_zalloc(sizeof(*cwork));
2592 if (cwork == NULL)
2593 return;
2594
2595 cwork->bss = bss;
2596 cwork->ssid = ssid;
2597
2598 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2599 wpas_start_assoc_cb, cwork) < 0) {
2600 os_free(cwork);
2601 }
2602}
2603
2604
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002605static int bss_is_ibss(struct wpa_bss *bss)
2606{
2607 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2608 IEEE80211_CAP_IBSS;
2609}
2610
2611
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002612static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2613 const struct wpa_ssid *ssid)
2614{
2615 enum hostapd_hw_mode hw_mode;
2616 struct hostapd_hw_modes *mode = NULL;
2617 u8 channel;
2618 int i;
2619
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002620 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2621 if (hw_mode == NUM_HOSTAPD_MODES)
2622 return 0;
2623 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2624 if (wpa_s->hw.modes[i].mode == hw_mode) {
2625 mode = &wpa_s->hw.modes[i];
2626 break;
2627 }
2628 }
2629
2630 if (!mode)
2631 return 0;
2632
2633 return mode->vht_capab != 0;
2634}
2635
2636
Hai Shalomc1a21442022-02-04 13:43:00 -08002637static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2638{
2639 int i;
2640
2641 for (i = channel; i < channel + 16; i += 4) {
2642 struct hostapd_channel_data *chan;
2643
2644 chan = hw_get_channel_chan(mode, i, NULL);
2645 if (!chan ||
2646 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2647 return false;
2648 }
2649
2650 return true;
2651}
2652
2653
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002654void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2655 const struct wpa_ssid *ssid,
2656 struct hostapd_freq_params *freq)
2657{
Hai Shalom81f62d82019-07-22 12:10:00 -07002658 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002659 enum hostapd_hw_mode hw_mode;
2660 struct hostapd_hw_modes *mode = NULL;
2661 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2662 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002663 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2664 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2665 6595, 6675, 6755, 6835, 6915, 6995 };
2666 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002667 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2668 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002669 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002670 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002671 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002672 int chwidth, seg0, seg1;
2673 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002674 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002675
2676 freq->freq = ssid->frequency;
2677
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002678 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2679 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2680
2681 if (ssid->mode != WPAS_MODE_IBSS)
2682 break;
2683
2684 /* Don't adjust control freq in case of fixed_freq */
2685 if (ssid->fixed_freq)
2686 break;
2687
2688 if (!bss_is_ibss(bss))
2689 continue;
2690
2691 if (ssid->ssid_len == bss->ssid_len &&
2692 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2693 wpa_printf(MSG_DEBUG,
2694 "IBSS already found in scan results, adjust control freq: %d",
2695 bss->freq);
2696 freq->freq = bss->freq;
2697 obss_scan = 0;
2698 break;
2699 }
2700 }
2701
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002702 /* For IBSS check HT_IBSS flag */
2703 if (ssid->mode == WPAS_MODE_IBSS &&
2704 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2705 return;
2706
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002707 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2708 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2709 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2710 wpa_printf(MSG_DEBUG,
2711 "IBSS: WEP/TKIP detected, do not try to enable HT");
2712 return;
2713 }
2714
2715 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002716 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2717 if (wpa_s->hw.modes[i].mode == hw_mode) {
2718 mode = &wpa_s->hw.modes[i];
2719 break;
2720 }
2721 }
2722
2723 if (!mode)
2724 return;
2725
Hai Shalom60840252021-02-19 19:02:11 -08002726 freq->channel = channel;
2727
Hai Shalomc3565922019-10-28 11:58:20 -07002728 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2729 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002730
Hai Shalomc1a21442022-02-04 13:43:00 -08002731 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2732 * However, HE is mandatory for 6 GHz.
2733 */
2734 is_6ghz = is_6ghz_freq(freq->freq);
2735 if (is_6ghz)
2736 goto skip_to_6ghz;
2737
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002738#ifdef CONFIG_HT_OVERRIDES
2739 if (ssid->disable_ht) {
2740 freq->ht_enabled = 0;
2741 return;
2742 }
2743#endif /* CONFIG_HT_OVERRIDES */
2744
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002745 freq->ht_enabled = ht_supported(mode);
2746 if (!freq->ht_enabled)
2747 return;
2748
Hai Shalomc3565922019-10-28 11:58:20 -07002749 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2750 if (is_24ghz)
2751 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002752#ifdef CONFIG_HE_OVERRIDES
2753 if (is_24ghz && ssid->disable_he)
2754 freq->he_enabled = 0;
2755#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002756
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002757 /* Setup higher BW only for 5 GHz */
2758 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2759 return;
2760
2761 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2762 pri_chan = &mode->channels[chan_idx];
2763 if (pri_chan->chan == channel)
2764 break;
2765 pri_chan = NULL;
2766 }
2767 if (!pri_chan)
2768 return;
2769
2770 /* Check primary channel flags */
2771 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2772 return;
2773
Hai Shalom74f70d42019-02-11 14:42:39 -08002774 freq->channel = pri_chan->chan;
2775
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002776#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002777 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002778#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002779 if (ssid->disable_vht)
2780 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002781#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002782 goto skip_ht40;
2783 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002784#endif /* CONFIG_HT_OVERRIDES */
2785
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002786 /* Check/setup HT40+/HT40- */
2787 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2788 if (ht40plus[j] == channel) {
2789 ht40 = 1;
2790 break;
2791 }
2792 }
2793
2794 /* Find secondary channel */
2795 for (i = 0; i < mode->num_channels; i++) {
2796 sec_chan = &mode->channels[i];
2797 if (sec_chan->chan == channel + ht40 * 4)
2798 break;
2799 sec_chan = NULL;
2800 }
2801 if (!sec_chan)
2802 return;
2803
2804 /* Check secondary channel flags */
2805 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2806 return;
2807
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002808 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002809 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2810 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002811 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002812 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2813 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002814 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002815 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002816
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002817 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002818 struct wpa_scan_results *scan_res;
2819
2820 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2821 if (scan_res == NULL) {
2822 /* Back to HT20 */
2823 freq->sec_channel_offset = 0;
2824 return;
2825 }
2826
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002827 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002828 switch (res) {
2829 case 0:
2830 /* Back to HT20 */
2831 freq->sec_channel_offset = 0;
2832 break;
2833 case 1:
2834 /* Configuration allowed */
2835 break;
2836 case 2:
2837 /* Switch pri/sec channels */
2838 freq->freq = hw_get_freq(mode, sec_chan->chan);
2839 freq->sec_channel_offset = -freq->sec_channel_offset;
2840 freq->channel = sec_chan->chan;
2841 break;
2842 default:
2843 freq->sec_channel_offset = 0;
2844 break;
2845 }
2846
2847 wpa_scan_results_free(scan_res);
2848 }
2849
Hai Shalom74f70d42019-02-11 14:42:39 -08002850#ifdef CONFIG_HT_OVERRIDES
2851skip_ht40:
2852#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002853 wpa_printf(MSG_DEBUG,
2854 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2855 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002856
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002857 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002858 return;
2859
2860 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002861 if (ssid->mode == WPAS_MODE_IBSS &&
2862 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002863 return;
2864
Paul Stewart092955c2017-02-06 09:13:09 -08002865#ifdef CONFIG_VHT_OVERRIDES
2866 if (ssid->disable_vht) {
2867 freq->vht_enabled = 0;
2868 return;
2869 }
2870#endif /* CONFIG_VHT_OVERRIDES */
2871
Hai Shalomc1a21442022-02-04 13:43:00 -08002872skip_to_6ghz:
2873 vht_freq = *freq;
2874
2875 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002876 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002877 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002878 return;
2879
Hai Shalomfdcde762020-04-02 11:19:20 -07002880 /* Enable HE with VHT for 5 GHz */
2881 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002882
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002883 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002884 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2885 if (freq->freq >= bw80[j] &&
2886 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002887 break;
2888 }
2889
Hai Shalomc1a21442022-02-04 13:43:00 -08002890 if (j == ARRAY_SIZE(bw80) ||
2891 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002892 return;
2893
Hai Shalomc1a21442022-02-04 13:43:00 -08002894 /* Back to HT configuration if channel not usable */
2895 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2896 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002897
Sunil8cd6f4d2022-06-28 18:40:46 +00002898 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002899 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002900 seg1 = 0;
2901
Hai Shalomc1a21442022-02-04 13:43:00 -08002902 if ((mode->he_capab[ieee80211_mode].phy_cap[
2903 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2904 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2905 /* In 160 MHz, the initial four 20 MHz channels were validated
2906 * above; check the remaining four 20 MHz channels for the total
2907 * of 160 MHz bandwidth.
2908 */
2909 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2910 return;
2911
2912 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2913 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002914 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002915 seg0 = channel + 14;
2916 break;
2917 }
2918 }
2919 }
2920
Sunil8cd6f4d2022-06-28 18:40:46 +00002921 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002922 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002923 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002924 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002925 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002926 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002927
2928 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2929 NUM_HOSTAPD_MODES)
2930 return;
2931
2932 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002933 struct hostapd_channel_data *chan;
2934
2935 chan = hw_get_channel_chan(mode, i, NULL);
2936 if (!chan)
2937 continue;
2938
2939 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2940 HOSTAPD_CHAN_NO_IR |
2941 HOSTAPD_CHAN_RADAR))
2942 continue;
2943
2944 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002945 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002946 if (!is_6ghz)
2947 vht_caps |=
2948 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2949 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002950 }
2951
Sunil8cd6f4d2022-06-28 18:40:46 +00002952 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002953 break;
2954 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002955 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002956 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002957 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002958 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2959 seg0 = 50;
2960 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002961 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002962 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2963 seg0 = 114;
2964 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002965 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2966 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002967 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002968#ifdef CONFIG_HT_OVERRIDES
2969 if (ssid->disable_ht40)
2970 seg0 = 0;
2971#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002972 }
2973
Hai Shalomfdcde762020-04-02 11:19:20 -07002974#ifdef CONFIG_HE_OVERRIDES
2975 if (ssid->disable_he) {
2976 vht_freq.he_enabled = 0;
2977 freq->he_enabled = 0;
2978 }
2979#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002980 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002981 freq->channel, ssid->enable_edmg,
2982 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002983 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002984 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002985 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002986 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002987 &mode->he_capab[ieee80211_mode],
2988 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002989 return;
2990
2991 *freq = vht_freq;
2992
2993 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2994 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002995}
2996
2997
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002998#ifdef CONFIG_FILS
2999static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3000 size_t ie_buf_len)
3001{
3002 struct fils_hlp_req *req;
3003 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3004 const u8 *pos;
3005 u8 *buf = ie_buf;
3006
3007 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3008 list) {
3009 rem_len = ie_buf_len - ie_len;
3010 pos = wpabuf_head(req->pkt);
3011 hdr_len = 1 + 2 * ETH_ALEN + 6;
3012 hlp_len = wpabuf_len(req->pkt);
3013
3014 if (rem_len < 2 + hdr_len + hlp_len) {
3015 wpa_printf(MSG_ERROR,
3016 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3017 (unsigned long) rem_len,
3018 (unsigned long) (2 + hdr_len + hlp_len));
3019 break;
3020 }
3021
3022 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3023 /* Element ID */
3024 *buf++ = WLAN_EID_EXTENSION;
3025 /* Length */
3026 *buf++ = len;
3027 /* Element ID Extension */
3028 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3029 /* Destination MAC address */
3030 os_memcpy(buf, req->dst, ETH_ALEN);
3031 buf += ETH_ALEN;
3032 /* Source MAC address */
3033 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3034 buf += ETH_ALEN;
3035 /* LLC/SNAP Header */
3036 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3037 buf += 6;
3038 /* HLP Packet */
3039 os_memcpy(buf, pos, len - hdr_len);
3040 buf += len - hdr_len;
3041 pos += len - hdr_len;
3042
3043 hlp_len -= len - hdr_len;
3044 ie_len += 2 + len;
3045 rem_len -= 2 + len;
3046
3047 while (hlp_len) {
3048 len = (hlp_len > 255) ? 255 : hlp_len;
3049 if (rem_len < 2 + len)
3050 break;
3051 *buf++ = WLAN_EID_FRAGMENT;
3052 *buf++ = len;
3053 os_memcpy(buf, pos, len);
3054 buf += len;
3055 pos += len;
3056
3057 hlp_len -= len;
3058 ie_len += 2 + len;
3059 rem_len -= 2 + len;
3060 }
3061 }
3062
3063 return ie_len;
3064}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003065
3066
3067int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3068{
3069 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3070 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3071 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3072 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3073}
3074
3075
3076int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3077{
3078#ifdef CONFIG_FILS_SK_PFS
3079 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3080 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3081#else /* CONFIG_FILS_SK_PFS */
3082 return 0;
3083#endif /* CONFIG_FILS_SK_PFS */
3084}
3085
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003086#endif /* CONFIG_FILS */
3087
3088
Hai Shalomc1a21442022-02-04 13:43:00 -08003089static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3090 struct wpa_bss *bss,
3091 u8 *wpa_ie, size_t wpa_ie_len,
3092 size_t max_wpa_ie_len)
3093{
3094 struct wpabuf *wfa_ie = NULL;
3095 u8 wfa_capa[1];
3096 size_t wfa_ie_len, buf_len;
3097
3098 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3099 if (wpa_s->enable_dscp_policy_capa)
3100 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3101
3102 if (!wfa_capa[0])
3103 return wpa_ie_len;
3104
3105 /* Wi-Fi Alliance element */
3106 buf_len = 1 + /* Element ID */
3107 1 + /* Length */
3108 3 + /* OUI */
3109 1 + /* OUI Type */
3110 1 + /* Capabilities Length */
3111 sizeof(wfa_capa); /* Capabilities */
3112 wfa_ie = wpabuf_alloc(buf_len);
3113 if (!wfa_ie)
3114 return wpa_ie_len;
3115
3116 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3117 wpabuf_put_u8(wfa_ie, buf_len - 2);
3118 wpabuf_put_be24(wfa_ie, OUI_WFA);
3119 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3120 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3121 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3122
3123 wfa_ie_len = wpabuf_len(wfa_ie);
3124 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3125 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3126 wfa_ie);
3127 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3128 wfa_ie_len);
3129 wpa_ie_len += wfa_ie_len;
3130 }
3131
3132 wpabuf_free(wfa_ie);
3133 return wpa_ie_len;
3134}
3135
3136
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003137static u8 * wpas_populate_assoc_ies(
3138 struct wpa_supplicant *wpa_s,
3139 struct wpa_bss *bss, struct wpa_ssid *ssid,
3140 struct wpa_driver_associate_params *params,
3141 enum wpa_drv_update_connect_params_mask *mask)
3142{
3143 u8 *wpa_ie;
3144 size_t max_wpa_ie_len = 500;
3145 size_t wpa_ie_len;
3146 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003147#ifdef CONFIG_MBO
3148 const u8 *mbo_ie;
3149#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303150#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3151 int pmksa_cached = 0;
3152#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003153#ifdef CONFIG_FILS
3154 const u8 *realm, *username, *rrk;
3155 size_t realm_len, username_len, rrk_len;
3156 u16 next_seq_num;
3157 struct fils_hlp_req *req;
3158
3159 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3160 list) {
3161 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3162 2 + 2 * wpabuf_len(req->pkt) / 255;
3163 }
3164#endif /* CONFIG_FILS */
3165
3166 wpa_ie = os_malloc(max_wpa_ie_len);
3167 if (!wpa_ie) {
3168 wpa_printf(MSG_ERROR,
3169 "Failed to allocate connect IE buffer for %lu bytes",
3170 (unsigned long) max_wpa_ie_len);
3171 return NULL;
3172 }
3173
3174 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3175 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3176 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3177 int try_opportunistic;
3178 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003179 const u8 *addr = bss->bssid;
3180
3181 if (wpa_s->valid_links)
3182 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003183
3184 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3185 wpa_s->conf->okc :
3186 ssid->proactive_key_caching) &&
3187 (ssid->proto & WPA_PROTO_RSN);
3188#ifdef CONFIG_FILS
3189 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3190 cache_id = wpa_bss_get_fils_cache_id(bss);
3191#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003192 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003193 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003194 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003195 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303196#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3197 pmksa_cached = 1;
3198#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003199 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003200 wpa_ie_len = max_wpa_ie_len;
3201 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003202 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003203 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3204 "key management and encryption suites");
3205 os_free(wpa_ie);
3206 return NULL;
3207 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003208#ifdef CONFIG_HS20
3209 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3210 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3211 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3212 wpa_ie_len = max_wpa_ie_len;
3213 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003214 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003215 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3216 "key management and encryption suites");
3217 os_free(wpa_ie);
3218 return NULL;
3219 }
3220#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003221 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3222 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3223 /*
3224 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3225 * use non-WPA since the scan results did not indicate that the
3226 * AP is using WPA or WPA2.
3227 */
3228 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3229 wpa_ie_len = 0;
3230 wpa_s->wpa_proto = 0;
3231 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3232 wpa_ie_len = max_wpa_ie_len;
3233 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003234 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003235 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3236 "key management and encryption suites (no "
3237 "scan results)");
3238 os_free(wpa_ie);
3239 return NULL;
3240 }
3241#ifdef CONFIG_WPS
3242 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3243 struct wpabuf *wps_ie;
3244 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3245 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3246 wpa_ie_len = wpabuf_len(wps_ie);
3247 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3248 } else
3249 wpa_ie_len = 0;
3250 wpabuf_free(wps_ie);
3251 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3252 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3253 params->wps = WPS_MODE_PRIVACY;
3254 else
3255 params->wps = WPS_MODE_OPEN;
3256 wpa_s->wpa_proto = 0;
3257#endif /* CONFIG_WPS */
3258 } else {
3259 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3260 wpa_ie_len = 0;
3261 wpa_s->wpa_proto = 0;
3262 }
3263
3264#ifdef IEEE8021X_EAPOL
3265 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3266 if (ssid->leap) {
3267 if (ssid->non_leap == 0)
3268 algs = WPA_AUTH_ALG_LEAP;
3269 else
3270 algs |= WPA_AUTH_ALG_LEAP;
3271 }
3272 }
3273
3274#ifdef CONFIG_FILS
3275 /* Clear FILS association */
3276 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3277
3278 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3279 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3280 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3281 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003282 &next_seq_num, &rrk, &rrk_len) == 0 &&
3283 (!wpa_s->last_con_fail_realm ||
3284 wpa_s->last_con_fail_realm_len != realm_len ||
3285 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003286 algs = WPA_AUTH_ALG_FILS;
3287 params->fils_erp_username = username;
3288 params->fils_erp_username_len = username_len;
3289 params->fils_erp_realm = realm;
3290 params->fils_erp_realm_len = realm_len;
3291 params->fils_erp_next_seq_num = next_seq_num;
3292 params->fils_erp_rrk = rrk;
3293 params->fils_erp_rrk_len = rrk_len;
3294
3295 if (mask)
3296 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303297 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3298 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3299 pmksa_cached) {
3300 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003301 }
3302#endif /* CONFIG_FILS */
3303#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003304#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003305 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003306 algs = WPA_AUTH_ALG_SAE;
3307#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003308
3309 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3310 if (ssid->auth_alg) {
3311 algs = ssid->auth_alg;
3312 wpa_dbg(wpa_s, MSG_DEBUG,
3313 "Overriding auth_alg selection: 0x%x", algs);
3314 }
3315
Hai Shalom5f92bc92019-04-18 11:54:11 -07003316#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303317 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003318 wpa_dbg(wpa_s, MSG_DEBUG,
3319 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3320 algs = WPA_AUTH_ALG_OPEN;
3321 }
3322#endif /* CONFIG_SAE */
3323
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003324#ifdef CONFIG_P2P
3325 if (wpa_s->global->p2p) {
3326 u8 *pos;
3327 size_t len;
3328 int res;
3329 pos = wpa_ie + wpa_ie_len;
3330 len = max_wpa_ie_len - wpa_ie_len;
3331 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3332 ssid->p2p_group);
3333 if (res >= 0)
3334 wpa_ie_len += res;
3335 }
3336
3337 wpa_s->cross_connect_disallowed = 0;
3338 if (bss) {
3339 struct wpabuf *p2p;
3340 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3341 if (p2p) {
3342 wpa_s->cross_connect_disallowed =
3343 p2p_get_cross_connect_disallowed(p2p);
3344 wpabuf_free(p2p);
3345 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3346 "connection",
3347 wpa_s->cross_connect_disallowed ?
3348 "disallows" : "allows");
3349 }
3350 }
3351
3352 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3353#endif /* CONFIG_P2P */
3354
3355 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003356 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003357 wpa_ie + wpa_ie_len,
3358 max_wpa_ie_len -
3359 wpa_ie_len);
3360 }
3361
3362 /*
3363 * Workaround: Add Extended Capabilities element only if the AP
3364 * included this element in Beacon/Probe Response frames. Some older
3365 * APs seem to have interoperability issues if this element is
3366 * included, so while the standard may require us to include the
3367 * element in all cases, it is justifiable to skip it to avoid
3368 * interoperability issues.
3369 */
3370 if (ssid->p2p_group)
3371 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3372 else
3373 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3374
3375 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3376 u8 ext_capab[18];
3377 int ext_capab_len;
3378 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3379 sizeof(ext_capab));
3380 if (ext_capab_len > 0 &&
3381 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3382 u8 *pos = wpa_ie;
3383 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3384 pos += 2 + pos[1];
3385 os_memmove(pos + ext_capab_len, pos,
3386 wpa_ie_len - (pos - wpa_ie));
3387 wpa_ie_len += ext_capab_len;
3388 os_memcpy(pos, ext_capab, ext_capab_len);
3389 }
3390 }
3391
3392#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003393 if (is_hs20_network(wpa_s, ssid, bss)
3394#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3395 && is_hs20_config(wpa_s)
3396#endif /* ANDROID */
3397 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003398 struct wpabuf *hs20;
3399
Roshan Pius3a1667e2018-07-03 15:17:14 -07003400 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003401 if (hs20) {
3402 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3403 size_t len;
3404
Hai Shalom74f70d42019-02-11 14:42:39 -08003405 wpas_hs20_add_indication(hs20, pps_mo_id,
3406 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003407 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003408 len = max_wpa_ie_len - wpa_ie_len;
3409 if (wpabuf_len(hs20) <= len) {
3410 os_memcpy(wpa_ie + wpa_ie_len,
3411 wpabuf_head(hs20), wpabuf_len(hs20));
3412 wpa_ie_len += wpabuf_len(hs20);
3413 }
3414 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003415 }
3416 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003417 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003418#endif /* CONFIG_HS20 */
3419
3420 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3421 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3422 size_t len;
3423
3424 len = max_wpa_ie_len - wpa_ie_len;
3425 if (wpabuf_len(buf) <= len) {
3426 os_memcpy(wpa_ie + wpa_ie_len,
3427 wpabuf_head(buf), wpabuf_len(buf));
3428 wpa_ie_len += wpabuf_len(buf);
3429 }
3430 }
3431
3432#ifdef CONFIG_FST
3433 if (wpa_s->fst_ies) {
3434 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3435
3436 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3437 os_memcpy(wpa_ie + wpa_ie_len,
3438 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3439 wpa_ie_len += fst_ies_len;
3440 }
3441 }
3442#endif /* CONFIG_FST */
3443
3444#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003445 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003446 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003447 int len;
3448
3449 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003450 max_wpa_ie_len - wpa_ie_len,
3451 !!mbo_attr_from_mbo_ie(mbo_ie,
3452 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003453 if (len >= 0)
3454 wpa_ie_len += len;
3455 }
3456#endif /* CONFIG_MBO */
3457
3458#ifdef CONFIG_FILS
3459 if (algs == WPA_AUTH_ALG_FILS) {
3460 size_t len;
3461
3462 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3463 max_wpa_ie_len - wpa_ie_len);
3464 wpa_ie_len += len;
3465 }
3466#endif /* CONFIG_FILS */
3467
3468#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003469#ifdef CONFIG_TESTING_OPTIONS
3470 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3471 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3472 } else
3473#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003474 if (algs == WPA_AUTH_ALG_OPEN &&
3475 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3476 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003477 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478
Roshan Pius3a1667e2018-07-03 15:17:14 -07003479 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003480 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003481 } else if (wpa_s->assoc_status_code ==
3482 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003483 if (wpa_s->last_owe_group == 19)
3484 group = 20;
3485 else if (wpa_s->last_owe_group == 20)
3486 group = 21;
3487 else
3488 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003489 } else {
3490 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003491 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003492
Roshan Pius3a1667e2018-07-03 15:17:14 -07003493 wpa_s->last_owe_group = group;
3494 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003495 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3496 if (owe_ie &&
3497 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3498 os_memcpy(wpa_ie + wpa_ie_len,
3499 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3500 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003501 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003502 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003503 }
3504#endif /* CONFIG_OWE */
3505
Hai Shalom021b0b52019-04-10 11:17:58 -07003506#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003507 if (DPP_VERSION > 1 &&
3508 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003509 ssid->dpp_netaccesskey &&
3510 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003511 struct rsn_pmksa_cache_entry *pmksa;
3512
3513 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3514 if (!pmksa || !pmksa->dpp_pfs)
3515 goto pfs_fail;
3516
Hai Shalom021b0b52019-04-10 11:17:58 -07003517 dpp_pfs_free(wpa_s->dpp_pfs);
3518 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3519 ssid->dpp_netaccesskey_len);
3520 if (!wpa_s->dpp_pfs) {
3521 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3522 /* Try to continue without PFS */
3523 goto pfs_fail;
3524 }
3525 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3526 max_wpa_ie_len - wpa_ie_len) {
3527 os_memcpy(wpa_ie + wpa_ie_len,
3528 wpabuf_head(wpa_s->dpp_pfs->ie),
3529 wpabuf_len(wpa_s->dpp_pfs->ie));
3530 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3531 }
3532 }
3533pfs_fail:
3534#endif /* CONFIG_DPP2 */
3535
Roshan Pius3a1667e2018-07-03 15:17:14 -07003536#ifdef CONFIG_IEEE80211R
3537 /*
3538 * Add MDIE under these conditions: the network profile allows FT,
3539 * the AP supports FT, and the mobility domain ID matches.
3540 */
3541 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3542 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3543
3544 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3545 size_t len = 0;
3546 const u8 *md = mdie + 2;
3547 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3548
3549 if (os_memcmp(md, wpa_md,
3550 MOBILITY_DOMAIN_ID_LEN) == 0) {
3551 /* Add mobility domain IE */
3552 len = wpa_ft_add_mdie(
3553 wpa_s->wpa, wpa_ie + wpa_ie_len,
3554 max_wpa_ie_len - wpa_ie_len, mdie);
3555 wpa_ie_len += len;
3556 }
3557#ifdef CONFIG_SME
3558 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003559 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003560 wpa_dbg(wpa_s, MSG_DEBUG,
3561 "SME: Trying to use FT over-the-air");
3562 algs |= WPA_AUTH_ALG_FT;
3563 }
3564#endif /* CONFIG_SME */
3565 }
3566 }
3567#endif /* CONFIG_IEEE80211R */
3568
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003569#ifdef CONFIG_TESTING_OPTIONS
3570 if (wpa_s->rsnxe_override_assoc &&
3571 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3572 max_wpa_ie_len - wpa_ie_len) {
3573 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3574 os_memcpy(wpa_ie + wpa_ie_len,
3575 wpabuf_head(wpa_s->rsnxe_override_assoc),
3576 wpabuf_len(wpa_s->rsnxe_override_assoc));
3577 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3578 } else
3579#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003580 if (wpa_s->rsnxe_len > 0 &&
3581 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3582 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3583 wpa_ie_len += wpa_s->rsnxe_len;
3584 }
3585
Hai Shalomc1a21442022-02-04 13:43:00 -08003586#ifdef CONFIG_TESTING_OPTIONS
3587 if (wpa_s->disable_mscs_support)
3588 goto mscs_end;
3589#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003590 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3591 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003592 struct wpabuf *mscs_ie;
3593 size_t mscs_ie_len, buf_len;
3594
Hai Shalom899fcc72020-10-19 14:38:18 -07003595 buf_len = 3 + /* MSCS descriptor IE header */
3596 1 + /* Request type */
3597 2 + /* User priority control */
3598 4 + /* Stream timeout */
3599 3 + /* TCLAS Mask IE header */
3600 wpa_s->robust_av.frame_classifier_len;
3601 mscs_ie = wpabuf_alloc(buf_len);
3602 if (!mscs_ie) {
3603 wpa_printf(MSG_INFO,
3604 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003605 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003606 }
3607
3608 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3609 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3610 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3611 mscs_ie_len = wpabuf_len(mscs_ie);
3612 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3613 mscs_ie_len);
3614 wpa_ie_len += mscs_ie_len;
3615 }
3616
3617 wpabuf_free(mscs_ie);
3618 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003619mscs_end:
3620
3621 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3622 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003623
Hai Shalom74f70d42019-02-11 14:42:39 -08003624 if (ssid->multi_ap_backhaul_sta) {
3625 size_t multi_ap_ie_len;
3626
3627 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3628 max_wpa_ie_len - wpa_ie_len,
3629 MULTI_AP_BACKHAUL_STA);
3630 if (multi_ap_ie_len == 0) {
3631 wpa_printf(MSG_ERROR,
3632 "Multi-AP: Failed to build Multi-AP IE");
3633 os_free(wpa_ie);
3634 return NULL;
3635 }
3636 wpa_ie_len += multi_ap_ie_len;
3637 }
3638
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003639 params->wpa_ie = wpa_ie;
3640 params->wpa_ie_len = wpa_ie_len;
3641 params->auth_alg = algs;
3642 if (mask)
3643 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3644
3645 return wpa_ie;
3646}
3647
3648
Hai Shalomc3565922019-10-28 11:58:20 -07003649#ifdef CONFIG_OWE
3650static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3651{
3652 struct wpa_driver_associate_params params;
3653 u8 *wpa_ie;
3654
3655 os_memset(&params, 0, sizeof(params));
3656 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3657 wpa_s->current_ssid, &params, NULL);
3658 if (!wpa_ie)
3659 return;
3660
3661 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3662 os_free(wpa_ie);
3663}
3664#endif /* CONFIG_OWE */
3665
3666
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003667#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3668static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3669{
3670 struct wpa_driver_associate_params params;
3671 enum wpa_drv_update_connect_params_mask mask = 0;
3672 u8 *wpa_ie;
3673
3674 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3675 return; /* nothing to do */
3676
3677 os_memset(&params, 0, sizeof(params));
3678 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3679 wpa_s->current_ssid, &params, &mask);
3680 if (!wpa_ie)
3681 return;
3682
Hai Shalomc1a21442022-02-04 13:43:00 -08003683 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3684 wpa_s->auth_alg = params.auth_alg;
3685 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003686 }
3687
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003688 os_free(wpa_ie);
3689}
3690#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3691
3692
Hai Shalomc3565922019-10-28 11:58:20 -07003693static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3694{
3695 if (!edmg_ie || edmg_ie[1] < 6)
3696 return 0;
3697 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3698}
3699
3700
3701static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3702{
3703 if (!edmg_ie || edmg_ie[1] < 6)
3704 return 0;
3705 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3706}
3707
3708
3709/* Returns the intersection of two EDMG configurations.
3710 * Note: The current implementation is limited to CB2 only (CB1 included),
3711 * i.e., the implementation supports up to 2 contiguous channels.
3712 * For supporting non-contiguous (aggregated) channels and for supporting
3713 * CB3 and above, this function will need to be extended.
3714 */
3715static struct ieee80211_edmg_config
3716get_edmg_intersection(struct ieee80211_edmg_config a,
3717 struct ieee80211_edmg_config b,
3718 u8 primary_channel)
3719{
3720 struct ieee80211_edmg_config result;
3721 int i, contiguous = 0;
3722 int max_contiguous = 0;
3723
3724 result.channels = b.channels & a.channels;
3725 if (!result.channels) {
3726 wpa_printf(MSG_DEBUG,
3727 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3728 a.channels, b.channels);
3729 goto fail;
3730 }
3731
3732 if (!(result.channels & BIT(primary_channel - 1))) {
3733 wpa_printf(MSG_DEBUG,
3734 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3735 primary_channel, result.channels);
3736 goto fail;
3737 }
3738
3739 /* Find max contiguous channels */
3740 for (i = 0; i < 6; i++) {
3741 if (result.channels & BIT(i))
3742 contiguous++;
3743 else
3744 contiguous = 0;
3745
3746 if (contiguous > max_contiguous)
3747 max_contiguous = contiguous;
3748 }
3749
3750 /* Assuming AP and STA supports ONLY contiguous channels,
3751 * bw configuration can have value between 4-7.
3752 */
3753 if ((b.bw_config < a.bw_config))
3754 result.bw_config = b.bw_config;
3755 else
3756 result.bw_config = a.bw_config;
3757
3758 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3759 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3760 wpa_printf(MSG_DEBUG,
3761 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3762 max_contiguous);
3763 goto fail;
3764 }
3765
3766 return result;
3767
3768fail:
3769 result.channels = 0;
3770 result.bw_config = 0;
3771 return result;
3772}
3773
3774
3775static struct ieee80211_edmg_config
3776get_supported_edmg(struct wpa_supplicant *wpa_s,
3777 struct hostapd_freq_params *freq,
3778 struct ieee80211_edmg_config request_edmg)
3779{
3780 enum hostapd_hw_mode hw_mode;
3781 struct hostapd_hw_modes *mode = NULL;
3782 u8 primary_channel;
3783
3784 if (!wpa_s->hw.modes)
3785 goto fail;
3786
3787 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3788 if (hw_mode == NUM_HOSTAPD_MODES)
3789 goto fail;
3790
Hai Shalom60840252021-02-19 19:02:11 -08003791 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003792 if (!mode)
3793 goto fail;
3794
3795 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3796
3797fail:
3798 request_edmg.channels = 0;
3799 request_edmg.bw_config = 0;
3800 return request_edmg;
3801}
3802
3803
Hai Shalom021b0b52019-04-10 11:17:58 -07003804#ifdef CONFIG_MBO
3805void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3806{
3807 struct wpa_driver_associate_params params;
3808 u8 *wpa_ie;
3809
3810 /*
3811 * Update MBO connect params only in case of change of MBO attributes
3812 * when connected, if the AP support MBO.
3813 */
3814
3815 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3816 !wpa_s->current_bss ||
3817 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3818 return;
3819
3820 os_memset(&params, 0, sizeof(params));
3821 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3822 wpa_s->current_ssid, &params, NULL);
3823 if (!wpa_ie)
3824 return;
3825
3826 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3827 os_free(wpa_ie);
3828}
3829#endif /* CONFIG_MBO */
3830
3831
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003832static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3833{
3834 struct wpa_connect_work *cwork = work->ctx;
3835 struct wpa_bss *bss = cwork->bss;
3836 struct wpa_ssid *ssid = cwork->ssid;
3837 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003838 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003839 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003840 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003841 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003842 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003843 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003844#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003845 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003846#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003847 int assoc_failed = 0;
3848 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003849 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003850#ifdef CONFIG_HT_OVERRIDES
3851 struct ieee80211_ht_capabilities htcaps;
3852 struct ieee80211_ht_capabilities htcaps_mask;
3853#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003854#ifdef CONFIG_VHT_OVERRIDES
3855 struct ieee80211_vht_capabilities vhtcaps;
3856 struct ieee80211_vht_capabilities vhtcaps_mask;
3857#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003858
Hai Shalomc1a21442022-02-04 13:43:00 -08003859 wpa_s->roam_in_progress = false;
3860#ifdef CONFIG_WNM
3861 wpa_s->bss_trans_mgmt_in_progress = false;
3862#endif /* CONFIG_WNM */
3863
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003864 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003865 if (work->started) {
3866 wpa_s->connect_work = NULL;
3867
3868 /* cancel possible auth. timeout */
3869 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3870 NULL);
3871 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003872 wpas_connect_work_free(cwork);
3873 return;
3874 }
3875
3876 wpa_s->connect_work = work;
3877
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003878 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3879 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003880 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3881 wpas_connect_work_done(wpa_s);
3882 return;
3883 }
3884
Dmitry Shmidte4663042016-04-04 10:07:49 -07003885 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003886 os_memset(&params, 0, sizeof(params));
3887 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003888 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003889
3890 /* Starting new association, so clear the possibly used WPA IE from the
3891 * previous association. */
3892 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3893 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3894 wpa_s->rsnxe_len = 0;
3895 wpa_s->mscs_setup_done = false;
3896
3897 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3898 if (!wpa_ie) {
3899 wpas_connect_work_done(wpa_s);
3900 return;
3901 }
3902
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003903 if (bss &&
3904 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003905#ifdef CONFIG_IEEE80211R
3906 const u8 *ie, *md = NULL;
3907#endif /* CONFIG_IEEE80211R */
3908 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3909 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3910 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3911 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3912 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3913 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3914 if (bssid_changed)
3915 wpas_notify_bssid_changed(wpa_s);
3916#ifdef CONFIG_IEEE80211R
3917 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3918 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3919 md = ie + 2;
3920 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3921 if (md) {
3922 /* Prepare for the next transition */
3923 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3924 }
3925#endif /* CONFIG_IEEE80211R */
3926#ifdef CONFIG_WPS
3927 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3928 wpa_s->conf->ap_scan == 2 &&
3929 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3930 /* Use ap_scan==1 style network selection to find the network
3931 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003932 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003933 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934 wpa_s->reassociate = 1;
3935 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003936 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937 return;
3938#endif /* CONFIG_WPS */
3939 } else {
3940 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3941 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003942 if (bss)
3943 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3944 else
3945 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003947 if (!wpa_s->pno)
3948 wpa_supplicant_cancel_sched_scan(wpa_s);
3949
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003950 wpa_supplicant_cancel_scan(wpa_s);
3951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003952 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3953 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003954 cipher_pairwise = wpa_s->pairwise_cipher;
3955 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003956 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003957 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3958 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3959 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3960 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003961#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003962 if (wpa_set_wep_keys(wpa_s, ssid)) {
3963 use_crypt = 1;
3964 wep_keys_set = 1;
3965 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003966#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 }
3968 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3969 use_crypt = 0;
3970
3971#ifdef IEEE8021X_EAPOL
3972 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3973 if ((ssid->eapol_flags &
3974 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3975 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3976 !wep_keys_set) {
3977 use_crypt = 0;
3978 } else {
3979 /* Assume that dynamic WEP-104 keys will be used and
3980 * set cipher suites in order for drivers to expect
3981 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003982 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 }
3984 }
3985#endif /* IEEE8021X_EAPOL */
3986
3987 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3988 /* Set the key before (and later after) association */
3989 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3990 }
3991
Sunil8cd6f4d2022-06-28 18:40:46 +00003992 /* Set current_ssid before changing state to ASSOCIATING, so that the
3993 * selected SSID is available to wpas_notify_state_changed(). */
3994 old_ssid = wpa_s->current_ssid;
3995 wpa_s->current_ssid = ssid;
3996
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3998 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 params.ssid = bss->ssid;
4000 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004001 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4002 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004003 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4004 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004005 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004006 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004007 ssid->bssid_set,
4008 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004009 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004010 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004011 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004012 params.bssid_hint = bss->bssid;
4013 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004014 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004016 if (ssid->bssid_hint_set)
4017 params.bssid_hint = ssid->bssid_hint;
4018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004019 params.ssid = ssid->ssid;
4020 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004021 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004022 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004023
4024 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4025 wpa_s->conf->ap_scan == 2) {
4026 params.bssid = ssid->bssid;
4027 params.fixed_bssid = 1;
4028 }
4029
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004030 /* Initial frequency for IBSS/mesh */
4031 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004032 ssid->frequency > 0 && params.freq.freq == 0)
4033 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004034
4035 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004036 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004037 if (ssid->beacon_int)
4038 params.beacon_int = ssid->beacon_int;
4039 else
4040 params.beacon_int = wpa_s->conf->beacon_int;
4041 }
4042
Hai Shalomc3565922019-10-28 11:58:20 -07004043 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004044 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4045 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004046 else
4047 edmg_ie_oper = NULL;
4048
4049 if (edmg_ie_oper) {
4050 params.freq.edmg.channels =
4051 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4052 params.freq.edmg.bw_config =
4053 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4054 wpa_printf(MSG_DEBUG,
4055 "AP supports EDMG channels 0x%x, bw_config %d",
4056 params.freq.edmg.channels,
4057 params.freq.edmg.bw_config);
4058
4059 /* User may ask for specific EDMG channel for EDMG connection
4060 * (must be supported by AP)
4061 */
4062 if (ssid->edmg_channel) {
4063 struct ieee80211_edmg_config configured_edmg;
4064 enum hostapd_hw_mode hw_mode;
4065 u8 primary_channel;
4066
4067 hw_mode = ieee80211_freq_to_chan(bss->freq,
4068 &primary_channel);
4069 if (hw_mode == NUM_HOSTAPD_MODES)
4070 goto edmg_fail;
4071
4072 hostapd_encode_edmg_chan(ssid->enable_edmg,
4073 ssid->edmg_channel,
4074 primary_channel,
4075 &configured_edmg);
4076
4077 if (ieee802_edmg_is_allowed(params.freq.edmg,
4078 configured_edmg)) {
4079 params.freq.edmg = configured_edmg;
4080 wpa_printf(MSG_DEBUG,
4081 "Use EDMG channel %d for connection",
4082 ssid->edmg_channel);
4083 } else {
4084 edmg_fail:
4085 params.freq.edmg.channels = 0;
4086 params.freq.edmg.bw_config = 0;
4087 wpa_printf(MSG_WARNING,
4088 "EDMG channel %d not supported by AP, fallback to DMG",
4089 ssid->edmg_channel);
4090 }
4091 }
4092
4093 if (params.freq.edmg.channels) {
4094 wpa_printf(MSG_DEBUG,
4095 "EDMG before: channels 0x%x, bw_config %d",
4096 params.freq.edmg.channels,
4097 params.freq.edmg.bw_config);
4098 params.freq.edmg = get_supported_edmg(wpa_s,
4099 &params.freq,
4100 params.freq.edmg);
4101 wpa_printf(MSG_DEBUG,
4102 "EDMG after: channels 0x%x, bw_config %d",
4103 params.freq.edmg.channels,
4104 params.freq.edmg.bw_config);
4105 }
4106 }
4107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004108 params.pairwise_suite = cipher_pairwise;
4109 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004110 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004111 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004112 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004113 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004114 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004115 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004116 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004117#ifdef CONFIG_WEP
4118 {
4119 int i;
4120
4121 for (i = 0; i < NUM_WEP_KEYS; i++) {
4122 if (ssid->wep_key_len[i])
4123 params.wep_key[i] = ssid->wep_key[i];
4124 params.wep_key_len[i] = ssid->wep_key_len[i];
4125 }
4126 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004128#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129
Hai Shalom74f70d42019-02-11 14:42:39 -08004130 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004131#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004132 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4133 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304134#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004135 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4136 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4137 (params.allowed_key_mgmts &
4138 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004139#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004140 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004141 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4142 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143 }
4144
Hai Shalom74f70d42019-02-11 14:42:39 -08004145 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4146 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4147 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4148 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4149 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004150 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004151
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004152 if (wpa_s->conf->key_mgmt_offload) {
4153 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4154 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004155 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4156 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004157 params.req_key_mgmt_offload =
4158 ssid->proactive_key_caching < 0 ?
4159 wpa_s->conf->okc : ssid->proactive_key_caching;
4160 else
4161 params.req_key_mgmt_offload = 1;
4162
Winnie Chen4138eec2022-11-10 16:32:53 +08004163#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004164 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004165 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4166 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004167#else
4168 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4169 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004170#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004171 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4172 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004173 }
4174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 params.drop_unencrypted = use_crypt;
4176
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004177 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004178 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4180 struct wpa_ie_data ie;
4181 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4182 ie.capabilities &
4183 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4184 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4185 "MFP: require MFP");
4186 params.mgmt_frame_protection =
4187 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004188#ifdef CONFIG_OWE
4189 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4190 !ssid->owe_only) {
4191 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4192#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004193 }
4194 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004196 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004197
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004198 if (wpa_s->p2pdev->set_sta_uapsd)
4199 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004200 else
4201 params.uapsd = -1;
4202
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004203#ifdef CONFIG_HT_OVERRIDES
4204 os_memset(&htcaps, 0, sizeof(htcaps));
4205 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4206 params.htcaps = (u8 *) &htcaps;
4207 params.htcaps_mask = (u8 *) &htcaps_mask;
4208 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4209#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004210#ifdef CONFIG_VHT_OVERRIDES
4211 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4212 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4213 params.vhtcaps = &vhtcaps;
4214 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004215 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004216#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004217#ifdef CONFIG_HE_OVERRIDES
4218 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4219#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004220 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004221
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004222#ifdef CONFIG_P2P
4223 /*
4224 * If multi-channel concurrency is not supported, check for any
4225 * frequency conflict. In case of any frequency conflict, remove the
4226 * least prioritized connection.
4227 */
4228 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004229 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004230 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004231 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004232 wpa_printf(MSG_DEBUG,
4233 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004234 freq, params.freq.freq);
4235 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004236 wpa_s, params.freq.freq, ssid) < 0) {
4237 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004238 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004239 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004240 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004241 }
4242 }
4243#endif /* CONFIG_P2P */
4244
Dmitry Shmidte4663042016-04-04 10:07:49 -07004245 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004246 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004247 params.prev_bssid = prev_bssid;
4248
Hai Shalom60840252021-02-19 19:02:11 -08004249#ifdef CONFIG_SAE
4250 params.sae_pwe = wpa_s->conf->sae_pwe;
4251#endif /* CONFIG_SAE */
4252
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004253 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004254 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004255 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004256 if (ret < 0) {
4257 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4258 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004259 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004260 /*
4261 * The driver is known to mean what is saying, so we
4262 * can stop right here; the association will not
4263 * succeed.
4264 */
4265 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004266 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004267 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004268 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4270 return;
4271 }
4272 /* try to continue anyway; new association will be tried again
4273 * after timeout */
4274 assoc_failed = 1;
4275 }
4276
4277 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4278 /* Set the key after the association just in case association
4279 * cleared the previously configured key. */
4280 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4281 /* No need to timeout authentication since there is no key
4282 * management. */
4283 wpa_supplicant_cancel_auth_timeout(wpa_s);
4284 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4285#ifdef CONFIG_IBSS_RSN
4286 } else if (ssid->mode == WPAS_MODE_IBSS &&
4287 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4288 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4289 /*
4290 * RSN IBSS authentication is per-STA and we can disable the
4291 * per-BSSID authentication.
4292 */
4293 wpa_supplicant_cancel_auth_timeout(wpa_s);
4294#endif /* CONFIG_IBSS_RSN */
4295 } else {
4296 /* Timeout for IEEE 802.11 authentication and association */
4297 int timeout = 60;
4298
4299 if (assoc_failed) {
4300 /* give IBSS a bit more time */
4301 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4302 } else if (wpa_s->conf->ap_scan == 1) {
4303 /* give IBSS a bit more time */
4304 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4305 }
4306 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4307 }
4308
Hai Shalomfdcde762020-04-02 11:19:20 -07004309#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004310 if (wep_keys_set &&
4311 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312 /* Set static WEP keys again */
4313 wpa_set_wep_keys(wpa_s, ssid);
4314 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004315#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004316
Sunil8cd6f4d2022-06-28 18:40:46 +00004317 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004318 /*
4319 * Do not allow EAP session resumption between different
4320 * network configurations.
4321 */
4322 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4323 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004324
4325 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004326 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004327#ifdef CONFIG_HS20
4328 hs20_configure_frame_filters(wpa_s);
4329#endif /* CONFIG_HS20 */
4330 }
4331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4333 wpa_supplicant_initiate_eapol(wpa_s);
4334 if (old_ssid != wpa_s->current_ssid)
4335 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004336 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4337 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004338}
4339
4340
4341static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4342 const u8 *addr)
4343{
4344 struct wpa_ssid *old_ssid;
4345
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004346 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004349 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004350 wpa_sm_set_config(wpa_s->wpa, NULL);
4351 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4352 if (old_ssid != wpa_s->current_ssid)
4353 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004354
4355 wpas_scs_deinit(wpa_s);
4356 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004357 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4358}
4359
4360
4361/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4363 * @wpa_s: Pointer to wpa_supplicant data
4364 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4365 *
4366 * This function is used to request %wpa_supplicant to deauthenticate from the
4367 * current AP.
4368 */
4369void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004370 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004371{
4372 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004373 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004374 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004376 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004377 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004378 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004379 reason_code, reason2str(reason_code),
4380 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004381
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004382 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4383 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4384 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004385 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004386 else if (!is_zero_ether_addr(wpa_s->bssid))
4387 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004388 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4389 /*
4390 * When using driver-based BSS selection, we may not know the
4391 * BSSID with which we are currently trying to associate. We
4392 * need to notify the driver of this disconnection even in such
4393 * a case, so use the all zeros address here.
4394 */
4395 addr = wpa_s->bssid;
4396 zero_addr = 1;
4397 }
4398
Hai Shalom74f70d42019-02-11 14:42:39 -08004399 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4400 wpa_s->enabled_4addr_mode = 0;
4401
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004402#ifdef CONFIG_TDLS
4403 wpa_tdls_teardown_peers(wpa_s->wpa);
4404#endif /* CONFIG_TDLS */
4405
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004406#ifdef CONFIG_MESH
4407 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004408 struct mesh_conf *mconf;
4409
4410 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004411 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4412 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004413 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4414 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004415 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004416 }
4417#endif /* CONFIG_MESH */
4418
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004419 if (addr) {
4420 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004421 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004422 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004423 event.deauth_info.locally_generated = 1;
4424 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004425 if (zero_addr)
4426 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004427 }
4428
4429 wpa_supplicant_clear_connection(wpa_s, addr);
4430}
4431
Hai Shalomfdcde762020-04-02 11:19:20 -07004432
4433void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4434{
4435 wpa_s->own_reconnect_req = 1;
4436 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4437
4438}
4439
4440
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004441static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4442 struct wpa_ssid *ssid)
4443{
4444 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4445 return;
4446
4447 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004448 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004449 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4450 wpas_notify_network_enabled_changed(wpa_s, ssid);
4451
4452 /*
4453 * Try to reassociate since there is no current configuration and a new
4454 * network was made available.
4455 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004456 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004457 wpa_s->reassociate = 1;
4458}
4459
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004460
Roshan Pius950bec92016-07-19 09:49:24 -07004461/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004462 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004463 * @wpa_s: wpa_supplicant structure for a network interface
4464 * Returns: The new network configuration or %NULL if operation failed
4465 *
4466 * This function performs the following operations:
4467 * 1. Adds a new network.
4468 * 2. Send network addition notification.
4469 * 3. Marks the network disabled.
4470 * 4. Set network default parameters.
4471 */
4472struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4473{
4474 struct wpa_ssid *ssid;
4475
4476 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004477 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004478 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004479 wpas_notify_network_added(wpa_s, ssid);
4480 ssid->disabled = 1;
4481 wpa_config_set_network_defaults(ssid);
4482
4483 return ssid;
4484}
4485
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004486
Roshan Pius950bec92016-07-19 09:49:24 -07004487/**
4488 * wpa_supplicant_remove_network - Remove a configured network based on id
4489 * @wpa_s: wpa_supplicant structure for a network interface
4490 * @id: Unique network id to search for
4491 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4492 * could not be removed
4493 *
4494 * This function performs the following operations:
4495 * 1. Removes the network.
4496 * 2. Send network removal notification.
4497 * 3. Update internal state machines.
4498 * 4. Stop any running sched scans.
4499 */
4500int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4501{
Sunil Ravia04bd252022-05-02 22:54:18 -07004502 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004503 int was_disabled;
4504
4505 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004506 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004507 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004508 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004509
Sunil Ravia04bd252022-05-02 22:54:18 -07004510 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004511#ifdef CONFIG_SME
4512 wpa_s->sme.prev_bssid_set = 0;
4513#endif /* CONFIG_SME */
4514 /*
4515 * Invalidate the EAP session cache if the current or
4516 * previously used network is removed.
4517 */
4518 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4519 }
4520
Sunil Ravia04bd252022-05-02 22:54:18 -07004521 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004522 wpa_sm_set_config(wpa_s->wpa, NULL);
4523 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4524
4525 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4526 wpa_s->own_disconnect_req = 1;
4527 wpa_supplicant_deauthenticate(wpa_s,
4528 WLAN_REASON_DEAUTH_LEAVING);
4529 }
4530
4531 was_disabled = ssid->disabled;
4532
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004533 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004534 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004535
4536 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004537 wpa_printf(MSG_DEBUG,
4538 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004539 wpa_supplicant_cancel_sched_scan(wpa_s);
4540 wpa_supplicant_req_scan(wpa_s, 0, 0);
4541 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004542
Roshan Pius950bec92016-07-19 09:49:24 -07004543 return 0;
4544}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004545
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004546
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004548 * wpa_supplicant_remove_all_networks - Remove all configured networks
4549 * @wpa_s: wpa_supplicant structure for a network interface
4550 * Returns: 0 on success (errors are currently ignored)
4551 *
4552 * This function performs the following operations:
4553 * 1. Remove all networks.
4554 * 2. Send network removal notifications.
4555 * 3. Update internal state machines.
4556 * 4. Stop any running sched scans.
4557 */
4558int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4559{
4560 struct wpa_ssid *ssid;
4561
4562 if (wpa_s->sched_scanning)
4563 wpa_supplicant_cancel_sched_scan(wpa_s);
4564
4565 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4566 if (wpa_s->current_ssid) {
4567#ifdef CONFIG_SME
4568 wpa_s->sme.prev_bssid_set = 0;
4569#endif /* CONFIG_SME */
4570 wpa_sm_set_config(wpa_s->wpa, NULL);
4571 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4572 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4573 wpa_s->own_disconnect_req = 1;
4574 wpa_supplicant_deauthenticate(
4575 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4576 }
4577 ssid = wpa_s->conf->ssid;
4578 while (ssid) {
4579 struct wpa_ssid *remove_ssid = ssid;
4580 int id;
4581
4582 id = ssid->id;
4583 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004584 wpas_notify_network_removed(wpa_s, remove_ssid);
4585 wpa_config_remove_network(wpa_s->conf, id);
4586 }
4587 return 0;
4588}
4589
4590
4591/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004592 * wpa_supplicant_enable_network - Mark a configured network as enabled
4593 * @wpa_s: wpa_supplicant structure for a network interface
4594 * @ssid: wpa_ssid structure for a configured network or %NULL
4595 *
4596 * Enables the specified network or all networks if no network specified.
4597 */
4598void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4599 struct wpa_ssid *ssid)
4600{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004601 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004602 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4603 wpa_supplicant_enable_one_network(wpa_s, ssid);
4604 } else
4605 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004607 if (wpa_s->reassociate && !wpa_s->disconnected &&
4608 (!wpa_s->current_ssid ||
4609 wpa_s->wpa_state == WPA_DISCONNECTED ||
4610 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004611 if (wpa_s->sched_scanning) {
4612 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4613 "new network to scan filters");
4614 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615 }
4616
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004617 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4618 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004619 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004620 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004621 }
4622}
4623
4624
4625/**
4626 * wpa_supplicant_disable_network - Mark a configured network as disabled
4627 * @wpa_s: wpa_supplicant structure for a network interface
4628 * @ssid: wpa_ssid structure for a configured network or %NULL
4629 *
4630 * Disables the specified network or all networks if no network specified.
4631 */
4632void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4633 struct wpa_ssid *ssid)
4634{
4635 struct wpa_ssid *other_ssid;
4636 int was_disabled;
4637
4638 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004639 if (wpa_s->sched_scanning)
4640 wpa_supplicant_cancel_sched_scan(wpa_s);
4641
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4643 other_ssid = other_ssid->next) {
4644 was_disabled = other_ssid->disabled;
4645 if (was_disabled == 2)
4646 continue; /* do not change persistent P2P group
4647 * data */
4648
4649 other_ssid->disabled = 1;
4650
4651 if (was_disabled != other_ssid->disabled)
4652 wpas_notify_network_enabled_changed(
4653 wpa_s, other_ssid);
4654 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004655 if (wpa_s->current_ssid) {
4656 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4657 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004658 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004659 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004660 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004661 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004662 if (ssid == wpa_s->current_ssid) {
4663 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4664 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004665 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004666 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004667 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004668
4669 was_disabled = ssid->disabled;
4670
4671 ssid->disabled = 1;
4672
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004673 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004674 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004675 if (wpa_s->sched_scanning) {
4676 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4677 "to remove network from filters");
4678 wpa_supplicant_cancel_sched_scan(wpa_s);
4679 wpa_supplicant_req_scan(wpa_s, 0, 0);
4680 }
4681 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004682 }
4683}
4684
4685
4686/**
4687 * wpa_supplicant_select_network - Attempt association with a network
4688 * @wpa_s: wpa_supplicant structure for a network interface
4689 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4690 */
4691void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4692 struct wpa_ssid *ssid)
4693{
4694
4695 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004696 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004697
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004698 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004699 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4700 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004701 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004703 disconnected = 1;
4704 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004705
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004706 if (ssid)
4707 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 /*
4710 * Mark all other networks disabled or mark all networks enabled if no
4711 * network specified.
4712 */
4713 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4714 other_ssid = other_ssid->next) {
4715 int was_disabled = other_ssid->disabled;
4716 if (was_disabled == 2)
4717 continue; /* do not change persistent P2P group data */
4718
4719 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004720 if (was_disabled && !other_ssid->disabled)
4721 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722
4723 if (was_disabled != other_ssid->disabled)
4724 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4725 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004726
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004727 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4728 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004729 /* We are already associated with the selected network */
4730 wpa_printf(MSG_DEBUG, "Already associated with the "
4731 "selected network - do nothing");
4732 return;
4733 }
4734
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004735 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004736 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004737 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004738 wpa_s->connect_without_scan =
4739 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004740
4741 /*
4742 * Don't optimize next scan freqs since a new ESS has been
4743 * selected.
4744 */
4745 os_free(wpa_s->next_scan_freqs);
4746 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004747 } else {
4748 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004749 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751 wpa_s->disconnected = 0;
4752 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004753 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004754 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004755 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004756 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004757 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4758 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004759
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004760 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004761 wpa_supplicant_fast_associate(wpa_s) != 1) {
4762 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004763 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004764 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004765 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766
4767 if (ssid)
4768 wpas_notify_network_selected(wpa_s, ssid);
4769}
4770
4771
4772/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004773 * wpas_remove_cred - Remove the specified credential and all the network
4774 * entries created based on the removed credential
4775 * @wpa_s: wpa_supplicant structure for a network interface
4776 * @cred: The credential to remove
4777 * Returns: 0 on success, -1 on failure
4778 */
4779int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4780{
4781 struct wpa_ssid *ssid, *next;
4782 int id;
4783
4784 if (!cred) {
4785 wpa_printf(MSG_DEBUG, "Could not find cred");
4786 return -1;
4787 }
4788
4789 id = cred->id;
4790 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4791 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4792 return -1;
4793 }
4794
4795 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4796
4797 /* Remove any network entry created based on the removed credential */
4798 ssid = wpa_s->conf->ssid;
4799 while (ssid) {
4800 next = ssid->next;
4801
4802 if (ssid->parent_cred == cred) {
4803 wpa_printf(MSG_DEBUG,
4804 "Remove network id %d since it used the removed credential",
4805 ssid->id);
4806 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4807 -1) {
4808 wpa_printf(MSG_DEBUG,
4809 "Could not find network id=%d",
4810 ssid->id);
4811 }
4812 }
4813
4814 ssid = next;
4815 }
4816
4817 return 0;
4818}
4819
4820
4821/**
4822 * wpas_remove_cred - Remove all the Interworking credentials
4823 * @wpa_s: wpa_supplicant structure for a network interface
4824 * Returns: 0 on success, -1 on failure
4825 */
4826int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4827{
4828 int res, ret = 0;
4829 struct wpa_cred *cred, *prev;
4830
4831 cred = wpa_s->conf->cred;
4832 while (cred) {
4833 prev = cred;
4834 cred = cred->next;
4835 res = wpas_remove_cred(wpa_s, prev);
4836 if (res < 0) {
4837 wpa_printf(MSG_DEBUG,
4838 "Removal of all credentials failed - failed to remove credential id=%d",
4839 prev->id);
4840 ret = -1;
4841 }
4842 }
4843
4844 return ret;
4845}
4846
4847
4848/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004849 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4850 * @wpa_s: wpa_supplicant structure for a network interface
4851 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4852 * @pkcs11_module_path: PKCS #11 module path or NULL
4853 * Returns: 0 on success; -1 on failure
4854 *
4855 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4856 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4857 * module path fails the paths will be reset to the default value (NULL).
4858 */
4859int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4860 const char *pkcs11_engine_path,
4861 const char *pkcs11_module_path)
4862{
4863 char *pkcs11_engine_path_copy = NULL;
4864 char *pkcs11_module_path_copy = NULL;
4865
4866 if (pkcs11_engine_path != NULL) {
4867 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4868 if (pkcs11_engine_path_copy == NULL)
4869 return -1;
4870 }
4871 if (pkcs11_module_path != NULL) {
4872 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004873 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004874 os_free(pkcs11_engine_path_copy);
4875 return -1;
4876 }
4877 }
4878
4879 os_free(wpa_s->conf->pkcs11_engine_path);
4880 os_free(wpa_s->conf->pkcs11_module_path);
4881 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4882 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4883
4884 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4885 eapol_sm_deinit(wpa_s->eapol);
4886 wpa_s->eapol = NULL;
4887 if (wpa_supplicant_init_eapol(wpa_s)) {
4888 /* Error -> Reset paths to the default value (NULL) once. */
4889 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4890 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4891 NULL);
4892
4893 return -1;
4894 }
4895 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4896
4897 return 0;
4898}
4899
4900
4901/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4903 * @wpa_s: wpa_supplicant structure for a network interface
4904 * @ap_scan: AP scan mode
4905 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4906 *
4907 */
4908int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4909{
4910
4911 int old_ap_scan;
4912
4913 if (ap_scan < 0 || ap_scan > 2)
4914 return -1;
4915
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004916 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4917 wpa_printf(MSG_INFO,
4918 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4919 }
4920
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004921#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004922 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4923 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4924 wpa_s->wpa_state < WPA_COMPLETED) {
4925 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4926 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004927 return 0;
4928 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004929#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004930
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004931 old_ap_scan = wpa_s->conf->ap_scan;
4932 wpa_s->conf->ap_scan = ap_scan;
4933
4934 if (old_ap_scan != wpa_s->conf->ap_scan)
4935 wpas_notify_ap_scan_changed(wpa_s);
4936
4937 return 0;
4938}
4939
4940
4941/**
4942 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4943 * @wpa_s: wpa_supplicant structure for a network interface
4944 * @expire_age: Expiration age in seconds
4945 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4946 *
4947 */
4948int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4949 unsigned int bss_expire_age)
4950{
4951 if (bss_expire_age < 10) {
4952 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4953 bss_expire_age);
4954 return -1;
4955 }
4956 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4957 bss_expire_age);
4958 wpa_s->conf->bss_expiration_age = bss_expire_age;
4959
4960 return 0;
4961}
4962
4963
4964/**
4965 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4966 * @wpa_s: wpa_supplicant structure for a network interface
4967 * @expire_count: number of scans after which an unseen BSS is reclaimed
4968 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4969 *
4970 */
4971int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4972 unsigned int bss_expire_count)
4973{
4974 if (bss_expire_count < 1) {
4975 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4976 bss_expire_count);
4977 return -1;
4978 }
4979 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4980 bss_expire_count);
4981 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4982
4983 return 0;
4984}
4985
4986
4987/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004988 * wpa_supplicant_set_scan_interval - Set scan interval
4989 * @wpa_s: wpa_supplicant structure for a network interface
4990 * @scan_interval: scan interval in seconds
4991 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4992 *
4993 */
4994int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4995 int scan_interval)
4996{
4997 if (scan_interval < 0) {
4998 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4999 scan_interval);
5000 return -1;
5001 }
5002 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5003 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005004 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005005
5006 return 0;
5007}
5008
5009
5010/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005011 * wpa_supplicant_set_debug_params - Set global debug params
5012 * @global: wpa_global structure
5013 * @debug_level: debug level
5014 * @debug_timestamp: determines if show timestamp in debug data
5015 * @debug_show_keys: determines if show keys in debug data
5016 * Returns: 0 if succeed or -1 if debug_level has wrong value
5017 */
5018int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5019 int debug_timestamp, int debug_show_keys)
5020{
5021
5022 int old_level, old_timestamp, old_show_keys;
5023
5024 /* check for allowed debuglevels */
5025 if (debug_level != MSG_EXCESSIVE &&
5026 debug_level != MSG_MSGDUMP &&
5027 debug_level != MSG_DEBUG &&
5028 debug_level != MSG_INFO &&
5029 debug_level != MSG_WARNING &&
5030 debug_level != MSG_ERROR)
5031 return -1;
5032
5033 old_level = wpa_debug_level;
5034 old_timestamp = wpa_debug_timestamp;
5035 old_show_keys = wpa_debug_show_keys;
5036
5037 wpa_debug_level = debug_level;
5038 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5039 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5040
5041 if (wpa_debug_level != old_level)
5042 wpas_notify_debug_level_changed(global);
5043 if (wpa_debug_timestamp != old_timestamp)
5044 wpas_notify_debug_timestamp_changed(global);
5045 if (wpa_debug_show_keys != old_show_keys)
5046 wpas_notify_debug_show_keys_changed(global);
5047
5048 return 0;
5049}
5050
5051
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005052#ifdef CONFIG_OWE
5053static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5054 const u8 *entry_ssid, size_t entry_ssid_len)
5055{
5056 const u8 *owe, *pos, *end;
5057 u8 ssid_len;
5058 struct wpa_bss *bss;
5059
5060 /* Check network profile SSID aganst the SSID in the
5061 * OWE Transition Mode element. */
5062
5063 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5064 if (!bss)
5065 return 0;
5066
5067 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5068 if (!owe)
5069 return 0;
5070
5071 pos = owe + 6;
5072 end = owe + 2 + owe[1];
5073
5074 if (end - pos < ETH_ALEN + 1)
5075 return 0;
5076 pos += ETH_ALEN;
5077 ssid_len = *pos++;
5078 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5079 return 0;
5080
5081 return entry_ssid_len == ssid_len &&
5082 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5083}
5084#endif /* CONFIG_OWE */
5085
5086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087/**
5088 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5089 * @wpa_s: Pointer to wpa_supplicant data
5090 * Returns: A pointer to the current network structure or %NULL on failure
5091 */
5092struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5093{
5094 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005095 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005096 int res;
5097 size_t ssid_len;
5098 u8 bssid[ETH_ALEN];
5099 int wired;
5100
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005101 res = wpa_drv_get_ssid(wpa_s, ssid);
5102 if (res < 0) {
5103 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5104 "driver");
5105 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005107 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005109 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005110 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5111 "driver");
5112 return NULL;
5113 }
5114
5115 wired = wpa_s->conf->ap_scan == 0 &&
5116 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5117
5118 entry = wpa_s->conf->ssid;
5119 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005120 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005121 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005122 (!entry->ssid ||
5123 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5124 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005125 (!entry->bssid_set ||
5126 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5127 return entry;
5128#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005129 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005130 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5131 (entry->ssid == NULL || entry->ssid_len == 0) &&
5132 (!entry->bssid_set ||
5133 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5134 return entry;
5135#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005136
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005137#ifdef CONFIG_OWE
5138 if (!wpas_network_disabled(wpa_s, entry) &&
5139 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5140 entry->ssid_len) &&
5141 (!entry->bssid_set ||
5142 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5143 return entry;
5144#endif /* CONFIG_OWE */
5145
Dmitry Shmidt04949592012-07-19 12:16:46 -07005146 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005147 entry->ssid_len == 0 &&
5148 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5149 return entry;
5150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151 entry = entry->next;
5152 }
5153
5154 return NULL;
5155}
5156
5157
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005158static int select_driver(struct wpa_supplicant *wpa_s, int i)
5159{
5160 struct wpa_global *global = wpa_s->global;
5161
5162 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005163 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005164 if (global->drv_priv[i] == NULL) {
5165 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5166 "'%s'", wpa_drivers[i]->name);
5167 return -1;
5168 }
5169 }
5170
5171 wpa_s->driver = wpa_drivers[i];
5172 wpa_s->global_drv_priv = global->drv_priv[i];
5173
5174 return 0;
5175}
5176
5177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005178static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5179 const char *name)
5180{
5181 int i;
5182 size_t len;
5183 const char *pos, *driver = name;
5184
5185 if (wpa_s == NULL)
5186 return -1;
5187
5188 if (wpa_drivers[0] == NULL) {
5189 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5190 "wpa_supplicant");
5191 return -1;
5192 }
5193
5194 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005195 /* Default to first successful driver in the list */
5196 for (i = 0; wpa_drivers[i]; i++) {
5197 if (select_driver(wpa_s, i) == 0)
5198 return 0;
5199 }
5200 /* Drivers have each reported failure, so no wpa_msg() here. */
5201 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202 }
5203
5204 do {
5205 pos = os_strchr(driver, ',');
5206 if (pos)
5207 len = pos - driver;
5208 else
5209 len = os_strlen(driver);
5210
5211 for (i = 0; wpa_drivers[i]; i++) {
5212 if (os_strlen(wpa_drivers[i]->name) == len &&
5213 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005214 0) {
5215 /* First driver that succeeds wins */
5216 if (select_driver(wpa_s, i) == 0)
5217 return 0;
5218 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005219 }
5220
5221 driver = pos + 1;
5222 } while (pos);
5223
5224 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5225 return -1;
5226}
5227
5228
5229/**
5230 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5231 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5232 * with struct wpa_driver_ops::init()
5233 * @src_addr: Source address of the EAPOL frame
5234 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5235 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005236 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005237 *
5238 * This function is called for each received EAPOL frame. Most driver
5239 * interfaces rely on more generic OS mechanism for receiving frames through
5240 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5241 * take care of received EAPOL frames and deliver them to the core supplicant
5242 * code by calling this function.
5243 */
5244void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005245 const u8 *buf, size_t len,
5246 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005247{
5248 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005249 const u8 *connected_addr = wpa_s->valid_links ?
5250 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005251
Sunil8cd6f4d2022-06-28 18:40:46 +00005252 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5253 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005254 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5255
Hai Shalomc1a21442022-02-04 13:43:00 -08005256 if (wpa_s->own_disconnect_req) {
5257 wpa_printf(MSG_DEBUG,
5258 "Drop received EAPOL frame as we are disconnecting");
5259 return;
5260 }
5261
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005262#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005263 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5264 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005265 if (wpa_s->ignore_auth_resp) {
5266 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5267 return;
5268 }
5269#endif /* CONFIG_TESTING_OPTIONS */
5270
Jouni Malinena05074c2012-12-21 21:35:35 +02005271 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5272 (wpa_s->last_eapol_matches_bssid &&
5273#ifdef CONFIG_AP
5274 !wpa_s->ap_iface &&
5275#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005276 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005277 /*
5278 * There is possible race condition between receiving the
5279 * association event and the EAPOL frame since they are coming
5280 * through different paths from the driver. In order to avoid
5281 * issues in trying to process the EAPOL frame before receiving
5282 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005283 * the association event is received. This may also be needed in
5284 * driver-based roaming case, so also use src_addr != BSSID as a
5285 * trigger if we have previously confirmed that the
5286 * Authenticator uses BSSID as the src_addr (which is not the
5287 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005288 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005289 wpa_dbg(wpa_s, MSG_DEBUG,
5290 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5291 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005292 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005293 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005294 wpabuf_free(wpa_s->pending_eapol_rx);
5295 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5296 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005297 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005298 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5299 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005300 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005301 }
5302 return;
5303 }
5304
Jouni Malinena05074c2012-12-21 21:35:35 +02005305 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005306 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005308#ifdef CONFIG_AP
5309 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005310 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5311 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005312 return;
5313 }
5314#endif /* CONFIG_AP */
5315
5316 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5317 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5318 "no key management is configured");
5319 return;
5320 }
5321
5322 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005323 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005324 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5325 wpa_s->wpa_state != WPA_COMPLETED) &&
5326 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005327 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005329 int timeout = 10;
5330
5331 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5332 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5333 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5334 /* Use longer timeout for IEEE 802.1X/EAP */
5335 timeout = 70;
5336 }
5337
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005338#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005339 if (wpa_s->current_ssid && wpa_s->current_bss &&
5340 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5341 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5342 /*
5343 * Use shorter timeout if going through WPS AP iteration
5344 * for PIN config method with an AP that does not
5345 * advertise Selected Registrar.
5346 */
5347 struct wpabuf *wps_ie;
5348
5349 wps_ie = wpa_bss_get_vendor_ie_multi(
5350 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5351 if (wps_ie &&
5352 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5353 timeout = 10;
5354 wpabuf_free(wps_ie);
5355 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005356#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005357
5358 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005359 }
5360 wpa_s->eapol_received++;
5361
5362 if (wpa_s->countermeasures) {
5363 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5364 "EAPOL packet");
5365 return;
5366 }
5367
5368#ifdef CONFIG_IBSS_RSN
5369 if (wpa_s->current_ssid &&
5370 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005371 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5372 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373 return;
5374 }
5375#endif /* CONFIG_IBSS_RSN */
5376
5377 /* Source address of the incoming EAPOL frame could be compared to the
5378 * current BSSID. However, it is possible that a centralized
5379 * Authenticator could be using another MAC address than the BSSID of
5380 * an AP, so just allow any address to be used for now. The replies are
5381 * still sent to the current BSSID (if available), though. */
5382
5383 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5384 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005385 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5386 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005387 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5388 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005389 return;
5390 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005391 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005392 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005393 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5394 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005395 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005396 * handshake processing which would normally set portValid. We
5397 * need this to allow the EAPOL state machines to be completed
5398 * without going through EAPOL-Key handshake.
5399 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005400 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005401 }
5402}
5403
5404
Sunil8cd6f4d2022-06-28 18:40:46 +00005405static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5406 const u8 *buf, size_t len)
5407{
5408 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5409 FRAME_ENCRYPTION_UNKNOWN);
5410}
5411
5412
Hai Shalomb755a2a2020-04-23 21:49:02 -07005413static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5414{
5415 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5416 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5417}
5418
5419
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005420int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005421{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005422 u8 prev_mac_addr[ETH_ALEN];
5423
5424 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5425
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005426 if ((!wpa_s->p2p_mgmt ||
5427 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5428 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005429 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005430 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5431 wpa_drv_get_mac_addr(wpa_s),
5432 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005433 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005434 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005435 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005436 if (wpa_s->l2 == NULL)
5437 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005438
5439 if (l2_packet_set_packet_filter(wpa_s->l2,
5440 L2_PACKET_FILTER_PKTTYPE))
5441 wpa_dbg(wpa_s, MSG_DEBUG,
5442 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005443
5444 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5445 wpa_msg(wpa_s, MSG_ERROR,
5446 "Failed to get own L2 address");
5447 return -1;
5448 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005449 } else {
5450 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5451 if (addr)
5452 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5453 }
5454
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005455 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005456 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005457
Hai Shalomc3565922019-10-28 11:58:20 -07005458#ifdef CONFIG_FST
5459 if (wpa_s->fst)
5460 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5461#endif /* CONFIG_FST */
5462
Sunil Ravi77d572f2023-01-17 23:58:31 +00005463 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5464 wpas_notify_mac_address_changed(wpa_s);
5465
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005466 return 0;
5467}
5468
5469
Dmitry Shmidt04949592012-07-19 12:16:46 -07005470static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5471 const u8 *buf, size_t len)
5472{
5473 struct wpa_supplicant *wpa_s = ctx;
5474 const struct l2_ethhdr *eth;
5475
5476 if (len < sizeof(*eth))
5477 return;
5478 eth = (const struct l2_ethhdr *) buf;
5479
5480 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5481 !(eth->h_dest[0] & 0x01)) {
5482 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5483 " (bridge - not for this interface - ignore)",
5484 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5485 return;
5486 }
5487
5488 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5489 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5490 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005491 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005492}
5493
5494
Hai Shalom899fcc72020-10-19 14:38:18 -07005495int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5496 const char *bridge_ifname)
5497{
5498 if (wpa_s->wpa_state > WPA_SCANNING)
5499 return -EBUSY;
5500
5501 if (bridge_ifname &&
5502 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5503 return -EINVAL;
5504
5505 if (!bridge_ifname)
5506 bridge_ifname = "";
5507
5508 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5509 return 0;
5510
5511 if (wpa_s->l2_br) {
5512 l2_packet_deinit(wpa_s->l2_br);
5513 wpa_s->l2_br = NULL;
5514 }
5515
5516 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5517 sizeof(wpa_s->bridge_ifname));
5518
5519 if (wpa_s->bridge_ifname[0]) {
5520 wpa_dbg(wpa_s, MSG_DEBUG,
5521 "Receiving packets from bridge interface '%s'",
5522 wpa_s->bridge_ifname);
5523 wpa_s->l2_br = l2_packet_init_bridge(
5524 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5525 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5526 if (!wpa_s->l2_br) {
5527 wpa_msg(wpa_s, MSG_ERROR,
5528 "Failed to open l2_packet connection for the bridge interface '%s'",
5529 wpa_s->bridge_ifname);
5530 goto fail;
5531 }
5532 }
5533
5534#ifdef CONFIG_TDLS
5535 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5536 goto fail;
5537#endif /* CONFIG_TDLS */
5538
5539 return 0;
5540fail:
5541 wpa_s->bridge_ifname[0] = 0;
5542 if (wpa_s->l2_br) {
5543 l2_packet_deinit(wpa_s->l2_br);
5544 wpa_s->l2_br = NULL;
5545 }
5546#ifdef CONFIG_TDLS
5547 if (!wpa_s->p2p_mgmt)
5548 wpa_tdls_init(wpa_s->wpa);
5549#endif /* CONFIG_TDLS */
5550 return -EIO;
5551}
5552
5553
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005554/**
5555 * wpa_supplicant_driver_init - Initialize driver interface parameters
5556 * @wpa_s: Pointer to wpa_supplicant data
5557 * Returns: 0 on success, -1 on failure
5558 *
5559 * This function is called to initialize driver interface parameters.
5560 * wpa_drv_init() must have been called before this function to initialize the
5561 * driver interface.
5562 */
5563int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5564{
5565 static int interface_count = 0;
5566
5567 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5568 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005570 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5571 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005572 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005573 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5574
Hai Shalomb755a2a2020-04-23 21:49:02 -07005575 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5577 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005578 wpa_s->l2_br = l2_packet_init_bridge(
5579 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5580 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005581 if (wpa_s->l2_br == NULL) {
5582 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5583 "connection for the bridge interface '%s'",
5584 wpa_s->bridge_ifname);
5585 return -1;
5586 }
5587 }
5588
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005589 if (wpa_s->conf->ap_scan == 2 &&
5590 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5591 wpa_printf(MSG_INFO,
5592 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5593 }
5594
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005595 wpa_clear_keys(wpa_s, NULL);
5596
5597 /* Make sure that TKIP countermeasures are not left enabled (could
5598 * happen if wpa_supplicant is killed during countermeasures. */
5599 wpa_drv_set_countermeasures(wpa_s, 0);
5600
5601 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5602 wpa_drv_flush_pmkid(wpa_s);
5603
5604 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005605 wpa_s->prev_scan_wildcard = 0;
5606
Dmitry Shmidt04949592012-07-19 12:16:46 -07005607 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005608 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5609 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5610 interface_count = 0;
5611 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005612#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005613 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005614 wpa_supplicant_delayed_sched_scan(wpa_s,
5615 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005616 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005617 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005618 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005619#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005620 interface_count++;
5621 } else
5622 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5623
5624 return 0;
5625}
5626
5627
5628static int wpa_supplicant_daemon(const char *pid_file)
5629{
5630 wpa_printf(MSG_DEBUG, "Daemonize..");
5631 return os_daemonize(pid_file);
5632}
5633
5634
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005635static struct wpa_supplicant *
5636wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637{
5638 struct wpa_supplicant *wpa_s;
5639
5640 wpa_s = os_zalloc(sizeof(*wpa_s));
5641 if (wpa_s == NULL)
5642 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005643 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005644 wpa_s->scan_interval = 5;
5645 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005646 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005647 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005648 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005649 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005650
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005651 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005652 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005653#ifdef CONFIG_TESTING_OPTIONS
5654 dl_list_init(&wpa_s->drv_signal_override);
5655#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005656 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005658 return wpa_s;
5659}
5660
5661
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005662#ifdef CONFIG_HT_OVERRIDES
5663
5664static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5665 struct ieee80211_ht_capabilities *htcaps,
5666 struct ieee80211_ht_capabilities *htcaps_mask,
5667 const char *ht_mcs)
5668{
5669 /* parse ht_mcs into hex array */
5670 int i;
5671 const char *tmp = ht_mcs;
5672 char *end = NULL;
5673
5674 /* If ht_mcs is null, do not set anything */
5675 if (!ht_mcs)
5676 return 0;
5677
5678 /* This is what we are setting in the kernel */
5679 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5680
5681 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5682
5683 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005684 long v;
5685
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005686 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005687 v = strtol(tmp, &end, 16);
5688
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005689 if (errno == 0) {
5690 wpa_msg(wpa_s, MSG_DEBUG,
5691 "htcap value[%i]: %ld end: %p tmp: %p",
5692 i, v, end, tmp);
5693 if (end == tmp)
5694 break;
5695
5696 htcaps->supported_mcs_set[i] = v;
5697 tmp = end;
5698 } else {
5699 wpa_msg(wpa_s, MSG_ERROR,
5700 "Failed to parse ht-mcs: %s, error: %s\n",
5701 ht_mcs, strerror(errno));
5702 return -1;
5703 }
5704 }
5705
5706 /*
5707 * If we were able to parse any values, then set mask for the MCS set.
5708 */
5709 if (i) {
5710 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5711 IEEE80211_HT_MCS_MASK_LEN - 1);
5712 /* skip the 3 reserved bits */
5713 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5714 0x1f;
5715 }
5716
5717 return 0;
5718}
5719
5720
5721static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5722 struct ieee80211_ht_capabilities *htcaps,
5723 struct ieee80211_ht_capabilities *htcaps_mask,
5724 int disabled)
5725{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005726 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005727
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005728 if (disabled == -1)
5729 return 0;
5730
Hai Shalom74f70d42019-02-11 14:42:39 -08005731 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5732
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005733 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5734 htcaps_mask->ht_capabilities_info |= msk;
5735 if (disabled)
5736 htcaps->ht_capabilities_info &= msk;
5737 else
5738 htcaps->ht_capabilities_info |= msk;
5739
5740 return 0;
5741}
5742
5743
5744static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5745 struct ieee80211_ht_capabilities *htcaps,
5746 struct ieee80211_ht_capabilities *htcaps_mask,
5747 int factor)
5748{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005749 if (factor == -1)
5750 return 0;
5751
Hai Shalom74f70d42019-02-11 14:42:39 -08005752 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5753
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005754 if (factor < 0 || factor > 3) {
5755 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5756 "Must be 0-3 or -1", factor);
5757 return -EINVAL;
5758 }
5759
5760 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5761 htcaps->a_mpdu_params &= ~0x3;
5762 htcaps->a_mpdu_params |= factor & 0x3;
5763
5764 return 0;
5765}
5766
5767
5768static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5769 struct ieee80211_ht_capabilities *htcaps,
5770 struct ieee80211_ht_capabilities *htcaps_mask,
5771 int density)
5772{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005773 if (density == -1)
5774 return 0;
5775
Hai Shalom74f70d42019-02-11 14:42:39 -08005776 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5777
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005778 if (density < 0 || density > 7) {
5779 wpa_msg(wpa_s, MSG_ERROR,
5780 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5781 density);
5782 return -EINVAL;
5783 }
5784
5785 htcaps_mask->a_mpdu_params |= 0x1C;
5786 htcaps->a_mpdu_params &= ~(0x1C);
5787 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5788
5789 return 0;
5790}
5791
5792
5793static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5794 struct ieee80211_ht_capabilities *htcaps,
5795 struct ieee80211_ht_capabilities *htcaps_mask,
5796 int disabled)
5797{
Hai Shalom74f70d42019-02-11 14:42:39 -08005798 if (disabled)
5799 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005800
Paul Stewart092955c2017-02-06 09:13:09 -08005801 set_disable_ht40(htcaps, disabled);
5802 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005803
5804 return 0;
5805}
5806
5807
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005808static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5809 struct ieee80211_ht_capabilities *htcaps,
5810 struct ieee80211_ht_capabilities *htcaps_mask,
5811 int disabled)
5812{
5813 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005814 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5815 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005816
Hai Shalom74f70d42019-02-11 14:42:39 -08005817 if (disabled)
5818 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005819
5820 if (disabled)
5821 htcaps->ht_capabilities_info &= ~msk;
5822 else
5823 htcaps->ht_capabilities_info |= msk;
5824
5825 htcaps_mask->ht_capabilities_info |= msk;
5826
5827 return 0;
5828}
5829
5830
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005831static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5832 struct ieee80211_ht_capabilities *htcaps,
5833 struct ieee80211_ht_capabilities *htcaps_mask,
5834 int disabled)
5835{
5836 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005837 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005838
Hai Shalom74f70d42019-02-11 14:42:39 -08005839 if (disabled)
5840 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005841
5842 if (disabled)
5843 htcaps->ht_capabilities_info &= ~msk;
5844 else
5845 htcaps->ht_capabilities_info |= msk;
5846
5847 htcaps_mask->ht_capabilities_info |= msk;
5848
5849 return 0;
5850}
5851
5852
Hai Shalom74f70d42019-02-11 14:42:39 -08005853static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5854 struct ieee80211_ht_capabilities *htcaps,
5855 struct ieee80211_ht_capabilities *htcaps_mask,
5856 int tx_stbc)
5857{
5858 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5859
5860 if (tx_stbc == -1)
5861 return 0;
5862
5863 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5864
5865 if (tx_stbc < 0 || tx_stbc > 1) {
5866 wpa_msg(wpa_s, MSG_ERROR,
5867 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5868 return -EINVAL;
5869 }
5870
5871 htcaps_mask->ht_capabilities_info |= msk;
5872 htcaps->ht_capabilities_info &= ~msk;
5873 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5874
5875 return 0;
5876}
5877
5878
5879static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5880 struct ieee80211_ht_capabilities *htcaps,
5881 struct ieee80211_ht_capabilities *htcaps_mask,
5882 int rx_stbc)
5883{
5884 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5885
5886 if (rx_stbc == -1)
5887 return 0;
5888
5889 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5890
5891 if (rx_stbc < 0 || rx_stbc > 3) {
5892 wpa_msg(wpa_s, MSG_ERROR,
5893 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5894 return -EINVAL;
5895 }
5896
5897 htcaps_mask->ht_capabilities_info |= msk;
5898 htcaps->ht_capabilities_info &= ~msk;
5899 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5900
5901 return 0;
5902}
5903
5904
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005905void wpa_supplicant_apply_ht_overrides(
5906 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5907 struct wpa_driver_associate_params *params)
5908{
5909 struct ieee80211_ht_capabilities *htcaps;
5910 struct ieee80211_ht_capabilities *htcaps_mask;
5911
5912 if (!ssid)
5913 return;
5914
5915 params->disable_ht = ssid->disable_ht;
5916 if (!params->htcaps || !params->htcaps_mask)
5917 return;
5918
5919 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5920 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5921 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5922 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5923 ssid->disable_max_amsdu);
5924 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5925 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5926 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005927 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005928 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005929 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5930 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005931
5932 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005933 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005934 htcaps->ht_capabilities_info |= bit;
5935 htcaps_mask->ht_capabilities_info |= bit;
5936 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005937}
5938
5939#endif /* CONFIG_HT_OVERRIDES */
5940
5941
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005942#ifdef CONFIG_VHT_OVERRIDES
5943void wpa_supplicant_apply_vht_overrides(
5944 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5945 struct wpa_driver_associate_params *params)
5946{
5947 struct ieee80211_vht_capabilities *vhtcaps;
5948 struct ieee80211_vht_capabilities *vhtcaps_mask;
5949
5950 if (!ssid)
5951 return;
5952
5953 params->disable_vht = ssid->disable_vht;
5954
5955 vhtcaps = (void *) params->vhtcaps;
5956 vhtcaps_mask = (void *) params->vhtcaps_mask;
5957
5958 if (!vhtcaps || !vhtcaps_mask)
5959 return;
5960
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005961 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5962 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005963
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005964#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005965 if (ssid->disable_sgi) {
5966 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5967 VHT_CAP_SHORT_GI_160);
5968 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5969 VHT_CAP_SHORT_GI_160);
5970 wpa_msg(wpa_s, MSG_DEBUG,
5971 "disable-sgi override specified, vht-caps: 0x%x",
5972 vhtcaps->vht_capabilities_info);
5973 }
5974
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005975 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005976 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5977 int max_ampdu;
5978
5979 max_ampdu = (ssid->vht_capa &
5980 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5981 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005982
5983 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5984 wpa_set_ampdu_factor(wpa_s,
5985 (void *) params->htcaps,
5986 (void *) params->htcaps_mask,
5987 max_ampdu);
5988 }
5989#endif /* CONFIG_HT_OVERRIDES */
5990
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005991#define OVERRIDE_MCS(i) \
5992 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5993 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005994 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005995 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005996 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5997 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005998 } \
5999 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6000 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006001 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006002 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006003 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6004 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006005 }
6006
6007 OVERRIDE_MCS(1);
6008 OVERRIDE_MCS(2);
6009 OVERRIDE_MCS(3);
6010 OVERRIDE_MCS(4);
6011 OVERRIDE_MCS(5);
6012 OVERRIDE_MCS(6);
6013 OVERRIDE_MCS(7);
6014 OVERRIDE_MCS(8);
6015}
6016#endif /* CONFIG_VHT_OVERRIDES */
6017
6018
Hai Shalomfdcde762020-04-02 11:19:20 -07006019#ifdef CONFIG_HE_OVERRIDES
6020void wpa_supplicant_apply_he_overrides(
6021 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6022 struct wpa_driver_associate_params *params)
6023{
6024 if (!ssid)
6025 return;
6026
6027 params->disable_he = ssid->disable_he;
6028}
6029#endif /* CONFIG_HE_OVERRIDES */
6030
6031
Sunil Ravi77d572f2023-01-17 23:58:31 +00006032void wpa_supplicant_apply_eht_overrides(
6033 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6034 struct wpa_driver_associate_params *params)
6035{
6036 if (!ssid)
6037 return;
6038
6039 params->disable_eht = ssid->disable_eht;
6040}
6041
6042
Dmitry Shmidt04949592012-07-19 12:16:46 -07006043static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6044{
6045#ifdef PCSC_FUNCS
6046 size_t len;
6047
6048 if (!wpa_s->conf->pcsc_reader)
6049 return 0;
6050
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006051 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006052 if (!wpa_s->scard)
6053 return 1;
6054
6055 if (wpa_s->conf->pcsc_pin &&
6056 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6057 scard_deinit(wpa_s->scard);
6058 wpa_s->scard = NULL;
6059 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6060 return -1;
6061 }
6062
6063 len = sizeof(wpa_s->imsi) - 1;
6064 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6065 scard_deinit(wpa_s->scard);
6066 wpa_s->scard = NULL;
6067 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6068 return -1;
6069 }
6070 wpa_s->imsi[len] = '\0';
6071
6072 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6073
6074 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6075 wpa_s->imsi, wpa_s->mnc_len);
6076
6077 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6078 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6079#endif /* PCSC_FUNCS */
6080
6081 return 0;
6082}
6083
6084
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006085int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6086{
6087 char *val, *pos;
6088
6089 ext_password_deinit(wpa_s->ext_pw);
6090 wpa_s->ext_pw = NULL;
6091 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6092
6093 if (!wpa_s->conf->ext_password_backend)
6094 return 0;
6095
6096 val = os_strdup(wpa_s->conf->ext_password_backend);
6097 if (val == NULL)
6098 return -1;
6099 pos = os_strchr(val, ':');
6100 if (pos)
6101 *pos++ = '\0';
6102
6103 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6104
6105 wpa_s->ext_pw = ext_password_init(val, pos);
6106 os_free(val);
6107 if (wpa_s->ext_pw == NULL) {
6108 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6109 return -1;
6110 }
6111 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6112
6113 return 0;
6114}
6115
6116
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006117#ifdef CONFIG_FST
6118
6119static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6120{
6121 struct wpa_supplicant *wpa_s = ctx;
6122
6123 return (is_zero_ether_addr(wpa_s->bssid) ||
6124 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6125}
6126
6127
6128static void wpas_fst_get_channel_info_cb(void *ctx,
6129 enum hostapd_hw_mode *hw_mode,
6130 u8 *channel)
6131{
6132 struct wpa_supplicant *wpa_s = ctx;
6133
6134 if (wpa_s->current_bss) {
6135 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6136 channel);
6137 } else if (wpa_s->hw.num_modes) {
6138 *hw_mode = wpa_s->hw.modes[0].mode;
6139 } else {
6140 WPA_ASSERT(0);
6141 *hw_mode = 0;
6142 }
6143}
6144
6145
6146static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6147{
6148 struct wpa_supplicant *wpa_s = ctx;
6149
6150 *modes = wpa_s->hw.modes;
6151 return wpa_s->hw.num_modes;
6152}
6153
6154
6155static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6156{
6157 struct wpa_supplicant *wpa_s = ctx;
6158
6159 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6160 wpa_s->fst_ies = fst_ies;
6161}
6162
6163
6164static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6165{
6166 struct wpa_supplicant *wpa_s = ctx;
6167
Paul Stewart092955c2017-02-06 09:13:09 -08006168 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6169 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6170 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6171 return -1;
6172 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006173 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006174 wpa_s->own_addr, wpa_s->bssid,
6175 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006176 0);
6177}
6178
6179
6180static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6181{
6182 struct wpa_supplicant *wpa_s = ctx;
6183
6184 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6185 return wpa_s->received_mb_ies;
6186}
6187
6188
6189static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6190 const u8 *buf, size_t size)
6191{
6192 struct wpa_supplicant *wpa_s = ctx;
6193 struct mb_ies_info info;
6194
6195 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6196
6197 if (!mb_ies_info_by_ies(&info, buf, size)) {
6198 wpabuf_free(wpa_s->received_mb_ies);
6199 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6200 }
6201}
6202
6203
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006204static const u8 * wpas_fst_get_peer_first(void *ctx,
6205 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006206 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006207{
6208 struct wpa_supplicant *wpa_s = ctx;
6209
6210 *get_ctx = NULL;
6211 if (!is_zero_ether_addr(wpa_s->bssid))
6212 return (wpa_s->received_mb_ies || !mb_only) ?
6213 wpa_s->bssid : NULL;
6214 return NULL;
6215}
6216
6217
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006218static const u8 * wpas_fst_get_peer_next(void *ctx,
6219 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006220 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006221{
6222 return NULL;
6223}
6224
6225void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6226 struct fst_wpa_obj *iface_obj)
6227{
Sunil8cd6f4d2022-06-28 18:40:46 +00006228 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006229 iface_obj->ctx = wpa_s;
6230 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6231 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6232 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6233 iface_obj->set_ies = wpas_fst_set_ies_cb;
6234 iface_obj->send_action = wpas_fst_send_action_cb;
6235 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6236 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6237 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6238 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6239}
6240#endif /* CONFIG_FST */
6241
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006242static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006243 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006244{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006245 struct wowlan_triggers *triggers;
6246 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006247
6248 if (!wpa_s->conf->wowlan_triggers)
6249 return 0;
6250
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006251 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6252 if (triggers) {
6253 ret = wpa_drv_wowlan(wpa_s, triggers);
6254 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006255 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006256 return ret;
6257}
6258
6259
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006260enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006261{
6262 if (freq < 3000)
6263 return BAND_2_4_GHZ;
6264 if (freq > 50000)
6265 return BAND_60_GHZ;
6266 return BAND_5_GHZ;
6267}
6268
6269
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006270unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006271{
6272 int i;
6273 unsigned int band = 0;
6274
6275 if (freqs) {
6276 /* freqs are specified for the radio work */
6277 for (i = 0; freqs[i]; i++)
6278 band |= wpas_freq_to_band(freqs[i]);
6279 } else {
6280 /*
6281 * freqs are not specified, implies all
6282 * the supported freqs by HW
6283 */
6284 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6285 if (wpa_s->hw.modes[i].num_channels != 0) {
6286 if (wpa_s->hw.modes[i].mode ==
6287 HOSTAPD_MODE_IEEE80211B ||
6288 wpa_s->hw.modes[i].mode ==
6289 HOSTAPD_MODE_IEEE80211G)
6290 band |= BAND_2_4_GHZ;
6291 else if (wpa_s->hw.modes[i].mode ==
6292 HOSTAPD_MODE_IEEE80211A)
6293 band |= BAND_5_GHZ;
6294 else if (wpa_s->hw.modes[i].mode ==
6295 HOSTAPD_MODE_IEEE80211AD)
6296 band |= BAND_60_GHZ;
6297 else if (wpa_s->hw.modes[i].mode ==
6298 HOSTAPD_MODE_IEEE80211ANY)
6299 band = BAND_2_4_GHZ | BAND_5_GHZ |
6300 BAND_60_GHZ;
6301 }
6302 }
6303 }
6304
6305 return band;
6306}
6307
6308
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006309static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6310 const char *rn)
6311{
6312 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6313 struct wpa_radio *radio;
6314
6315 while (rn && iface) {
6316 radio = iface->radio;
6317 if (radio && os_strcmp(rn, radio->name) == 0) {
6318 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6319 wpa_s->ifname, rn);
6320 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6321 return radio;
6322 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006323
6324 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006325 }
6326
6327 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6328 wpa_s->ifname, rn ? rn : "N/A");
6329 radio = os_zalloc(sizeof(*radio));
6330 if (radio == NULL)
6331 return NULL;
6332
6333 if (rn)
6334 os_strlcpy(radio->name, rn, sizeof(radio->name));
6335 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006336 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006337 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6338
6339 return radio;
6340}
6341
6342
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006343static void radio_work_free(struct wpa_radio_work *work)
6344{
6345 if (work->wpa_s->scan_work == work) {
6346 /* This should not really happen. */
6347 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6348 work->type, work, work->started);
6349 work->wpa_s->scan_work = NULL;
6350 }
6351
6352#ifdef CONFIG_P2P
6353 if (work->wpa_s->p2p_scan_work == work) {
6354 /* This should not really happen. */
6355 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6356 work->type, work, work->started);
6357 work->wpa_s->p2p_scan_work = NULL;
6358 }
6359#endif /* CONFIG_P2P */
6360
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006361 if (work->started) {
6362 work->wpa_s->radio->num_active_works--;
6363 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006364 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006365 work->type, work,
6366 work->wpa_s->radio->num_active_works);
6367 }
6368
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006369 dl_list_del(&work->list);
6370 os_free(work);
6371}
6372
6373
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006374static int radio_work_is_connect(struct wpa_radio_work *work)
6375{
6376 return os_strcmp(work->type, "sme-connect") == 0 ||
6377 os_strcmp(work->type, "connect") == 0;
6378}
6379
6380
6381static int radio_work_is_scan(struct wpa_radio_work *work)
6382{
6383 return os_strcmp(work->type, "scan") == 0 ||
6384 os_strcmp(work->type, "p2p-scan") == 0;
6385}
6386
6387
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006388static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6389{
6390 struct wpa_radio_work *active_work = NULL;
6391 struct wpa_radio_work *tmp;
6392
6393 /* Get the active work to know the type and band. */
6394 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6395 if (tmp->started) {
6396 active_work = tmp;
6397 break;
6398 }
6399 }
6400
6401 if (!active_work) {
6402 /* No active work, start one */
6403 radio->num_active_works = 0;
6404 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6405 list) {
6406 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006407 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006408 (((struct wpa_driver_scan_params *)
6409 tmp->ctx)->only_new_results ||
6410 tmp->wpa_s->clear_driver_scan_cache))
6411 continue;
6412 return tmp;
6413 }
6414 return NULL;
6415 }
6416
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006417 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006418 /*
6419 * If the active work is either connect or sme-connect,
6420 * do not parallelize them with other radio works.
6421 */
6422 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6423 "Do not parallelize radio work with %s",
6424 active_work->type);
6425 return NULL;
6426 }
6427
6428 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6429 if (tmp->started)
6430 continue;
6431
6432 /*
6433 * If connect or sme-connect are enqueued, parallelize only
6434 * those operations ahead of them in the queue.
6435 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006436 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006437 break;
6438
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006439 /* Serialize parallel scan and p2p_scan operations on the same
6440 * interface since the driver_nl80211 mechanism for tracking
6441 * scan cookies does not yet have support for this. */
6442 if (active_work->wpa_s == tmp->wpa_s &&
6443 radio_work_is_scan(active_work) &&
6444 radio_work_is_scan(tmp)) {
6445 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6446 "Do not start work '%s' when another work '%s' is already scheduled",
6447 tmp->type, active_work->type);
6448 continue;
6449 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006450 /*
6451 * Check that the radio works are distinct and
6452 * on different bands.
6453 */
6454 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6455 (active_work->bands != tmp->bands)) {
6456 /*
6457 * If a scan has to be scheduled through nl80211 scan
6458 * interface and if an external scan is already running,
6459 * do not schedule the scan since it is likely to get
6460 * rejected by kernel.
6461 */
6462 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006463 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006464 (((struct wpa_driver_scan_params *)
6465 tmp->ctx)->only_new_results ||
6466 tmp->wpa_s->clear_driver_scan_cache))
6467 continue;
6468
6469 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6470 "active_work:%s new_work:%s",
6471 active_work->type, tmp->type);
6472 return tmp;
6473 }
6474 }
6475
6476 /* Did not find a radio work to schedule in parallel. */
6477 return NULL;
6478}
6479
6480
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006481static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6482{
6483 struct wpa_radio *radio = eloop_ctx;
6484 struct wpa_radio_work *work;
6485 struct os_reltime now, diff;
6486 struct wpa_supplicant *wpa_s;
6487
6488 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006489 if (work == NULL) {
6490 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006491 return;
6492 }
6493
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006494 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6495 radio_list);
6496
6497 if (!(wpa_s &&
6498 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6499 if (work->started)
6500 return; /* already started and still in progress */
6501
Hai Shalom60840252021-02-19 19:02:11 -08006502 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006503 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6504 return;
6505 }
6506 } else {
6507 work = NULL;
6508 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6509 /* get the work to schedule next */
6510 work = radio_work_get_next_work(radio);
6511 }
6512 if (!work)
6513 return;
6514 }
6515
6516 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006517 os_get_reltime(&now);
6518 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006519 wpa_dbg(wpa_s, MSG_DEBUG,
6520 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006521 work->type, work, diff.sec, diff.usec);
6522 work->started = 1;
6523 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006524 radio->num_active_works++;
6525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006526 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006527
6528 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6529 radio->num_active_works < MAX_ACTIVE_WORKS)
6530 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006531}
6532
6533
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006534/*
6535 * This function removes both started and pending radio works running on
6536 * the provided interface's radio.
6537 * Prior to the removal of the radio work, its callback (cb) is called with
6538 * deinit set to be 1. Each work's callback is responsible for clearing its
6539 * internal data and restoring to a correct state.
6540 * @wpa_s: wpa_supplicant data
6541 * @type: type of works to be removed
6542 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6543 * this interface's works.
6544 */
6545void radio_remove_works(struct wpa_supplicant *wpa_s,
6546 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006547{
6548 struct wpa_radio_work *work, *tmp;
6549 struct wpa_radio *radio = wpa_s->radio;
6550
6551 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6552 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006553 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006554 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006555
6556 /* skip other ifaces' works */
6557 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006558 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006559
6560 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6561 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006562 work->cb(work, 1);
6563 radio_work_free(work);
6564 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006565
6566 /* in case we removed the started work */
6567 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006568}
6569
6570
Roshan Pius3a1667e2018-07-03 15:17:14 -07006571void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6572{
6573 struct wpa_radio_work *work;
6574 struct wpa_radio *radio = wpa_s->radio;
6575
6576 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6577 if (work->ctx != ctx)
6578 continue;
6579 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6580 work->type, work, work->started ? " (started)" : "");
6581 radio_work_free(work);
6582 break;
6583 }
6584}
6585
6586
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006587static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6588{
6589 struct wpa_radio *radio = wpa_s->radio;
6590
6591 if (!radio)
6592 return;
6593
6594 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6595 wpa_s->ifname, radio->name);
6596 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006597 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006598 /* If the interface that triggered the external scan was removed, the
6599 * external scan is no longer running. */
6600 if (wpa_s == radio->external_scan_req_interface)
6601 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006602 wpa_s->radio = NULL;
6603 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006604 return; /* Interfaces remain for this radio */
6605
6606 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006607 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006608 os_free(radio);
6609}
6610
6611
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006612void radio_work_check_next(struct wpa_supplicant *wpa_s)
6613{
6614 struct wpa_radio *radio = wpa_s->radio;
6615
6616 if (dl_list_empty(&radio->work))
6617 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006618 if (wpa_s->ext_work_in_progress) {
6619 wpa_printf(MSG_DEBUG,
6620 "External radio work in progress - delay start of pending item");
6621 return;
6622 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006623 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6624 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6625}
6626
6627
6628/**
6629 * radio_add_work - Add a radio work item
6630 * @wpa_s: Pointer to wpa_supplicant data
6631 * @freq: Frequency of the offchannel operation in MHz or 0
6632 * @type: Unique identifier for each type of work
6633 * @next: Force as the next work to be executed
6634 * @cb: Callback function for indicating when radio is available
6635 * @ctx: Context pointer for the work (work->ctx in cb())
6636 * Returns: 0 on success, -1 on failure
6637 *
6638 * This function is used to request time for an operation that requires
6639 * exclusive radio control. Once the radio is available, the registered callback
6640 * function will be called. radio_work_done() must be called once the exclusive
6641 * radio operation has been completed, so that the radio is freed for other
6642 * operations. The special case of deinit=1 is used to free the context data
6643 * during interface removal. That does not allow the callback function to start
6644 * the radio operation, i.e., it must free any resources allocated for the radio
6645 * work and return.
6646 *
6647 * The @freq parameter can be used to indicate a single channel on which the
6648 * offchannel operation will occur. This may allow multiple radio work
6649 * operations to be performed in parallel if they apply for the same channel.
6650 * Setting this to 0 indicates that the work item may use multiple channels or
6651 * requires exclusive control of the radio.
6652 */
6653int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6654 const char *type, int next,
6655 void (*cb)(struct wpa_radio_work *work, int deinit),
6656 void *ctx)
6657{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006658 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006659 struct wpa_radio_work *work;
6660 int was_empty;
6661
6662 work = os_zalloc(sizeof(*work));
6663 if (work == NULL)
6664 return -1;
6665 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6666 os_get_reltime(&work->time);
6667 work->freq = freq;
6668 work->type = type;
6669 work->wpa_s = wpa_s;
6670 work->cb = cb;
6671 work->ctx = ctx;
6672
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006673 if (freq)
6674 work->bands = wpas_freq_to_band(freq);
6675 else if (os_strcmp(type, "scan") == 0 ||
6676 os_strcmp(type, "p2p-scan") == 0)
6677 work->bands = wpas_get_bands(wpa_s,
6678 ((struct wpa_driver_scan_params *)
6679 ctx)->freqs);
6680 else
6681 work->bands = wpas_get_bands(wpa_s, NULL);
6682
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006683 was_empty = dl_list_empty(&wpa_s->radio->work);
6684 if (next)
6685 dl_list_add(&wpa_s->radio->work, &work->list);
6686 else
6687 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6688 if (was_empty) {
6689 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6690 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006691 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6692 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6693 wpa_dbg(wpa_s, MSG_DEBUG,
6694 "Try to schedule a radio work (num_active_works=%u)",
6695 radio->num_active_works);
6696 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006697 }
6698
6699 return 0;
6700}
6701
6702
6703/**
6704 * radio_work_done - Indicate that a radio work item has been completed
6705 * @work: Completed work
6706 *
6707 * This function is called once the callback function registered with
6708 * radio_add_work() has completed its work.
6709 */
6710void radio_work_done(struct wpa_radio_work *work)
6711{
6712 struct wpa_supplicant *wpa_s = work->wpa_s;
6713 struct os_reltime now, diff;
6714 unsigned int started = work->started;
6715
6716 os_get_reltime(&now);
6717 os_reltime_sub(&now, &work->time, &diff);
6718 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6719 work->type, work, started ? "done" : "canceled",
6720 diff.sec, diff.usec);
6721 radio_work_free(work);
6722 if (started)
6723 radio_work_check_next(wpa_s);
6724}
6725
6726
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006727struct wpa_radio_work *
6728radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006729{
6730 struct wpa_radio_work *work;
6731 struct wpa_radio *radio = wpa_s->radio;
6732
6733 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6734 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006735 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006736 }
6737
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006738 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006739}
6740
6741
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006742static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006743 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006744{
6745 const char *ifname, *driver, *rn;
6746
6747 driver = iface->driver;
6748next_driver:
6749 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6750 return -1;
6751
6752 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6753 if (wpa_s->drv_priv == NULL) {
6754 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006755 int level = MSG_ERROR;
6756
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006757 pos = driver ? os_strchr(driver, ',') : NULL;
6758 if (pos) {
6759 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6760 "driver interface - try next driver wrapper");
6761 driver = pos + 1;
6762 goto next_driver;
6763 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006764
6765#ifdef CONFIG_MATCH_IFACE
6766 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6767 level = MSG_DEBUG;
6768#endif /* CONFIG_MATCH_IFACE */
6769 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006770 return -1;
6771 }
6772 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6773 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6774 "driver_param '%s'", wpa_s->conf->driver_param);
6775 return -1;
6776 }
6777
6778 ifname = wpa_drv_get_ifname(wpa_s);
6779 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6780 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6781 "interface name with '%s'", ifname);
6782 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6783 }
6784
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006785 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006786 if (rn && rn[0] == '\0')
6787 rn = NULL;
6788
6789 wpa_s->radio = radio_add_interface(wpa_s, rn);
6790 if (wpa_s->radio == NULL)
6791 return -1;
6792
6793 return 0;
6794}
6795
6796
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006797#ifdef CONFIG_GAS_SERVER
6798
6799static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6800 unsigned int freq, const u8 *dst,
6801 const u8 *src, const u8 *bssid,
6802 const u8 *data, size_t data_len,
6803 enum offchannel_send_action_result result)
6804{
6805 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6806 " result=%s",
6807 freq, MAC2STR(dst),
6808 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6809 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6810 "FAILED"));
6811 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6812 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6813}
6814
6815
6816static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6817 struct wpabuf *buf, unsigned int wait_time)
6818{
6819 struct wpa_supplicant *wpa_s = ctx;
6820 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6821
6822 if (wait_time > wpa_s->max_remain_on_chan)
6823 wait_time = wpa_s->max_remain_on_chan;
6824
6825 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6826 wpabuf_head(buf), wpabuf_len(buf),
6827 wait_time, wpas_gas_server_tx_status, 0);
6828}
6829
6830#endif /* CONFIG_GAS_SERVER */
6831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006832static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006833 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006834{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006835 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006836 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006837 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006838
6839 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6840 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6841 iface->confname ? iface->confname : "N/A",
6842 iface->driver ? iface->driver : "default",
6843 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6844 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6845
6846 if (iface->confname) {
6847#ifdef CONFIG_BACKEND_FILE
6848 wpa_s->confname = os_rel2abs_path(iface->confname);
6849 if (wpa_s->confname == NULL) {
6850 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6851 "for configuration file '%s'.",
6852 iface->confname);
6853 return -1;
6854 }
6855 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6856 iface->confname, wpa_s->confname);
6857#else /* CONFIG_BACKEND_FILE */
6858 wpa_s->confname = os_strdup(iface->confname);
6859#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00006860 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006861 if (wpa_s->conf == NULL) {
6862 wpa_printf(MSG_ERROR, "Failed to read or parse "
6863 "configuration '%s'.", wpa_s->confname);
6864 return -1;
6865 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006866 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006867 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00006868 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006869 wpa_printf(MSG_ERROR,
6870 "Failed to read or parse configuration '%s'.",
6871 wpa_s->confanother);
6872 return -1;
6873 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006874
6875 /*
6876 * Override ctrl_interface and driver_param if set on command
6877 * line.
6878 */
6879 if (iface->ctrl_interface) {
6880 os_free(wpa_s->conf->ctrl_interface);
6881 wpa_s->conf->ctrl_interface =
6882 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006883 if (!wpa_s->conf->ctrl_interface) {
6884 wpa_printf(MSG_ERROR,
6885 "Failed to duplicate control interface '%s'.",
6886 iface->ctrl_interface);
6887 return -1;
6888 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006889 }
6890
6891 if (iface->driver_param) {
6892 os_free(wpa_s->conf->driver_param);
6893 wpa_s->conf->driver_param =
6894 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006895 if (!wpa_s->conf->driver_param) {
6896 wpa_printf(MSG_ERROR,
6897 "Failed to duplicate driver param '%s'.",
6898 iface->driver_param);
6899 return -1;
6900 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006901 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006902
6903 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6904 os_free(wpa_s->conf->ctrl_interface);
6905 wpa_s->conf->ctrl_interface = NULL;
6906 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006907 } else
6908 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6909 iface->driver_param);
6910
6911 if (wpa_s->conf == NULL) {
6912 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6913 return -1;
6914 }
6915
6916 if (iface->ifname == NULL) {
6917 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6918 return -1;
6919 }
6920 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6921 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6922 iface->ifname);
6923 return -1;
6924 }
6925 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006926#ifdef CONFIG_MATCH_IFACE
6927 wpa_s->matched = iface->matched;
6928#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006929
6930 if (iface->bridge_ifname) {
6931 if (os_strlen(iface->bridge_ifname) >=
6932 sizeof(wpa_s->bridge_ifname)) {
6933 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6934 "name '%s'.", iface->bridge_ifname);
6935 return -1;
6936 }
6937 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6938 sizeof(wpa_s->bridge_ifname));
6939 }
6940
6941 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006942 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6943 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006944
6945 /* Initialize driver interface and register driver event handler before
6946 * L2 receive handler so that association events are processed before
6947 * EAPOL-Key packets if both become available for the same select()
6948 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006949 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006950 return -1;
6951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006952 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6953 return -1;
6954
6955 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6956 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6957 NULL);
6958 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6959
6960 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6961 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6962 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6963 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6964 "dot11RSNAConfigPMKLifetime");
6965 return -1;
6966 }
6967
6968 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6969 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6970 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6971 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6972 "dot11RSNAConfigPMKReauthThreshold");
6973 return -1;
6974 }
6975
6976 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6977 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6978 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6979 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6980 "dot11RSNAConfigSATimeout");
6981 return -1;
6982 }
6983
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006984 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6985 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006986 &wpa_s->hw.flags,
6987 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006988 if (wpa_s->hw.modes) {
6989 u16 i;
6990
6991 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6992 if (wpa_s->hw.modes[i].vht_capab) {
6993 wpa_s->hw_capab = CAPAB_VHT;
6994 break;
6995 }
6996
6997 if (wpa_s->hw.modes[i].ht_capab &
6998 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6999 wpa_s->hw_capab = CAPAB_HT40;
7000 else if (wpa_s->hw.modes[i].ht_capab &&
7001 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7002 wpa_s->hw_capab = CAPAB_HT;
7003 }
7004 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007005
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007006 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7007 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007008 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007009 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007010 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007011 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007012 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007013 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007014 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007015 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007016 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007017 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7018 wpa_s->max_sched_scan_plan_interval =
7019 capa.max_sched_scan_plan_interval;
7020 wpa_s->max_sched_scan_plan_iterations =
7021 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007022 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7023 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007024 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7025 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007026 wpa_s->extended_capa = capa.extended_capa;
7027 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7028 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007029 wpa_s->num_multichan_concurrent =
7030 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007031 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007032 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007033
7034 if (capa.mac_addr_rand_scan_supported)
7035 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7036 if (wpa_s->sched_scan_supported &&
7037 capa.mac_addr_rand_sched_scan_supported)
7038 wpa_s->mac_addr_rand_supported |=
7039 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007040
7041 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7042 if (wpa_s->extended_capa &&
7043 wpa_s->extended_capa_len >= 3 &&
7044 wpa_s->extended_capa[2] & 0x40)
7045 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007046 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007047#ifdef CONFIG_PASN
7048 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7049#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007050 if (wpa_s->max_remain_on_chan == 0)
7051 wpa_s->max_remain_on_chan = 1000;
7052
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007053 /*
7054 * Only take p2p_mgmt parameters when P2P Device is supported.
7055 * Doing it here as it determines whether l2_packet_init() will be done
7056 * during wpa_supplicant_driver_init().
7057 */
7058 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7059 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007060
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007061 if (wpa_s->num_multichan_concurrent == 0)
7062 wpa_s->num_multichan_concurrent = 1;
7063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007064 if (wpa_supplicant_driver_init(wpa_s) < 0)
7065 return -1;
7066
7067#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007068 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007069 return -1;
7070#endif /* CONFIG_TDLS */
7071
7072 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7073 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7074 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7075 return -1;
7076 }
7077
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007078#ifdef CONFIG_FST
7079 if (wpa_s->conf->fst_group_id) {
7080 struct fst_iface_cfg cfg;
7081 struct fst_wpa_obj iface_obj;
7082
7083 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7084 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7085 sizeof(cfg.group_id));
7086 cfg.priority = wpa_s->conf->fst_priority;
7087 cfg.llt = wpa_s->conf->fst_llt;
7088
7089 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7090 &iface_obj, &cfg);
7091 if (!wpa_s->fst) {
7092 wpa_msg(wpa_s, MSG_ERROR,
7093 "FST: Cannot attach iface %s to group %s",
7094 wpa_s->ifname, cfg.group_id);
7095 return -1;
7096 }
7097 }
7098#endif /* CONFIG_FST */
7099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007100 if (wpas_wps_init(wpa_s))
7101 return -1;
7102
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007103#ifdef CONFIG_GAS_SERVER
7104 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7105 if (!wpa_s->gas_server) {
7106 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7107 return -1;
7108 }
7109#endif /* CONFIG_GAS_SERVER */
7110
7111#ifdef CONFIG_DPP
7112 if (wpas_dpp_init(wpa_s) < 0)
7113 return -1;
7114#endif /* CONFIG_DPP */
7115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007116 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7117 return -1;
7118 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7119
7120 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7121 if (wpa_s->ctrl_iface == NULL) {
7122 wpa_printf(MSG_ERROR,
7123 "Failed to initialize control interface '%s'.\n"
7124 "You may have another wpa_supplicant process "
7125 "already running or the file was\n"
7126 "left by an unclean termination of wpa_supplicant "
7127 "in which case you will need\n"
7128 "to manually remove this file before starting "
7129 "wpa_supplicant again.\n",
7130 wpa_s->conf->ctrl_interface);
7131 return -1;
7132 }
7133
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007134 wpa_s->gas = gas_query_init(wpa_s);
7135 if (wpa_s->gas == NULL) {
7136 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7137 return -1;
7138 }
7139
Roshan Pius3a1667e2018-07-03 15:17:14 -07007140 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7141 wpa_s->p2p_mgmt) &&
7142 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007143 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7144 return -1;
7145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007146
7147 if (wpa_bss_init(wpa_s) < 0)
7148 return -1;
7149
Paul Stewart092955c2017-02-06 09:13:09 -08007150#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7151#ifdef CONFIG_MESH
7152 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7153#endif /* CONFIG_MESH */
7154#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7155
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007156 /*
7157 * Set Wake-on-WLAN triggers, if configured.
7158 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7159 * have effect anyway when the interface is down).
7160 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007161 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007162 return -1;
7163
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007164#ifdef CONFIG_EAP_PROXY
7165{
7166 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007167 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7168 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007169 if (wpa_s->mnc_len > 0) {
7170 wpa_s->imsi[len] = '\0';
7171 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7172 wpa_s->imsi, wpa_s->mnc_len);
7173 } else {
7174 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7175 }
7176}
7177#endif /* CONFIG_EAP_PROXY */
7178
Dmitry Shmidt04949592012-07-19 12:16:46 -07007179 if (pcsc_reader_init(wpa_s) < 0)
7180 return -1;
7181
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007182 if (wpas_init_ext_pw(wpa_s) < 0)
7183 return -1;
7184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007185 wpas_rrm_reset(wpa_s);
7186
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007187 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7188
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007189#ifdef CONFIG_HS20
7190 hs20_init(wpa_s);
7191#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007192#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007193 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007194 if ((wpa_s->conf->oce & OCE_STA) &&
7195 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7196 wpa_s->enable_oce = OCE_STA;
7197 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7198 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7199 /* TODO: Need to add STA-CFON support */
7200 wpa_printf(MSG_ERROR,
7201 "OCE STA-CFON feature is not yet supported");
7202 }
7203 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007204 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7205#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007206
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007207 wpa_supplicant_set_default_scan_ies(wpa_s);
7208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007209 return 0;
7210}
7211
7212
7213static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007214 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007215{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007216 struct wpa_global *global = wpa_s->global;
7217 struct wpa_supplicant *iface, *prev;
7218
Jimmy Chen0e73c002021-08-18 13:21:30 +08007219 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007220 wpas_p2p_group_remove(wpa_s, "*");
7221
7222 iface = global->ifaces;
7223 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007224 if (iface->p2pdev == wpa_s)
7225 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007226 if (iface == wpa_s || iface->parent != wpa_s) {
7227 iface = iface->next;
7228 continue;
7229 }
7230 wpa_printf(MSG_DEBUG,
7231 "Remove remaining child interface %s from parent %s",
7232 iface->ifname, wpa_s->ifname);
7233 prev = iface;
7234 iface = iface->next;
7235 wpa_supplicant_remove_iface(global, prev, terminate);
7236 }
7237
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007238 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007239 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007240 /*
7241 * Don't deauthenticate if WoWLAN is enable and not explicitly
7242 * been configured to disconnect.
7243 */
7244 if (!wpa_drv_get_wowlan(wpa_s) ||
7245 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007246 wpa_supplicant_deauthenticate(
7247 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007248
Hai Shalomfdcde762020-04-02 11:19:20 -07007249 wpa_drv_set_countermeasures(wpa_s, 0);
7250 wpa_clear_keys(wpa_s, NULL);
7251 } else {
7252 wpa_msg(wpa_s, MSG_INFO,
7253 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7254 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007255 }
7256
7257 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007258 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007259
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007260 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007261 radio_remove_interface(wpa_s);
7262
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007263#ifdef CONFIG_FST
7264 if (wpa_s->fst) {
7265 fst_detach(wpa_s->fst);
7266 wpa_s->fst = NULL;
7267 }
7268 if (wpa_s->received_mb_ies) {
7269 wpabuf_free(wpa_s->received_mb_ies);
7270 wpa_s->received_mb_ies = NULL;
7271 }
7272#endif /* CONFIG_FST */
7273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007274 if (wpa_s->drv_priv)
7275 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007276
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007277 if (notify)
7278 wpas_notify_iface_removed(wpa_s);
7279
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007280 if (terminate)
7281 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007282
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007283 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7284 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007285
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007286#ifdef CONFIG_MESH
7287 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007288 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007289 wpa_s->ifmsh = NULL;
7290 }
7291#endif /* CONFIG_MESH */
7292
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007293 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007294 wpa_config_free(wpa_s->conf);
7295 wpa_s->conf = NULL;
7296 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007297
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007298 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007299 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007300
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007301 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007302}
7303
7304
Dmitry Shmidte4663042016-04-04 10:07:49 -07007305#ifdef CONFIG_MATCH_IFACE
7306
7307/**
7308 * wpa_supplicant_match_iface - Match an interface description to a name
7309 * @global: Pointer to global data from wpa_supplicant_init()
7310 * @ifname: Name of the interface to match
7311 * Returns: Pointer to the created interface description or %NULL on failure
7312 */
7313struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7314 const char *ifname)
7315{
7316 int i;
7317 struct wpa_interface *iface, *miface;
7318
7319 for (i = 0; i < global->params.match_iface_count; i++) {
7320 miface = &global->params.match_ifaces[i];
7321 if (!miface->ifname ||
7322 fnmatch(miface->ifname, ifname, 0) == 0) {
7323 iface = os_zalloc(sizeof(*iface));
7324 if (!iface)
7325 return NULL;
7326 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007327 if (!miface->ifname)
7328 iface->matched = WPA_IFACE_MATCHED_NULL;
7329 else
7330 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007331 iface->ifname = ifname;
7332 return iface;
7333 }
7334 }
7335
7336 return NULL;
7337}
7338
7339
7340/**
7341 * wpa_supplicant_match_existing - Match existing interfaces
7342 * @global: Pointer to global data from wpa_supplicant_init()
7343 * Returns: 0 on success, -1 on failure
7344 */
7345static int wpa_supplicant_match_existing(struct wpa_global *global)
7346{
7347 struct if_nameindex *ifi, *ifp;
7348 struct wpa_supplicant *wpa_s;
7349 struct wpa_interface *iface;
7350
7351 ifp = if_nameindex();
7352 if (!ifp) {
7353 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7354 return -1;
7355 }
7356
7357 for (ifi = ifp; ifi->if_name; ifi++) {
7358 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7359 if (wpa_s)
7360 continue;
7361 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7362 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007363 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007364 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007365 }
7366 }
7367
7368 if_freenameindex(ifp);
7369 return 0;
7370}
7371
7372#endif /* CONFIG_MATCH_IFACE */
7373
7374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007375/**
7376 * wpa_supplicant_add_iface - Add a new network interface
7377 * @global: Pointer to global data from wpa_supplicant_init()
7378 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007379 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007380 * Returns: Pointer to the created interface or %NULL on failure
7381 *
7382 * This function is used to add new network interfaces for %wpa_supplicant.
7383 * This can be called before wpa_supplicant_run() to add interfaces before the
7384 * main event loop has been started. In addition, new interfaces can be added
7385 * dynamically while %wpa_supplicant is already running. This could happen,
7386 * e.g., when a hotplug network adapter is inserted.
7387 */
7388struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007389 struct wpa_interface *iface,
7390 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007391{
7392 struct wpa_supplicant *wpa_s;
7393 struct wpa_interface t_iface;
7394 struct wpa_ssid *ssid;
7395
7396 if (global == NULL || iface == NULL)
7397 return NULL;
7398
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007399 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007400 if (wpa_s == NULL)
7401 return NULL;
7402
7403 wpa_s->global = global;
7404
7405 t_iface = *iface;
7406 if (global->params.override_driver) {
7407 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7408 "('%s' -> '%s')",
7409 iface->driver, global->params.override_driver);
7410 t_iface.driver = global->params.override_driver;
7411 }
7412 if (global->params.override_ctrl_interface) {
7413 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7414 "ctrl_interface ('%s' -> '%s')",
7415 iface->ctrl_interface,
7416 global->params.override_ctrl_interface);
7417 t_iface.ctrl_interface =
7418 global->params.override_ctrl_interface;
7419 }
7420 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7421 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7422 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007423 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007424 return NULL;
7425 }
7426
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007427 /* Notify the control interfaces about new iface */
7428 if (wpas_notify_iface_added(wpa_s)) {
7429 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7430 return NULL;
7431 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007432
Jimmy Chene2206be2022-07-10 10:25:21 +08007433 /* Notify the control interfaces about new networks */
7434 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7435 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007436 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007437 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7438 && os_strncmp((const char *) ssid->ssid,
7439 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7440 wpas_notify_persistent_group_added(wpa_s, ssid);
7441 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007442 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007443
7444 wpa_s->next = global->ifaces;
7445 global->ifaces = wpa_s;
7446
7447 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007448 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007449
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007450#ifdef CONFIG_P2P
7451 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007452 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007453 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007454 wpas_p2p_add_p2pdev_interface(
7455 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007456 wpa_printf(MSG_INFO,
7457 "P2P: Failed to enable P2P Device interface");
7458 /* Try to continue without. P2P will be disabled. */
7459 }
7460#endif /* CONFIG_P2P */
7461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007462 return wpa_s;
7463}
7464
7465
7466/**
7467 * wpa_supplicant_remove_iface - Remove a network interface
7468 * @global: Pointer to global data from wpa_supplicant_init()
7469 * @wpa_s: Pointer to the network interface to be removed
7470 * Returns: 0 if interface was removed, -1 if interface was not found
7471 *
7472 * This function can be used to dynamically remove network interfaces from
7473 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7474 * addition, this function is used to remove all remaining interfaces when
7475 * %wpa_supplicant is terminated.
7476 */
7477int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007478 struct wpa_supplicant *wpa_s,
7479 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007480{
7481 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007482#ifdef CONFIG_MESH
7483 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7484 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007485 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007486#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007487
7488 /* Remove interface from the global list of interfaces */
7489 prev = global->ifaces;
7490 if (prev == wpa_s) {
7491 global->ifaces = wpa_s->next;
7492 } else {
7493 while (prev && prev->next != wpa_s)
7494 prev = prev->next;
7495 if (prev == NULL)
7496 return -1;
7497 prev->next = wpa_s->next;
7498 }
7499
7500 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7501
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007502#ifdef CONFIG_MESH
7503 if (mesh_if_created) {
7504 ifname = os_strdup(wpa_s->ifname);
7505 if (ifname == NULL) {
7506 wpa_dbg(wpa_s, MSG_ERROR,
7507 "mesh: Failed to malloc ifname");
7508 return -1;
7509 }
7510 }
7511#endif /* CONFIG_MESH */
7512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007513 if (global->p2p_group_formation == wpa_s)
7514 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007515 if (global->p2p_invite_group == wpa_s)
7516 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007517 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007518
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007519#ifdef CONFIG_MESH
7520 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007521 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007522 os_free(ifname);
7523 }
7524#endif /* CONFIG_MESH */
7525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007526 return 0;
7527}
7528
7529
7530/**
7531 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7532 * @wpa_s: Pointer to the network interface
7533 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7534 */
7535const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7536{
7537 const char *eapol_method;
7538
7539 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7540 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7541 return "NO-EAP";
7542 }
7543
7544 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7545 if (eapol_method == NULL)
7546 return "UNKNOWN-EAP";
7547
7548 return eapol_method;
7549}
7550
7551
7552/**
7553 * wpa_supplicant_get_iface - Get a new network interface
7554 * @global: Pointer to global data from wpa_supplicant_init()
7555 * @ifname: Interface name
7556 * Returns: Pointer to the interface or %NULL if not found
7557 */
7558struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7559 const char *ifname)
7560{
7561 struct wpa_supplicant *wpa_s;
7562
7563 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7564 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7565 return wpa_s;
7566 }
7567 return NULL;
7568}
7569
7570
7571#ifndef CONFIG_NO_WPA_MSG
7572static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7573{
7574 struct wpa_supplicant *wpa_s = ctx;
7575 if (wpa_s == NULL)
7576 return NULL;
7577 return wpa_s->ifname;
7578}
7579#endif /* CONFIG_NO_WPA_MSG */
7580
7581
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007582#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7583#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7584#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7585
7586/* Periodic cleanup tasks */
7587static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7588{
7589 struct wpa_global *global = eloop_ctx;
7590 struct wpa_supplicant *wpa_s;
7591
7592 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7593 wpas_periodic, global, NULL);
7594
7595#ifdef CONFIG_P2P
7596 if (global->p2p)
7597 p2p_expire_peers(global->p2p);
7598#endif /* CONFIG_P2P */
7599
7600 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7601 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7602#ifdef CONFIG_AP
7603 ap_periodic(wpa_s);
7604#endif /* CONFIG_AP */
7605 }
7606}
7607
7608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007609/**
7610 * wpa_supplicant_init - Initialize %wpa_supplicant
7611 * @params: Parameters for %wpa_supplicant
7612 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7613 *
7614 * This function is used to initialize %wpa_supplicant. After successful
7615 * initialization, the returned data pointer can be used to add and remove
7616 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7617 */
7618struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7619{
7620 struct wpa_global *global;
7621 int ret, i;
7622
7623 if (params == NULL)
7624 return NULL;
7625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007626#ifdef CONFIG_DRIVER_NDIS
7627 {
7628 void driver_ndis_init_ops(void);
7629 driver_ndis_init_ops();
7630 }
7631#endif /* CONFIG_DRIVER_NDIS */
7632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007633#ifndef CONFIG_NO_WPA_MSG
7634 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7635#endif /* CONFIG_NO_WPA_MSG */
7636
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007637 if (params->wpa_debug_file_path)
7638 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007639 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007640 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007641 if (params->wpa_debug_syslog)
7642 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007643 if (params->wpa_debug_tracing) {
7644 ret = wpa_debug_open_linux_tracing();
7645 if (ret) {
7646 wpa_printf(MSG_ERROR,
7647 "Failed to enable trace logging");
7648 return NULL;
7649 }
7650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007651
7652 ret = eap_register_methods();
7653 if (ret) {
7654 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7655 if (ret == -2)
7656 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7657 "the same EAP type.");
7658 return NULL;
7659 }
7660
7661 global = os_zalloc(sizeof(*global));
7662 if (global == NULL)
7663 return NULL;
7664 dl_list_init(&global->p2p_srv_bonjour);
7665 dl_list_init(&global->p2p_srv_upnp);
7666 global->params.daemonize = params->daemonize;
7667 global->params.wait_for_monitor = params->wait_for_monitor;
7668 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007669
7670 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007671 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007672 if (!global->params.pid_file) {
7673 wpa_supplicant_deinit(global);
7674 return NULL;
7675 }
7676 }
7677
7678 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007679 global->params.ctrl_interface =
7680 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007681 if (!global->params.ctrl_interface) {
7682 wpa_supplicant_deinit(global);
7683 return NULL;
7684 }
7685 }
7686
7687 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007688 global->params.ctrl_interface_group =
7689 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007690 if (!global->params.ctrl_interface_group) {
7691 wpa_supplicant_deinit(global);
7692 return NULL;
7693 }
7694 }
7695
7696 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007697 global->params.override_driver =
7698 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007699 if (!global->params.override_driver) {
7700 wpa_supplicant_deinit(global);
7701 return NULL;
7702 }
7703 }
7704
7705 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007706 global->params.override_ctrl_interface =
7707 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007708 if (!global->params.override_ctrl_interface) {
7709 wpa_supplicant_deinit(global);
7710 return NULL;
7711 }
7712 }
7713
Dmitry Shmidte4663042016-04-04 10:07:49 -07007714#ifdef CONFIG_MATCH_IFACE
7715 global->params.match_iface_count = params->match_iface_count;
7716 if (params->match_iface_count) {
7717 global->params.match_ifaces =
7718 os_calloc(params->match_iface_count,
7719 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007720 if (!global->params.match_ifaces) {
7721 wpa_printf(MSG_ERROR,
7722 "Failed to allocate match interfaces");
7723 wpa_supplicant_deinit(global);
7724 return NULL;
7725 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007726 os_memcpy(global->params.match_ifaces,
7727 params->match_ifaces,
7728 params->match_iface_count *
7729 sizeof(struct wpa_interface));
7730 }
7731#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007732#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007733 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007734 global->params.conf_p2p_dev =
7735 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007736 if (!global->params.conf_p2p_dev) {
7737 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7738 wpa_supplicant_deinit(global);
7739 return NULL;
7740 }
7741 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007742#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007743 wpa_debug_level = global->params.wpa_debug_level =
7744 params->wpa_debug_level;
7745 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7746 params->wpa_debug_show_keys;
7747 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7748 params->wpa_debug_timestamp;
7749
Hai Shalomfdcde762020-04-02 11:19:20 -07007750 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007751
7752 if (eloop_init()) {
7753 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7754 wpa_supplicant_deinit(global);
7755 return NULL;
7756 }
7757
Jouni Malinen75ecf522011-06-27 15:19:46 -07007758 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007759
7760 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7761 if (global->ctrl_iface == NULL) {
7762 wpa_supplicant_deinit(global);
7763 return NULL;
7764 }
7765
7766 if (wpas_notify_supplicant_initialized(global)) {
7767 wpa_supplicant_deinit(global);
7768 return NULL;
7769 }
7770
7771 for (i = 0; wpa_drivers[i]; i++)
7772 global->drv_count++;
7773 if (global->drv_count == 0) {
7774 wpa_printf(MSG_ERROR, "No drivers enabled");
7775 wpa_supplicant_deinit(global);
7776 return NULL;
7777 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007778 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007779 if (global->drv_priv == NULL) {
7780 wpa_supplicant_deinit(global);
7781 return NULL;
7782 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007783
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007784#ifdef CONFIG_WIFI_DISPLAY
7785 if (wifi_display_init(global) < 0) {
7786 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7787 wpa_supplicant_deinit(global);
7788 return NULL;
7789 }
7790#endif /* CONFIG_WIFI_DISPLAY */
7791
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007792 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7793 wpas_periodic, global, NULL);
7794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007795 return global;
7796}
7797
7798
7799/**
7800 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7801 * @global: Pointer to global data from wpa_supplicant_init()
7802 * Returns: 0 after successful event loop run, -1 on failure
7803 *
7804 * This function starts the main event loop and continues running as long as
7805 * there are any remaining events. In most cases, this function is running as
7806 * long as the %wpa_supplicant process in still in use.
7807 */
7808int wpa_supplicant_run(struct wpa_global *global)
7809{
7810 struct wpa_supplicant *wpa_s;
7811
7812 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007813 (wpa_supplicant_daemon(global->params.pid_file) ||
7814 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007815 return -1;
7816
Dmitry Shmidte4663042016-04-04 10:07:49 -07007817#ifdef CONFIG_MATCH_IFACE
7818 if (wpa_supplicant_match_existing(global))
7819 return -1;
7820#endif
7821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007822 if (global->params.wait_for_monitor) {
7823 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007824 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007825 wpa_supplicant_ctrl_iface_wait(
7826 wpa_s->ctrl_iface);
7827 }
7828
7829 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7830 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7831
7832 eloop_run();
7833
7834 return 0;
7835}
7836
7837
7838/**
7839 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7840 * @global: Pointer to global data from wpa_supplicant_init()
7841 *
7842 * This function is called to deinitialize %wpa_supplicant and to free all
7843 * allocated resources. Remaining network interfaces will also be removed.
7844 */
7845void wpa_supplicant_deinit(struct wpa_global *global)
7846{
7847 int i;
7848
7849 if (global == NULL)
7850 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007851
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007852 eloop_cancel_timeout(wpas_periodic, global, NULL);
7853
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007854#ifdef CONFIG_WIFI_DISPLAY
7855 wifi_display_deinit(global);
7856#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007857
7858 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007859 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007860
7861 if (global->ctrl_iface)
7862 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7863
7864 wpas_notify_supplicant_deinitialized(global);
7865
7866 eap_peer_unregister_methods();
7867#ifdef CONFIG_AP
7868 eap_server_unregister_methods();
7869#endif /* CONFIG_AP */
7870
7871 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7872 if (!global->drv_priv[i])
7873 continue;
7874 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7875 }
7876 os_free(global->drv_priv);
7877
7878 random_deinit();
7879
7880 eloop_destroy();
7881
7882 if (global->params.pid_file) {
7883 os_daemonize_terminate(global->params.pid_file);
7884 os_free(global->params.pid_file);
7885 }
7886 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007887 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007888 os_free(global->params.override_driver);
7889 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007890#ifdef CONFIG_MATCH_IFACE
7891 os_free(global->params.match_ifaces);
7892#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007893#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007894 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007895#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007896
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007897 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007898 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007899 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007900
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007901 os_free(global);
7902 wpa_debug_close_syslog();
7903 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007904 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007905}
7906
7907
7908void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7909{
7910 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7911 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7912 char country[3];
7913 country[0] = wpa_s->conf->country[0];
7914 country[1] = wpa_s->conf->country[1];
7915 country[2] = '\0';
7916 if (wpa_drv_set_country(wpa_s, country) < 0) {
7917 wpa_printf(MSG_ERROR, "Failed to set country code "
7918 "'%s'", country);
7919 }
7920 }
7921
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007922 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7923 wpas_init_ext_pw(wpa_s);
7924
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007925 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7926 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7927
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007928 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7929 struct wpa_driver_capa capa;
7930 int res = wpa_drv_get_capa(wpa_s, &capa);
7931
7932 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7933 wpa_printf(MSG_ERROR,
7934 "Failed to update wowlan_triggers to '%s'",
7935 wpa_s->conf->wowlan_triggers);
7936 }
7937
Hai Shalom81f62d82019-07-22 12:10:00 -07007938 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7939 wpa_supplicant_set_default_scan_ies(wpa_s);
7940
Hai Shalom899fcc72020-10-19 14:38:18 -07007941#ifdef CONFIG_BGSCAN
7942 /*
7943 * We default to global bgscan parameters only when per-network bgscan
7944 * parameters aren't set. Only bother resetting bgscan parameters if
7945 * this is the case.
7946 */
7947 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7948 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7949 wpa_s->wpa_state == WPA_COMPLETED)
7950 wpa_supplicant_reset_bgscan(wpa_s);
7951#endif /* CONFIG_BGSCAN */
7952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007953#ifdef CONFIG_WPS
7954 wpas_wps_update_config(wpa_s);
7955#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007956 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007957 wpa_s->conf->changed_parameters = 0;
7958}
7959
7960
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007961void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007962{
7963 int i;
7964
7965 for (i = 0; i < *num_freqs; i++) {
7966 if (freqs[i] == freq)
7967 return;
7968 }
7969
7970 freqs[*num_freqs] = freq;
7971 (*num_freqs)++;
7972}
7973
7974
7975static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7976{
7977 struct wpa_bss *bss, *cbss;
7978 const int max_freqs = 10;
7979 int *freqs;
7980 int num_freqs = 0;
7981
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007982 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007983 if (freqs == NULL)
7984 return NULL;
7985
7986 cbss = wpa_s->current_bss;
7987
7988 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7989 if (bss == cbss)
7990 continue;
7991 if (bss->ssid_len == cbss->ssid_len &&
7992 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007993 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007994 add_freq(freqs, &num_freqs, bss->freq);
7995 if (num_freqs == max_freqs)
7996 break;
7997 }
7998 }
7999
8000 if (num_freqs == 0) {
8001 os_free(freqs);
8002 freqs = NULL;
8003 }
8004
8005 return freqs;
8006}
8007
8008
8009void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8010{
8011 int timeout;
8012 int count;
8013 int *freqs = NULL;
8014
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008015 wpas_connect_work_done(wpa_s);
8016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008017 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008018 * Remove possible authentication timeout since the connection failed.
8019 */
8020 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8021
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008022 /*
Hai Shalom60840252021-02-19 19:02:11 -08008023 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008024 * generated based on local request to disconnect.
8025 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008026 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008027 wpa_s->own_disconnect_req = 0;
8028 wpa_dbg(wpa_s, MSG_DEBUG,
8029 "Ignore connection failure due to local request to disconnect");
8030 return;
8031 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008032 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008033 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8034 "indication since interface has been put into "
8035 "disconnected state");
8036 return;
8037 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008038 if (wpa_s->auto_reconnect_disabled) {
8039 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8040 "indication since auto connect is disabled");
8041 return;
8042 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008043
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008044 /*
Hai Shalom60840252021-02-19 19:02:11 -08008045 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008046 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008047 */
Hai Shalom60840252021-02-19 19:02:11 -08008048 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008049 if (count == 1 && wpa_s->current_bss) {
8050 /*
Hai Shalom60840252021-02-19 19:02:11 -08008051 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008052 * another BSS available for the same ESS, we should try that
8053 * next. Otherwise, we may as well try this one once more
8054 * before allowing other, likely worse, ESSes to be considered.
8055 */
8056 freqs = get_bss_freqs_in_ess(wpa_s);
8057 if (freqs) {
8058 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8059 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008060 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008061 /*
8062 * On the next scan, go through only the known channels
8063 * used in this ESS based on previous scans to speed up
8064 * common load balancing use case.
8065 */
8066 os_free(wpa_s->next_scan_freqs);
8067 wpa_s->next_scan_freqs = freqs;
8068 }
8069 }
8070
Hai Shalom899fcc72020-10-19 14:38:18 -07008071 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008072
Hai Shalom899fcc72020-10-19 14:38:18 -07008073 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008074 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8075 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008076 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008077 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008078 /*
8079 * Multiple consecutive connection failures mean that other APs are
8080 * either not available or have already been tried, so we can start
8081 * increasing the delay here to avoid constant scanning.
8082 */
8083 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008084 case 1:
8085 timeout = 100;
8086 break;
8087 case 2:
8088 timeout = 500;
8089 break;
8090 case 3:
8091 timeout = 1000;
8092 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008093 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008094 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008095 break;
8096 default:
8097 timeout = 10000;
8098 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008099 }
8100
Hai Shalom899fcc72020-10-19 14:38:18 -07008101 wpa_dbg(wpa_s, MSG_DEBUG,
8102 "Consecutive connection failures: %d --> request scan in %d ms",
8103 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008104
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008105 /*
8106 * TODO: if more than one possible AP is available in scan results,
8107 * could try the other ones before requesting a new scan.
8108 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008109
8110 /* speed up the connection attempt with normal scan */
8111 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008112 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8113 1000 * (timeout % 1000));
8114}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008115
8116
Hai Shalomce48b4a2018-09-05 11:41:35 -07008117#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008118
8119void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8120{
8121 struct wpa_ssid *ssid = wpa_s->current_ssid;
8122 const u8 *realm, *username, *rrk;
8123 size_t realm_len, username_len, rrk_len;
8124 u16 next_seq_num;
8125
8126 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8127 * Check for ERP keys existing to limit when this can be done since
8128 * the rejection response is not protected and such triggers should
8129 * really not allow internal state to be modified unless required to
8130 * avoid significant issues in functionality. In addition, drop
8131 * externally configure PMKSA entries even without ERP keys since it
8132 * is possible for an external component to add PMKSA entries for FILS
8133 * authentication without restoring previously generated ERP keys.
8134 *
8135 * In this case, this is needed to allow recovery from cases where the
8136 * AP or authentication server has dropped PMKSAs and ERP keys. */
8137 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8138 return;
8139
8140 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8141 &username, &username_len,
8142 &realm, &realm_len, &next_seq_num,
8143 &rrk, &rrk_len) != 0 ||
8144 !realm) {
8145 wpa_dbg(wpa_s, MSG_DEBUG,
8146 "FILS: Drop external PMKSA cache entry");
8147 wpa_sm_aborted_external_cached(wpa_s->wpa);
8148 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8149 return;
8150 }
8151
8152 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8153 wpa_sm_aborted_cached(wpa_s->wpa);
8154 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8155}
8156
8157
Hai Shalomce48b4a2018-09-05 11:41:35 -07008158void fils_connection_failure(struct wpa_supplicant *wpa_s)
8159{
8160 struct wpa_ssid *ssid = wpa_s->current_ssid;
8161 const u8 *realm, *username, *rrk;
8162 size_t realm_len, username_len, rrk_len;
8163 u16 next_seq_num;
8164
8165 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8166 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8167 &username, &username_len,
8168 &realm, &realm_len, &next_seq_num,
8169 &rrk, &rrk_len) != 0 ||
8170 !realm)
8171 return;
8172
8173 wpa_hexdump_ascii(MSG_DEBUG,
8174 "FILS: Store last connection failure realm",
8175 realm, realm_len);
8176 os_free(wpa_s->last_con_fail_realm);
8177 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8178 if (wpa_s->last_con_fail_realm) {
8179 wpa_s->last_con_fail_realm_len = realm_len;
8180 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8181 }
8182}
8183#endif /* CONFIG_FILS */
8184
8185
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008186int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8187{
8188 return wpa_s->conf->ap_scan == 2 ||
8189 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8190}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008191
Dmitry Shmidt04949592012-07-19 12:16:46 -07008192
Gabriel Biren57ededa2021-09-03 16:08:50 +00008193#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008194int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8195 struct wpa_ssid *ssid,
8196 const char *field,
8197 const char *value)
8198{
8199#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008200 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008201
8202 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8203 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8204 (const u8 *) value, os_strlen(value));
8205
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008206 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008207 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008208#else /* IEEE8021X_EAPOL */
8209 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8210 return -1;
8211#endif /* IEEE8021X_EAPOL */
8212}
8213
8214int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8215 struct wpa_ssid *ssid,
8216 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008217 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008218{
8219#ifdef IEEE8021X_EAPOL
8220 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008221 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008222
8223 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008224 case WPA_CTRL_REQ_EAP_IDENTITY:
8225 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008226 os_free(eap->imsi_identity);
8227 if (value == NULL)
8228 return -1;
8229 identity = os_strchr(value, ':');
8230 if (identity == NULL) {
8231 /* plain identity */
8232 eap->identity = (u8 *)os_strdup(value);
8233 eap->identity_len = os_strlen(value);
8234 } else {
8235 /* have both plain identity and encrypted identity */
8236 imsi_identity = value;
8237 *identity++ = '\0';
8238 /* plain identity */
8239 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8240 eap->imsi_identity_len = strlen(imsi_identity);
8241 /* encrypted identity */
8242 eap->identity = (u8 *)dup_binstr(identity,
8243 value_len - strlen(imsi_identity) - 1);
8244 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8245 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008246 eap->pending_req_identity = 0;
8247 if (ssid == wpa_s->current_ssid)
8248 wpa_s->reassociate = 1;
8249 break;
8250 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008251 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008252 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008253 if (!eap->password)
8254 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008255 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008256 eap->pending_req_password = 0;
8257 if (ssid == wpa_s->current_ssid)
8258 wpa_s->reassociate = 1;
8259 break;
8260 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008261 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008262 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008263 if (!eap->new_password)
8264 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008265 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008266 eap->pending_req_new_password = 0;
8267 if (ssid == wpa_s->current_ssid)
8268 wpa_s->reassociate = 1;
8269 break;
8270 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008271 str_clear_free(eap->cert.pin);
8272 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008273 if (!eap->cert.pin)
8274 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008275 eap->pending_req_pin = 0;
8276 if (ssid == wpa_s->current_ssid)
8277 wpa_s->reassociate = 1;
8278 break;
8279 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008280 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008281 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008282 if (!eap->otp)
8283 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008284 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008285 os_free(eap->pending_req_otp);
8286 eap->pending_req_otp = NULL;
8287 eap->pending_req_otp_len = 0;
8288 break;
8289 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008290 str_clear_free(eap->cert.private_key_passwd);
8291 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008292 if (!eap->cert.private_key_passwd)
8293 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008294 eap->pending_req_passphrase = 0;
8295 if (ssid == wpa_s->current_ssid)
8296 wpa_s->reassociate = 1;
8297 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008298 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008299 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008300 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008301 if (!eap->external_sim_resp)
8302 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008303 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008304 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008305 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8306 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8307 return -1;
8308 ssid->mem_only_psk = 1;
8309 if (ssid->passphrase)
8310 wpa_config_update_psk(ssid);
8311 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8312 wpa_supplicant_req_scan(wpa_s, 0, 0);
8313 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008314 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8315 if (eap->pending_ext_cert_check != PENDING_CHECK)
8316 return -1;
8317 if (os_strcmp(value, "good") == 0)
8318 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8319 else if (os_strcmp(value, "bad") == 0)
8320 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8321 else
8322 return -1;
8323 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008324 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008325 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008326 return -1;
8327 }
8328
8329 return 0;
8330#else /* IEEE8021X_EAPOL */
8331 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8332 return -1;
8333#endif /* IEEE8021X_EAPOL */
8334}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008335#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008336
8337
8338int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8339{
Hai Shalomfdcde762020-04-02 11:19:20 -07008340#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008341 int i;
8342 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008343#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008344
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008345 if (wpa_s->p2p_mgmt)
8346 return 1; /* no normal network profiles on p2p_mgmt interface */
8347
Dmitry Shmidt04949592012-07-19 12:16:46 -07008348 if (ssid == NULL)
8349 return 1;
8350
8351 if (ssid->disabled)
8352 return 1;
8353
Hai Shalomfdcde762020-04-02 11:19:20 -07008354#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008355 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008356 drv_enc = wpa_s->drv_enc;
8357 else
8358 drv_enc = (unsigned int) -1;
8359
8360 for (i = 0; i < NUM_WEP_KEYS; i++) {
8361 size_t len = ssid->wep_key_len[i];
8362 if (len == 0)
8363 continue;
8364 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8365 continue;
8366 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8367 continue;
8368 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8369 continue;
8370 return 1; /* invalid WEP key */
8371 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008372#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008373
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008374 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008375 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008376 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008377 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008378 return 1;
8379
Sunil Ravi89eba102022-09-13 21:04:37 -07008380#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008381#ifdef CRYPTO_RSA_OAEP_SHA256
8382 if (ssid->eap.imsi_privacy_cert) {
8383 struct crypto_rsa_key *key;
8384 bool failed = false;
8385
8386 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8387 if (!key)
8388 failed = true;
8389 crypto_rsa_key_free(key);
8390 if (failed) {
8391 wpa_printf(MSG_DEBUG,
8392 "Invalid imsi_privacy_cert (%s) - disable network",
8393 ssid->eap.imsi_privacy_cert);
8394 return 1;
8395 }
8396 }
8397#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008398#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008399
Dmitry Shmidt04949592012-07-19 12:16:46 -07008400 return 0;
8401}
8402
8403
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008404int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8405{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008406 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8407 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8408 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8409 /*
8410 * Driver does not support BIP -- ignore pmf=1 default
8411 * since the connection with PMF would fail and the
8412 * configuration does not require PMF to be enabled.
8413 */
8414 return NO_MGMT_FRAME_PROTECTION;
8415 }
8416
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008417 if (ssid &&
8418 (ssid->key_mgmt &
8419 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8420 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8421 /*
8422 * Do not use the default PMF value for non-RSN networks
8423 * since PMF is available only with RSN and pmf=2
8424 * configuration would otherwise prevent connections to
8425 * all open networks.
8426 */
8427 return NO_MGMT_FRAME_PROTECTION;
8428 }
8429
Sunil Ravi77d572f2023-01-17 23:58:31 +00008430#ifdef CONFIG_OCV
8431 /* Enable PMF if OCV is being enabled */
8432 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8433 ssid && ssid->ocv)
8434 return MGMT_FRAME_PROTECTION_OPTIONAL;
8435#endif /* CONFIG_OCV */
8436
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008437 return wpa_s->conf->pmf;
8438 }
8439
8440 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008441}
8442
8443
Sunil Ravi77d572f2023-01-17 23:58:31 +00008444#ifdef CONFIG_SAE
8445bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8446 struct wpa_ssid *ssid,
8447 const struct wpa_ie_data *ie)
8448{
8449 return wpa_s->conf->sae_check_mfp &&
8450 (!(ie->capabilities &
8451 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8452 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8453}
8454#endif /* CONFIG_SAE */
8455
8456
Hai Shalomc1a21442022-02-04 13:43:00 -08008457int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8458{
8459 if (wpa_s->current_ssid == NULL ||
8460 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8461 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8462 return 0;
8463 return wpa_sm_pmf_enabled(wpa_s->wpa);
8464}
8465
8466
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008467int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008468{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008469 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008470 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008471 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008472 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008473 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008474}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008475
8476
Sunil Ravi77d572f2023-01-17 23:58:31 +00008477void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8478 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008479{
8480 struct wpa_ssid *ssid = wpa_s->current_ssid;
8481 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008482 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008483
8484 if (ssid == NULL) {
8485 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8486 "SSID block");
8487 return;
8488 }
8489
8490 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8491 return;
8492
8493 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008494
8495#ifdef CONFIG_P2P
8496 if (ssid->p2p_group &&
8497 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8498 /*
8499 * Skip the wait time since there is a short timeout on the
8500 * connection to a P2P group.
8501 */
8502 return;
8503 }
8504#endif /* CONFIG_P2P */
8505
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008506 if (ssid->auth_failures > 50)
8507 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008508 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008509 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008510 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008511 dur = 90;
8512 else if (ssid->auth_failures > 3)
8513 dur = 60;
8514 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008515 dur = 30;
8516 else if (ssid->auth_failures > 1)
8517 dur = 20;
8518 else
8519 dur = 10;
8520
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008521 if (ssid->auth_failures > 1 &&
8522 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8523 dur += os_random() % (ssid->auth_failures * 10);
8524
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008525 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008526 if (now.sec + dur <= ssid->disabled_until.sec)
8527 return;
8528
8529 ssid->disabled_until.sec = now.sec + dur;
8530
8531 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008532 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008533 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008534 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008535
8536 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8537 int msg_len = snprintf(NULL, 0, format_str,
8538 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8539 ssid->auth_failures, dur, reason) + 1;
8540 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308541 if (!msg)
8542 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008543 snprintf(msg, msg_len, format_str,
8544 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8545 ssid->auth_failures, dur, reason);
8546 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8547 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008548
8549 if (bssid)
8550 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008551}
8552
8553
8554void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8555 struct wpa_ssid *ssid, int clear_failures)
8556{
8557 if (ssid == NULL)
8558 return;
8559
8560 if (ssid->disabled_until.sec) {
8561 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8562 "id=%d ssid=\"%s\"",
8563 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8564 }
8565 ssid->disabled_until.sec = 0;
8566 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008567 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008568 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008569 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8570 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8571 " ignored to allow a lower priority BSS, if any, to be tried next",
8572 MAC2STR(ssid->disabled_due_to));
8573 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8574 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8575 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008576}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008577
8578
8579int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8580{
8581 size_t i;
8582
8583 if (wpa_s->disallow_aps_bssid == NULL)
8584 return 0;
8585
8586 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8587 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8588 bssid, ETH_ALEN) == 0)
8589 return 1;
8590 }
8591
8592 return 0;
8593}
8594
8595
8596int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8597 size_t ssid_len)
8598{
8599 size_t i;
8600
8601 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8602 return 0;
8603
8604 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8605 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8606 if (ssid_len == s->ssid_len &&
8607 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8608 return 1;
8609 }
8610
8611 return 0;
8612}
8613
8614
8615/**
8616 * wpas_request_connection - Request a new connection
8617 * @wpa_s: Pointer to the network interface
8618 *
8619 * This function is used to request a new connection to be found. It will mark
8620 * the interface to allow reassociation and request a new scan to find a
8621 * suitable network to connect to.
8622 */
8623void wpas_request_connection(struct wpa_supplicant *wpa_s)
8624{
8625 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008626 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008627 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008628 wpa_s->disconnected = 0;
8629 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008630 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008631
8632 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8633 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008634 else
8635 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008636}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008637
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008638
Roshan Pius02242d72016-08-09 15:31:48 -07008639/**
8640 * wpas_request_disconnection - Request disconnection
8641 * @wpa_s: Pointer to the network interface
8642 *
8643 * This function is used to request disconnection from the currently connected
8644 * network. This will stop any ongoing scans and initiate deauthentication.
8645 */
8646void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8647{
8648#ifdef CONFIG_SME
8649 wpa_s->sme.prev_bssid_set = 0;
8650#endif /* CONFIG_SME */
8651 wpa_s->reassociate = 0;
8652 wpa_s->disconnected = 1;
8653 wpa_supplicant_cancel_sched_scan(wpa_s);
8654 wpa_supplicant_cancel_scan(wpa_s);
8655 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8656 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008657 radio_remove_works(wpa_s, "connect", 0);
8658 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008659 wpa_s->roam_in_progress = false;
8660#ifdef CONFIG_WNM
8661 wpa_s->bss_trans_mgmt_in_progress = false;
8662#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008663}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008664
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008665
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008666void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8667 struct wpa_used_freq_data *freqs_data,
8668 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008669{
8670 unsigned int i;
8671
8672 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8673 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008674 for (i = 0; i < len; i++) {
8675 struct wpa_used_freq_data *cur = &freqs_data[i];
8676 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8677 i, cur->freq, cur->flags);
8678 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008679}
8680
8681
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008682/*
8683 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008684 * are using the same radio as the current interface, and in addition, get
8685 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008686 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008687int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8688 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008689 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008690{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008691 struct wpa_supplicant *ifs;
8692 u8 bssid[ETH_ALEN];
8693 int freq;
8694 unsigned int idx = 0, i;
8695
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008696 wpa_dbg(wpa_s, MSG_DEBUG,
8697 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008698 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008699
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008700 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8701 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008702 if (idx == len)
8703 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008704
Sunil Ravi77d572f2023-01-17 23:58:31 +00008705 if (exclude_current && ifs == wpa_s)
8706 continue;
8707
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008708 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8709 continue;
8710
8711 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008712 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8713 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008714 freq = ifs->current_ssid->frequency;
8715 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8716 freq = ifs->assoc_freq;
8717 else
8718 continue;
8719
8720 /* Hold only distinct freqs */
8721 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008722 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008723 break;
8724
8725 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008726 freqs_data[idx++].freq = freq;
8727
8728 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008729 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008730 WPA_FREQ_USED_BY_P2P_CLIENT :
8731 WPA_FREQ_USED_BY_INFRA_STATION;
8732 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008733 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008734
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008735 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008736 return idx;
8737}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008738
8739
8740/*
8741 * Find the operating frequencies of any of the virtual interfaces that
8742 * are using the same radio as the current interface.
8743 */
8744int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008745 int *freq_array, unsigned int len,
8746 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008747{
8748 struct wpa_used_freq_data *freqs_data;
8749 int num, i;
8750
8751 os_memset(freq_array, 0, sizeof(int) * len);
8752
8753 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8754 if (!freqs_data)
8755 return -1;
8756
Sunil Ravi77d572f2023-01-17 23:58:31 +00008757 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8758 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008759 for (i = 0; i < num; i++)
8760 freq_array[i] = freqs_data[i].freq;
8761
8762 os_free(freqs_data);
8763
8764 return num;
8765}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008766
8767
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008768struct wpa_supplicant *
8769wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8770{
8771 switch (frame) {
8772#ifdef CONFIG_P2P
8773 case VENDOR_ELEM_PROBE_REQ_P2P:
8774 case VENDOR_ELEM_PROBE_RESP_P2P:
8775 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8776 case VENDOR_ELEM_BEACON_P2P_GO:
8777 case VENDOR_ELEM_P2P_PD_REQ:
8778 case VENDOR_ELEM_P2P_PD_RESP:
8779 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8780 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8781 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8782 case VENDOR_ELEM_P2P_INV_REQ:
8783 case VENDOR_ELEM_P2P_INV_RESP:
8784 case VENDOR_ELEM_P2P_ASSOC_REQ:
8785 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008786 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008787#endif /* CONFIG_P2P */
8788 default:
8789 return wpa_s;
8790 }
8791}
8792
8793
8794void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8795{
8796 unsigned int i;
8797 char buf[30];
8798
8799 wpa_printf(MSG_DEBUG, "Update vendor elements");
8800
8801 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8802 if (wpa_s->vendor_elem[i]) {
8803 int res;
8804
8805 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8806 if (!os_snprintf_error(sizeof(buf), res)) {
8807 wpa_hexdump_buf(MSG_DEBUG, buf,
8808 wpa_s->vendor_elem[i]);
8809 }
8810 }
8811 }
8812
8813#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008814 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008815 wpa_s->global->p2p &&
8816 !wpa_s->global->p2p_disabled)
8817 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8818#endif /* CONFIG_P2P */
8819}
8820
8821
8822int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8823 const u8 *elem, size_t len)
8824{
8825 u8 *ie, *end;
8826
8827 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8828 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8829
8830 for (; ie + 1 < end; ie += 2 + ie[1]) {
8831 if (ie + len > end)
8832 break;
8833 if (os_memcmp(ie, elem, len) != 0)
8834 continue;
8835
8836 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8837 wpabuf_free(wpa_s->vendor_elem[frame]);
8838 wpa_s->vendor_elem[frame] = NULL;
8839 } else {
8840 os_memmove(ie, ie + len, end - (ie + len));
8841 wpa_s->vendor_elem[frame]->used -= len;
8842 }
8843 wpas_vendor_elem_update(wpa_s);
8844 return 0;
8845 }
8846
8847 return -1;
8848}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008849
8850
8851struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008852 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008853 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008854{
8855 u16 i;
8856
Hai Shalomc1a21442022-02-04 13:43:00 -08008857 if (!modes)
8858 return NULL;
8859
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008860 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008861 if (modes[i].mode != mode ||
8862 !modes[i].num_channels || !modes[i].channels)
8863 continue;
8864 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8865 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008866 return &modes[i];
8867 }
8868
8869 return NULL;
8870}
8871
8872
Hai Shalomc1a21442022-02-04 13:43:00 -08008873struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8874 u16 num_modes, int freq)
8875{
8876 int i, j;
8877
8878 for (i = 0; i < num_modes; i++) {
8879 for (j = 0; j < modes[i].num_channels; j++) {
8880 if (freq == modes[i].channels[j].freq)
8881 return &modes[i];
8882 }
8883 }
8884
8885 return NULL;
8886}
8887
8888
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008889static struct
8890wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8891 const u8 *bssid)
8892{
8893 struct wpa_bss_tmp_disallowed *bss;
8894
8895 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8896 struct wpa_bss_tmp_disallowed, list) {
8897 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8898 return bss;
8899 }
8900
8901 return NULL;
8902}
8903
8904
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008905static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8906{
8907 struct wpa_bss_tmp_disallowed *tmp;
8908 unsigned int num_bssid = 0;
8909 u8 *bssids;
8910 int ret;
8911
8912 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8913 if (!bssids)
8914 return -1;
8915 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8916 struct wpa_bss_tmp_disallowed, list) {
8917 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8918 ETH_ALEN);
8919 num_bssid++;
8920 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008921 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008922 os_free(bssids);
8923 return ret;
8924}
8925
8926
8927static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8928{
8929 struct wpa_supplicant *wpa_s = eloop_ctx;
8930 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8931
8932 /* Make sure the bss is not already freed */
8933 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8934 struct wpa_bss_tmp_disallowed, list) {
8935 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008936 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008937 wpa_set_driver_tmp_disallow_list(wpa_s);
8938 break;
8939 }
8940 }
8941}
8942
8943
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008944void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008945 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008946{
8947 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008948
8949 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8950 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008951 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008952 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008953 }
8954
8955 bss = os_malloc(sizeof(*bss));
8956 if (!bss) {
8957 wpa_printf(MSG_DEBUG,
8958 "Failed to allocate memory for temp disallow BSS");
8959 return;
8960 }
8961
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008962 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8963 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008964 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008965
8966finish:
8967 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008968 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8969 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008970}
8971
8972
Hai Shalom74f70d42019-02-11 14:42:39 -08008973int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8974 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008975{
Hai Shalom74f70d42019-02-11 14:42:39 -08008976 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008977
8978 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8979 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008980 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8981 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008982 break;
8983 }
8984 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008985 if (!disallowed)
8986 return 0;
8987
8988 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008989 bss->level > disallowed->rssi_threshold) {
8990 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8991 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008992 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008993 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008994
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008995 return 1;
8996}
Hai Shalom81f62d82019-07-22 12:10:00 -07008997
8998
8999int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9000 unsigned int type, const u8 *addr,
9001 const u8 *mask)
9002{
9003 if ((addr && !mask) || (!addr && mask)) {
9004 wpa_printf(MSG_INFO,
9005 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9006 return -1;
9007 }
9008
9009 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9010 wpa_printf(MSG_INFO,
9011 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9012 return -1;
9013 }
9014
9015 if (type & MAC_ADDR_RAND_SCAN) {
9016 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9017 addr, mask))
9018 return -1;
9019 }
9020
9021 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9022 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9023 addr, mask))
9024 return -1;
9025
9026 if (wpa_s->sched_scanning && !wpa_s->pno)
9027 wpas_scan_restart_sched_scan(wpa_s);
9028 }
9029
9030 if (type & MAC_ADDR_RAND_PNO) {
9031 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9032 addr, mask))
9033 return -1;
9034
9035 if (wpa_s->pno) {
9036 wpas_stop_pno(wpa_s);
9037 wpas_start_pno(wpa_s);
9038 }
9039 }
9040
9041 return 0;
9042}
9043
9044
9045int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9046 unsigned int type)
9047{
9048 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9049 if (wpa_s->pno) {
9050 if (type & MAC_ADDR_RAND_PNO) {
9051 wpas_stop_pno(wpa_s);
9052 wpas_start_pno(wpa_s);
9053 }
9054 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9055 wpas_scan_restart_sched_scan(wpa_s);
9056 }
9057
9058 return 0;
9059}
Hai Shalomfdcde762020-04-02 11:19:20 -07009060
9061
9062int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9063 struct wpa_signal_info *si)
9064{
9065 int res;
9066
9067 if (!wpa_s->driver->signal_poll)
9068 return -1;
9069
9070 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9071
9072#ifdef CONFIG_TESTING_OPTIONS
9073 if (res == 0) {
9074 struct driver_signal_override *dso;
9075
9076 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9077 struct driver_signal_override, list) {
9078 if (os_memcmp(wpa_s->bssid, dso->bssid,
9079 ETH_ALEN) != 0)
9080 continue;
9081 wpa_printf(MSG_DEBUG,
9082 "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 +00009083 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009084 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009085 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009086 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009087 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009088 dso->si_avg_beacon_signal,
9089 si->current_noise,
9090 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009091 si->data.signal = dso->si_current_signal;
9092 si->data.avg_signal = dso->si_avg_signal;
9093 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009094 si->current_noise = dso->si_current_noise;
9095 break;
9096 }
9097 }
9098#endif /* CONFIG_TESTING_OPTIONS */
9099
9100 return res;
9101}
9102
9103
9104struct wpa_scan_results *
9105wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9106{
9107 struct wpa_scan_results *scan_res;
9108#ifdef CONFIG_TESTING_OPTIONS
9109 size_t idx;
9110#endif /* CONFIG_TESTING_OPTIONS */
9111
9112 if (!wpa_s->driver->get_scan_results2)
9113 return NULL;
9114
9115 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9116
9117#ifdef CONFIG_TESTING_OPTIONS
9118 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9119 struct driver_signal_override *dso;
9120 struct wpa_scan_res *res = scan_res->res[idx];
9121
9122 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9123 struct driver_signal_override, list) {
9124 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9125 continue;
9126 wpa_printf(MSG_DEBUG,
9127 "Override driver scan signal level %d->%d for "
9128 MACSTR,
9129 res->level, dso->scan_level,
9130 MAC2STR(res->bssid));
9131 res->flags |= WPA_SCAN_QUAL_INVALID;
9132 if (dso->scan_level < 0)
9133 res->flags |= WPA_SCAN_LEVEL_DBM;
9134 else
9135 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9136 res->level = dso->scan_level;
9137 break;
9138 }
9139 }
9140#endif /* CONFIG_TESTING_OPTIONS */
9141
9142 return scan_res;
9143}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009144
9145
9146static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9147{
9148 int i;
9149
9150 if (!wpa_s->valid_links)
9151 return false;
9152
9153 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9154 if (!(wpa_s->valid_links & BIT(i)))
9155 continue;
9156
9157 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9158 return true;
9159 }
9160
9161 return false;
9162}
9163
9164
9165int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9166 unsigned int wait, const u8 *dst, const u8 *src,
9167 const u8 *bssid, const u8 *data, size_t data_len,
9168 int no_cck)
9169{
9170 if (!wpa_s->driver->send_action)
9171 return -1;
9172
9173 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9174 if (wpas_ap_link_address(wpa_s, dst))
9175 dst = wpa_s->ap_mld_addr;
9176
9177 if (wpas_ap_link_address(wpa_s, bssid))
9178 bssid = wpa_s->ap_mld_addr;
9179 }
9180
9181 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9182 bssid, data, data_len, no_cck);
9183}