blob: 134bcf1e98616e4cceb2c0610bf289a60bf69a00 [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 Ravi036cec52023-03-29 11:35:17 -07002341void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
2342 bool force)
Hai Shalomc3565922019-10-28 11:58:20 -07002343{
2344#ifdef CONFIG_SAE
2345 int *groups = conf->sae_groups;
2346 int default_groups[] = { 19, 20, 21, 0 };
2347 const char *password;
2348
2349 if (!groups || groups[0] <= 0)
2350 groups = default_groups;
2351
2352 password = ssid->sae_password;
2353 if (!password)
2354 password = ssid->passphrase;
2355
Hai Shalom899fcc72020-10-19 14:38:18 -07002356 if (!password ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002357 (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002358 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002359 !force &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002360 !sae_pk_valid_password(password)) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002361 conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
Hai Shalomc3565922019-10-28 11:58:20 -07002362 /* PT derivation not needed */
2363 sae_deinit_pt(ssid->pt);
2364 ssid->pt = NULL;
2365 return;
2366 }
2367
2368 if (ssid->pt)
2369 return; /* PT already derived */
2370 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2371 (const u8 *) password, os_strlen(password),
2372 ssid->sae_password_id);
2373#endif /* CONFIG_SAE */
2374}
2375
2376
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002377static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2378{
2379#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2380 os_free(wpa_s->sme.sae_rejected_groups);
2381 wpa_s->sme.sae_rejected_groups = NULL;
2382#ifdef CONFIG_TESTING_OPTIONS
2383 if (wpa_s->extra_sae_rejected_groups) {
2384 int i, *groups = wpa_s->extra_sae_rejected_groups;
2385
2386 for (i = 0; groups[i]; i++) {
2387 wpa_printf(MSG_DEBUG,
2388 "TESTING: Indicate rejection of an extra SAE group %d",
2389 groups[i]);
2390 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2391 groups[i]);
2392 }
2393 }
2394#endif /* CONFIG_TESTING_OPTIONS */
2395#endif /* CONFIG_SAE && CONFIG_SME */
2396}
2397
2398
Hai Shalom60840252021-02-19 19:02:11 -08002399int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2400{
2401 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2402 wpa_msg(wpa_s, MSG_INFO,
2403 "Could not restore permanent MAC address");
2404 return -1;
2405 }
2406 wpa_s->mac_addr_changed = 0;
2407 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2408 wpa_msg(wpa_s, MSG_INFO,
2409 "Could not update MAC address information");
2410 return -1;
2411 }
2412 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2413 return 0;
2414}
2415
2416
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002417static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2418
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419/**
2420 * wpa_supplicant_associate - Request association
2421 * @wpa_s: Pointer to wpa_supplicant data
2422 * @bss: Scan results for the selected BSS, or %NULL if not available
2423 * @ssid: Configuration data for the selected network
2424 *
2425 * This function is used to request %wpa_supplicant to associate with a BSS.
2426 */
2427void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2428 struct wpa_bss *bss, struct wpa_ssid *ssid)
2429{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002430 struct wpa_connect_work *cwork;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002431 enum wpas_mac_addr_style rand_style;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002432
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002433 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002434 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002435
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002436 /*
2437 * If we are starting a new connection, any previously pending EAPOL
2438 * RX cannot be valid anymore.
2439 */
2440 wpabuf_free(wpa_s->pending_eapol_rx);
2441 wpa_s->pending_eapol_rx = NULL;
2442
Sunil Ravi77d572f2023-01-17 23:58:31 +00002443 if (ssid->mac_addr == WPAS_MAC_ADDR_STYLE_NOT_SET)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002444 rand_style = wpa_s->conf->mac_addr;
2445 else
2446 rand_style = ssid->mac_addr;
2447
Sunil Ravia04bd252022-05-02 22:54:18 -07002448 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002449 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002450 wmm_ac_clear_saved_tspecs(wpa_s);
2451 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002452 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002453#ifdef CONFIG_TESTING_OPTIONS
2454 wpa_s->testing_resend_assoc = 0;
2455#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002456
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002457 if (wpa_s->last_ssid == ssid) {
2458 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002459 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002460 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2461 wmm_ac_save_tspecs(wpa_s);
2462 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002463 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2464 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002465 }
Hai Shalomc3565922019-10-28 11:58:20 -07002466 } else {
2467#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002468 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002469#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002470 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002471#ifdef CONFIG_SAE
Sunil Ravi036cec52023-03-29 11:35:17 -07002472 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc1a21442022-02-04 13:43:00 -08002473#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002474
Sunil Ravi77d572f2023-01-17 23:58:31 +00002475 if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
2476 int status = wpas_update_random_addr(wpa_s, rand_style, ssid);
2477
2478 if (status < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002479 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002480 if (rand_style != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS &&
2481 status > 0) /* MAC changed */
2482 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2483 } else if (rand_style == WPAS_MAC_ADDR_STYLE_PERMANENT &&
2484 wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002485 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002486 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002487 }
2488 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489
2490#ifdef CONFIG_IBSS_RSN
2491 ibss_rsn_deinit(wpa_s->ibss_rsn);
2492 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002493#else /* CONFIG_IBSS_RSN */
2494 if (ssid->mode == WPAS_MODE_IBSS &&
2495 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2496 wpa_msg(wpa_s, MSG_INFO,
2497 "IBSS RSN not supported in the build");
2498 return;
2499 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500#endif /* CONFIG_IBSS_RSN */
2501
2502 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2503 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2504#ifdef CONFIG_AP
2505 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2506 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2507 "mode");
2508 return;
2509 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002510 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2511 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002512 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2513 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002514 return;
2515 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 wpa_s->current_bss = bss;
2517#else /* CONFIG_AP */
2518 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2519 "the build");
2520#endif /* CONFIG_AP */
2521 return;
2522 }
2523
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002524 if (ssid->mode == WPAS_MODE_MESH) {
2525#ifdef CONFIG_MESH
2526 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2527 wpa_msg(wpa_s, MSG_INFO,
2528 "Driver does not support mesh mode");
2529 return;
2530 }
2531 if (bss)
2532 ssid->frequency = bss->freq;
2533 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002534 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002535 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2536 return;
2537 }
2538 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002539#else /* CONFIG_MESH */
2540 wpa_msg(wpa_s, MSG_ERROR,
2541 "mesh mode support not included in the build");
2542#endif /* CONFIG_MESH */
2543 return;
2544 }
2545
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002546 /*
2547 * Set WPA state machine configuration to match the selected network now
2548 * so that the information is available before wpas_start_assoc_cb()
2549 * gets called. This is needed at least for RSN pre-authentication where
2550 * candidate APs are added to a list based on scan result processing
2551 * before completion of the first association.
2552 */
2553 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2554
2555#ifdef CONFIG_DPP
2556 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2557 return;
2558#endif /* CONFIG_DPP */
2559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560#ifdef CONFIG_TDLS
2561 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002562 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563#endif /* CONFIG_TDLS */
2564
Hai Shalomc3565922019-10-28 11:58:20 -07002565#ifdef CONFIG_MBO
2566 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2567#endif /* CONFIG_MBO */
2568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002570 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 sme_authenticate(wpa_s, bss, ssid);
2572 return;
2573 }
2574
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002575 if (wpa_s->connect_work) {
2576 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2577 return;
2578 }
2579
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002580 if (radio_work_pending(wpa_s, "connect")) {
2581 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2582 return;
2583 }
2584
Dmitry Shmidt29333592017-01-09 12:27:11 -08002585#ifdef CONFIG_SME
2586 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2587 /* Clear possibly set auth_alg, if any, from last attempt. */
2588 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2589 }
2590#endif /* CONFIG_SME */
2591
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002592 wpas_abort_ongoing_scan(wpa_s);
2593
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002594 cwork = os_zalloc(sizeof(*cwork));
2595 if (cwork == NULL)
2596 return;
2597
2598 cwork->bss = bss;
2599 cwork->ssid = ssid;
2600
2601 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2602 wpas_start_assoc_cb, cwork) < 0) {
2603 os_free(cwork);
2604 }
2605}
2606
2607
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002608static int bss_is_ibss(struct wpa_bss *bss)
2609{
2610 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2611 IEEE80211_CAP_IBSS;
2612}
2613
2614
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002615static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2616 const struct wpa_ssid *ssid)
2617{
2618 enum hostapd_hw_mode hw_mode;
2619 struct hostapd_hw_modes *mode = NULL;
2620 u8 channel;
2621 int i;
2622
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002623 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2624 if (hw_mode == NUM_HOSTAPD_MODES)
2625 return 0;
2626 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2627 if (wpa_s->hw.modes[i].mode == hw_mode) {
2628 mode = &wpa_s->hw.modes[i];
2629 break;
2630 }
2631 }
2632
2633 if (!mode)
2634 return 0;
2635
2636 return mode->vht_capab != 0;
2637}
2638
2639
Hai Shalomc1a21442022-02-04 13:43:00 -08002640static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2641{
2642 int i;
2643
2644 for (i = channel; i < channel + 16; i += 4) {
2645 struct hostapd_channel_data *chan;
2646
2647 chan = hw_get_channel_chan(mode, i, NULL);
2648 if (!chan ||
2649 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2650 return false;
2651 }
2652
2653 return true;
2654}
2655
2656
Sunil Ravi036cec52023-03-29 11:35:17 -07002657static struct wpa_bss * ibss_find_existing_bss(struct wpa_supplicant *wpa_s,
2658 const struct wpa_ssid *ssid)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002659{
Sunil Ravi036cec52023-03-29 11:35:17 -07002660 unsigned int j;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002661
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002662 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2663 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2664
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002665 if (!bss_is_ibss(bss))
2666 continue;
2667
2668 if (ssid->ssid_len == bss->ssid_len &&
Sunil Ravi036cec52023-03-29 11:35:17 -07002669 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0)
2670 return bss;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002671 }
Sunil Ravi036cec52023-03-29 11:35:17 -07002672 return NULL;
2673}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002674
Sunil Ravi036cec52023-03-29 11:35:17 -07002675
2676static bool ibss_mesh_can_use_ht(struct wpa_supplicant *wpa_s,
2677 const struct wpa_ssid *ssid,
2678 struct hostapd_hw_modes *mode)
2679{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002680 /* For IBSS check HT_IBSS flag */
2681 if (ssid->mode == WPAS_MODE_IBSS &&
2682 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
Sunil Ravi036cec52023-03-29 11:35:17 -07002683 return false;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002684
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002685 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2686 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2687 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2688 wpa_printf(MSG_DEBUG,
2689 "IBSS: WEP/TKIP detected, do not try to enable HT");
Sunil Ravi036cec52023-03-29 11:35:17 -07002690 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002691 }
2692
Sunil Ravi036cec52023-03-29 11:35:17 -07002693 if (!ht_supported(mode))
2694 return false;
Hai Shalomc1a21442022-02-04 13:43:00 -08002695
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002696#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002697 if (ssid->disable_ht)
2698 return false;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002699#endif /* CONFIG_HT_OVERRIDES */
2700
Sunil Ravi036cec52023-03-29 11:35:17 -07002701 return true;
2702}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002703
Sunil Ravi036cec52023-03-29 11:35:17 -07002704
2705static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
2706 const struct wpa_ssid *ssid,
2707 struct hostapd_hw_modes *mode)
2708{
2709 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2710 return false;
2711
2712 if (!drv_supports_vht(wpa_s, ssid))
2713 return false;
2714
2715 /* For IBSS check VHT_IBSS flag */
2716 if (ssid->mode == WPAS_MODE_IBSS &&
2717 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
2718 return false;
2719
2720 if (!vht_supported(mode))
2721 return false;
2722
2723#ifdef CONFIG_VHT_OVERRIDES
2724 if (ssid->disable_vht)
2725 return false;
2726#endif /* CONFIG_VHT_OVERRIDES */
2727
2728 return true;
2729}
2730
2731
2732static bool ibss_mesh_can_use_he(struct wpa_supplicant *wpa_s,
2733 const struct wpa_ssid *ssid,
2734 const struct hostapd_hw_modes *mode,
2735 int ieee80211_mode)
2736{
Hai Shalomfdcde762020-04-02 11:19:20 -07002737#ifdef CONFIG_HE_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002738 if (ssid->disable_he)
2739 return false;
Hai Shalomfdcde762020-04-02 11:19:20 -07002740#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002741
Sunil Ravi036cec52023-03-29 11:35:17 -07002742 switch (mode->mode) {
2743 case HOSTAPD_MODE_IEEE80211G:
2744 case HOSTAPD_MODE_IEEE80211B:
2745 case HOSTAPD_MODE_IEEE80211A:
2746 return mode->he_capab[ieee80211_mode].he_supported;
2747 default:
2748 return false;
2749 }
2750}
2751
2752
2753static bool ibss_mesh_can_use_eht(struct wpa_supplicant *wpa_s,
2754 const struct wpa_ssid *ssid,
2755 const struct hostapd_hw_modes *mode,
2756 int ieee80211_mode)
2757{
2758 if (ssid->disable_eht)
2759 return false;
2760
2761 switch(mode->mode) {
2762 case HOSTAPD_MODE_IEEE80211G:
2763 case HOSTAPD_MODE_IEEE80211B:
2764 case HOSTAPD_MODE_IEEE80211A:
2765 return mode->eht_capab[ieee80211_mode].eht_supported;
2766 default:
2767 return false;
2768 }
2769}
2770
2771
2772static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
2773 const struct wpa_ssid *ssid,
2774 struct hostapd_hw_modes *mode,
2775 struct hostapd_freq_params *freq,
2776 int obss_scan) {
2777 int chan_idx;
2778 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2779 int i, res;
2780 unsigned int j;
2781 static const int ht40plus[] = {
2782 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 165, 173,
2783 184, 192
2784 };
2785 int ht40 = -1;
2786
2787 if (!freq->ht_enabled)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002788 return;
2789
2790 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2791 pri_chan = &mode->channels[chan_idx];
Sunil Ravi036cec52023-03-29 11:35:17 -07002792 if (pri_chan->chan == freq->channel)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002793 break;
2794 pri_chan = NULL;
2795 }
2796 if (!pri_chan)
2797 return;
2798
2799 /* Check primary channel flags */
2800 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2801 return;
2802
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002803#ifdef CONFIG_HT_OVERRIDES
Sunil Ravi036cec52023-03-29 11:35:17 -07002804 if (ssid->disable_ht40)
2805 return;
2806#endif
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002807
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002808 /* Check/setup HT40+/HT40- */
2809 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
Sunil Ravi036cec52023-03-29 11:35:17 -07002810 if (ht40plus[j] == freq->channel) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002811 ht40 = 1;
2812 break;
2813 }
2814 }
2815
2816 /* Find secondary channel */
2817 for (i = 0; i < mode->num_channels; i++) {
2818 sec_chan = &mode->channels[i];
Sunil Ravi036cec52023-03-29 11:35:17 -07002819 if (sec_chan->chan == freq->channel + ht40 * 4)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002820 break;
2821 sec_chan = NULL;
2822 }
2823 if (!sec_chan)
2824 return;
2825
2826 /* Check secondary channel flags */
2827 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2828 return;
2829
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002830 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002831 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2832 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002833 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002834 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2835 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002836 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002837 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002838
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002839 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002840 struct wpa_scan_results *scan_res;
2841
2842 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2843 if (scan_res == NULL) {
2844 /* Back to HT20 */
2845 freq->sec_channel_offset = 0;
2846 return;
2847 }
2848
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002849 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002850 switch (res) {
2851 case 0:
2852 /* Back to HT20 */
2853 freq->sec_channel_offset = 0;
2854 break;
2855 case 1:
2856 /* Configuration allowed */
2857 break;
2858 case 2:
2859 /* Switch pri/sec channels */
2860 freq->freq = hw_get_freq(mode, sec_chan->chan);
2861 freq->sec_channel_offset = -freq->sec_channel_offset;
2862 freq->channel = sec_chan->chan;
2863 break;
2864 default:
2865 freq->sec_channel_offset = 0;
2866 break;
2867 }
2868
2869 wpa_scan_results_free(scan_res);
2870 }
2871
2872 wpa_printf(MSG_DEBUG,
2873 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2874 freq->channel, freq->sec_channel_offset);
Sunil Ravi036cec52023-03-29 11:35:17 -07002875}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002876
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002877
Sunil Ravi036cec52023-03-29 11:35:17 -07002878static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
2879 const struct wpa_ssid *ssid,
2880 struct hostapd_hw_modes *mode,
2881 struct hostapd_freq_params *freq,
2882 int ieee80211_mode, bool is_6ghz) {
2883 static const int bw80[] = {
2884 5180, 5260, 5500, 5580, 5660, 5745, 5825,
2885 5955, 6035, 6115, 6195, 6275, 6355, 6435,
2886 6515, 6595, 6675, 6755, 6835, 6915, 6995
2887 };
2888 static const int bw160[] = {
2889 5955, 6115, 6275, 6435, 6595, 6755, 6915
2890 };
2891 struct hostapd_freq_params vht_freq;
2892 int i;
2893 unsigned int j, k;
2894 int chwidth, seg0, seg1;
2895 u32 vht_caps = 0;
2896 u8 channel = freq->channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002897
Sunil Ravi036cec52023-03-29 11:35:17 -07002898 if (!freq->vht_enabled && !freq->he_enabled)
2899 return true;
Paul Stewart092955c2017-02-06 09:13:09 -08002900
Hai Shalomc1a21442022-02-04 13:43:00 -08002901 vht_freq = *freq;
2902
Sunil Ravi036cec52023-03-29 11:35:17 -07002903 chwidth = CONF_OPER_CHWIDTH_USE_HT;
2904 seg0 = freq->channel + 2 * freq->sec_channel_offset;
2905 seg1 = 0;
2906 if (freq->sec_channel_offset == 0) {
2907 seg0 = 0;
2908 /* Don't try 80 MHz if 40 MHz failed, except in 6 GHz */
2909 if (freq->ht_enabled && !is_6ghz)
2910 goto skip_80mhz;
2911 }
2912 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
2913 goto skip_80mhz;
Hai Shalomc3565922019-10-28 11:58:20 -07002914
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002915 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002916 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2917 if (freq->freq >= bw80[j] &&
2918 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002919 break;
2920 }
2921
Hai Shalomc1a21442022-02-04 13:43:00 -08002922 if (j == ARRAY_SIZE(bw80) ||
2923 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002924 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002925
Sunil Ravi036cec52023-03-29 11:35:17 -07002926 /* Use 40 MHz if channel not usable */
Hai Shalomc1a21442022-02-04 13:43:00 -08002927 if (!ibss_mesh_is_80mhz_avail(channel, mode))
Sunil Ravi036cec52023-03-29 11:35:17 -07002928 goto skip_80mhz;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002929
Sunil8cd6f4d2022-06-28 18:40:46 +00002930 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002931 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002932 seg1 = 0;
2933
Sunil Ravi036cec52023-03-29 11:35:17 -07002934 /* In 160 MHz, the initial four 20 MHz channels were validated
2935 * above. If 160 MHz is supported, check the remaining four 20 MHz
2936 * channels for the total of 160 MHz bandwidth for 6 GHz.
2937 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002938 if ((mode->he_capab[ieee80211_mode].phy_cap[
2939 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
Sunil Ravi036cec52023-03-29 11:35:17 -07002940 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
2941 ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
Hai Shalomc1a21442022-02-04 13:43:00 -08002942 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2943 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002944 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002945 seg0 = channel + 14;
2946 break;
2947 }
2948 }
2949 }
2950
Sunil8cd6f4d2022-06-28 18:40:46 +00002951 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002952 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002953 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002954 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002955 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002956 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002957
2958 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2959 NUM_HOSTAPD_MODES)
Sunil Ravi036cec52023-03-29 11:35:17 -07002960 break;
Hai Shalomc1a21442022-02-04 13:43:00 -08002961
2962 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002963 struct hostapd_channel_data *chan;
2964
2965 chan = hw_get_channel_chan(mode, i, NULL);
2966 if (!chan)
2967 continue;
2968
2969 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2970 HOSTAPD_CHAN_NO_IR |
2971 HOSTAPD_CHAN_RADAR))
2972 continue;
2973
2974 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002975 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002976 if (!is_6ghz)
2977 vht_caps |=
2978 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2979 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002980 }
2981
Sunil8cd6f4d2022-06-28 18:40:46 +00002982 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002983 break;
2984 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002985 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002986 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002987 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002988 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2989 seg0 = 50;
2990 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002991 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002992 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2993 seg0 = 114;
2994 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002995 }
2996
Sunil Ravi036cec52023-03-29 11:35:17 -07002997skip_80mhz:
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002998 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002999 freq->channel, ssid->enable_edmg,
3000 ssid->edmg_channel, freq->ht_enabled,
Sunil Ravi036cec52023-03-29 11:35:17 -07003001 freq->vht_enabled, freq->he_enabled,
3002 freq->eht_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003003 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07003004 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07003005 &mode->he_capab[ieee80211_mode],
Sunil Ravi036cec52023-03-29 11:35:17 -07003006 &mode->eht_capab[ieee80211_mode]) != 0)
3007 return false;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003008
3009 *freq = vht_freq;
3010
3011 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
3012 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Sunil Ravi036cec52023-03-29 11:35:17 -07003013 return true;
3014}
3015
3016
3017void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
3018 const struct wpa_ssid *ssid,
3019 struct hostapd_freq_params *freq)
3020{
3021 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
3022 enum hostapd_hw_mode hw_mode;
3023 struct hostapd_hw_modes *mode = NULL;
3024 int i, obss_scan = 1;
3025 u8 channel;
3026 bool is_6ghz;
3027
3028 freq->freq = ssid->frequency;
3029
3030 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
3031 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
3032
3033 if (bss) {
3034 wpa_printf(MSG_DEBUG,
3035 "IBSS already found in scan results, adjust control freq: %d",
3036 bss->freq);
3037 freq->freq = bss->freq;
3038 obss_scan = 0;
3039 }
3040 }
3041
3042 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
3043 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
3044 if (wpa_s->hw.modes[i].mode == hw_mode &&
3045 hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
3046 NULL) != NULL) {
3047 mode = &wpa_s->hw.modes[i];
3048 break;
3049 }
3050 }
3051
3052 if (!mode)
3053 return;
3054
3055 is_6ghz = is_6ghz_freq(freq->freq);
3056
3057 freq->ht_enabled = 0;
3058 freq->vht_enabled = 0;
3059 freq->he_enabled = 0;
3060 freq->eht_enabled = 0;
3061
3062 if (!is_6ghz)
3063 freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
3064 if (freq->ht_enabled)
3065 freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
3066 if (freq->vht_enabled || is_6ghz)
3067 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
3068 ieee80211_mode);
3069 freq->channel = channel;
3070 /* Setup higher BW only for 5 GHz */
3071 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
3072 ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
3073 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
3074 ieee80211_mode, is_6ghz))
3075 freq->he_enabled = freq->vht_enabled = false;
3076 }
3077
3078 if (freq->he_enabled)
3079 freq->eht_enabled = ibss_mesh_can_use_eht(wpa_s, ssid, mode,
3080 ieee80211_mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003081}
3082
3083
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084#ifdef CONFIG_FILS
3085static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
3086 size_t ie_buf_len)
3087{
3088 struct fils_hlp_req *req;
3089 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
3090 const u8 *pos;
3091 u8 *buf = ie_buf;
3092
3093 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3094 list) {
3095 rem_len = ie_buf_len - ie_len;
3096 pos = wpabuf_head(req->pkt);
3097 hdr_len = 1 + 2 * ETH_ALEN + 6;
3098 hlp_len = wpabuf_len(req->pkt);
3099
3100 if (rem_len < 2 + hdr_len + hlp_len) {
3101 wpa_printf(MSG_ERROR,
3102 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
3103 (unsigned long) rem_len,
3104 (unsigned long) (2 + hdr_len + hlp_len));
3105 break;
3106 }
3107
3108 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
3109 /* Element ID */
3110 *buf++ = WLAN_EID_EXTENSION;
3111 /* Length */
3112 *buf++ = len;
3113 /* Element ID Extension */
3114 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
3115 /* Destination MAC address */
3116 os_memcpy(buf, req->dst, ETH_ALEN);
3117 buf += ETH_ALEN;
3118 /* Source MAC address */
3119 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
3120 buf += ETH_ALEN;
3121 /* LLC/SNAP Header */
3122 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
3123 buf += 6;
3124 /* HLP Packet */
3125 os_memcpy(buf, pos, len - hdr_len);
3126 buf += len - hdr_len;
3127 pos += len - hdr_len;
3128
3129 hlp_len -= len - hdr_len;
3130 ie_len += 2 + len;
3131 rem_len -= 2 + len;
3132
3133 while (hlp_len) {
3134 len = (hlp_len > 255) ? 255 : hlp_len;
3135 if (rem_len < 2 + len)
3136 break;
3137 *buf++ = WLAN_EID_FRAGMENT;
3138 *buf++ = len;
3139 os_memcpy(buf, pos, len);
3140 buf += len;
3141 pos += len;
3142
3143 hlp_len -= len;
3144 ie_len += 2 + len;
3145 rem_len -= 2 + len;
3146 }
3147 }
3148
3149 return ie_len;
3150}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003151
3152
3153int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3154{
3155 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3156 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3157 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3158 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3159}
3160
3161
3162int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3163{
3164#ifdef CONFIG_FILS_SK_PFS
3165 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3166 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3167#else /* CONFIG_FILS_SK_PFS */
3168 return 0;
3169#endif /* CONFIG_FILS_SK_PFS */
3170}
3171
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003172#endif /* CONFIG_FILS */
3173
3174
Hai Shalomc1a21442022-02-04 13:43:00 -08003175static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3176 struct wpa_bss *bss,
3177 u8 *wpa_ie, size_t wpa_ie_len,
3178 size_t max_wpa_ie_len)
3179{
3180 struct wpabuf *wfa_ie = NULL;
3181 u8 wfa_capa[1];
3182 size_t wfa_ie_len, buf_len;
3183
3184 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3185 if (wpa_s->enable_dscp_policy_capa)
3186 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3187
3188 if (!wfa_capa[0])
3189 return wpa_ie_len;
3190
3191 /* Wi-Fi Alliance element */
3192 buf_len = 1 + /* Element ID */
3193 1 + /* Length */
3194 3 + /* OUI */
3195 1 + /* OUI Type */
3196 1 + /* Capabilities Length */
3197 sizeof(wfa_capa); /* Capabilities */
3198 wfa_ie = wpabuf_alloc(buf_len);
3199 if (!wfa_ie)
3200 return wpa_ie_len;
3201
3202 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3203 wpabuf_put_u8(wfa_ie, buf_len - 2);
3204 wpabuf_put_be24(wfa_ie, OUI_WFA);
3205 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3206 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3207 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3208
3209 wfa_ie_len = wpabuf_len(wfa_ie);
3210 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3211 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3212 wfa_ie);
3213 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3214 wfa_ie_len);
3215 wpa_ie_len += wfa_ie_len;
3216 }
3217
3218 wpabuf_free(wfa_ie);
3219 return wpa_ie_len;
3220}
3221
3222
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003223static u8 * wpas_populate_assoc_ies(
3224 struct wpa_supplicant *wpa_s,
3225 struct wpa_bss *bss, struct wpa_ssid *ssid,
3226 struct wpa_driver_associate_params *params,
3227 enum wpa_drv_update_connect_params_mask *mask)
3228{
3229 u8 *wpa_ie;
3230 size_t max_wpa_ie_len = 500;
3231 size_t wpa_ie_len;
3232 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003233#ifdef CONFIG_MBO
3234 const u8 *mbo_ie;
3235#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303236#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3237 int pmksa_cached = 0;
3238#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003239#ifdef CONFIG_FILS
3240 const u8 *realm, *username, *rrk;
3241 size_t realm_len, username_len, rrk_len;
3242 u16 next_seq_num;
3243 struct fils_hlp_req *req;
3244
3245 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3246 list) {
3247 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3248 2 + 2 * wpabuf_len(req->pkt) / 255;
3249 }
3250#endif /* CONFIG_FILS */
3251
3252 wpa_ie = os_malloc(max_wpa_ie_len);
3253 if (!wpa_ie) {
3254 wpa_printf(MSG_ERROR,
3255 "Failed to allocate connect IE buffer for %lu bytes",
3256 (unsigned long) max_wpa_ie_len);
3257 return NULL;
3258 }
3259
3260 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3261 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3262 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3263 int try_opportunistic;
3264 const u8 *cache_id = NULL;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003265 const u8 *addr = bss->bssid;
3266
Sunil Ravi036cec52023-03-29 11:35:17 -07003267 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3268 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
3269 !is_zero_ether_addr(bss->mld_addr))
3270 addr = bss->mld_addr;
3271
3272 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3273 wpa_s->valid_links)
Sunil Ravi77d572f2023-01-17 23:58:31 +00003274 addr = wpa_s->ap_mld_addr;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003275
3276 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3277 wpa_s->conf->okc :
3278 ssid->proactive_key_caching) &&
3279 (ssid->proto & WPA_PROTO_RSN);
3280#ifdef CONFIG_FILS
3281 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3282 cache_id = wpa_bss_get_fils_cache_id(bss);
3283#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003284 if (pmksa_cache_set_current(wpa_s->wpa, NULL, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003285 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003286 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303288#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3289 pmksa_cached = 1;
3290#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003291 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003292 wpa_ie_len = max_wpa_ie_len;
3293 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003294 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003295 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3296 "key management and encryption suites");
3297 os_free(wpa_ie);
3298 return NULL;
3299 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003300#ifdef CONFIG_HS20
3301 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3302 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3303 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3304 wpa_ie_len = max_wpa_ie_len;
3305 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003306 wpa_ie, &wpa_ie_len, false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003307 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3308 "key management and encryption suites");
3309 os_free(wpa_ie);
3310 return NULL;
3311 }
3312#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3314 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3315 /*
3316 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3317 * use non-WPA since the scan results did not indicate that the
3318 * AP is using WPA or WPA2.
3319 */
3320 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3321 wpa_ie_len = 0;
3322 wpa_s->wpa_proto = 0;
3323 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3324 wpa_ie_len = max_wpa_ie_len;
3325 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003326 wpa_ie, &wpa_ie_len, false)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003327 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3328 "key management and encryption suites (no "
3329 "scan results)");
3330 os_free(wpa_ie);
3331 return NULL;
3332 }
3333#ifdef CONFIG_WPS
3334 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3335 struct wpabuf *wps_ie;
3336 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3337 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3338 wpa_ie_len = wpabuf_len(wps_ie);
3339 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3340 } else
3341 wpa_ie_len = 0;
3342 wpabuf_free(wps_ie);
3343 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3344 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3345 params->wps = WPS_MODE_PRIVACY;
3346 else
3347 params->wps = WPS_MODE_OPEN;
3348 wpa_s->wpa_proto = 0;
3349#endif /* CONFIG_WPS */
3350 } else {
3351 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3352 wpa_ie_len = 0;
3353 wpa_s->wpa_proto = 0;
3354 }
3355
3356#ifdef IEEE8021X_EAPOL
3357 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3358 if (ssid->leap) {
3359 if (ssid->non_leap == 0)
3360 algs = WPA_AUTH_ALG_LEAP;
3361 else
3362 algs |= WPA_AUTH_ALG_LEAP;
3363 }
3364 }
3365
3366#ifdef CONFIG_FILS
3367 /* Clear FILS association */
3368 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3369
3370 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3371 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3372 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3373 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003374 &next_seq_num, &rrk, &rrk_len) == 0 &&
3375 (!wpa_s->last_con_fail_realm ||
3376 wpa_s->last_con_fail_realm_len != realm_len ||
3377 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003378 algs = WPA_AUTH_ALG_FILS;
3379 params->fils_erp_username = username;
3380 params->fils_erp_username_len = username_len;
3381 params->fils_erp_realm = realm;
3382 params->fils_erp_realm_len = realm_len;
3383 params->fils_erp_next_seq_num = next_seq_num;
3384 params->fils_erp_rrk = rrk;
3385 params->fils_erp_rrk_len = rrk_len;
3386
3387 if (mask)
3388 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303389 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3390 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3391 pmksa_cached) {
3392 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003393 }
3394#endif /* CONFIG_FILS */
3395#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003396#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003397 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003398 algs = WPA_AUTH_ALG_SAE;
3399#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003400
3401 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3402 if (ssid->auth_alg) {
3403 algs = ssid->auth_alg;
3404 wpa_dbg(wpa_s, MSG_DEBUG,
3405 "Overriding auth_alg selection: 0x%x", algs);
3406 }
3407
Hai Shalom5f92bc92019-04-18 11:54:11 -07003408#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303409 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003410 wpa_dbg(wpa_s, MSG_DEBUG,
3411 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3412 algs = WPA_AUTH_ALG_OPEN;
3413 }
3414#endif /* CONFIG_SAE */
3415
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003416#ifdef CONFIG_P2P
3417 if (wpa_s->global->p2p) {
3418 u8 *pos;
3419 size_t len;
3420 int res;
3421 pos = wpa_ie + wpa_ie_len;
3422 len = max_wpa_ie_len - wpa_ie_len;
3423 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3424 ssid->p2p_group);
3425 if (res >= 0)
3426 wpa_ie_len += res;
3427 }
3428
3429 wpa_s->cross_connect_disallowed = 0;
3430 if (bss) {
3431 struct wpabuf *p2p;
3432 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3433 if (p2p) {
3434 wpa_s->cross_connect_disallowed =
3435 p2p_get_cross_connect_disallowed(p2p);
3436 wpabuf_free(p2p);
3437 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3438 "connection",
3439 wpa_s->cross_connect_disallowed ?
3440 "disallows" : "allows");
3441 }
3442 }
3443
3444 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3445#endif /* CONFIG_P2P */
3446
3447 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003448 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003449 wpa_ie + wpa_ie_len,
3450 max_wpa_ie_len -
3451 wpa_ie_len);
3452 }
3453
3454 /*
3455 * Workaround: Add Extended Capabilities element only if the AP
3456 * included this element in Beacon/Probe Response frames. Some older
3457 * APs seem to have interoperability issues if this element is
3458 * included, so while the standard may require us to include the
3459 * element in all cases, it is justifiable to skip it to avoid
3460 * interoperability issues.
3461 */
3462 if (ssid->p2p_group)
3463 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3464 else
3465 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3466
3467 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3468 u8 ext_capab[18];
3469 int ext_capab_len;
3470 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3471 sizeof(ext_capab));
3472 if (ext_capab_len > 0 &&
3473 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3474 u8 *pos = wpa_ie;
3475 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3476 pos += 2 + pos[1];
3477 os_memmove(pos + ext_capab_len, pos,
3478 wpa_ie_len - (pos - wpa_ie));
3479 wpa_ie_len += ext_capab_len;
3480 os_memcpy(pos, ext_capab, ext_capab_len);
3481 }
3482 }
3483
3484#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003485 if (is_hs20_network(wpa_s, ssid, bss)
3486#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3487 && is_hs20_config(wpa_s)
3488#endif /* ANDROID */
3489 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003490 struct wpabuf *hs20;
3491
Roshan Pius3a1667e2018-07-03 15:17:14 -07003492 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003493 if (hs20) {
3494 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3495 size_t len;
3496
Hai Shalom74f70d42019-02-11 14:42:39 -08003497 wpas_hs20_add_indication(hs20, pps_mo_id,
3498 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003499 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003500 len = max_wpa_ie_len - wpa_ie_len;
3501 if (wpabuf_len(hs20) <= len) {
3502 os_memcpy(wpa_ie + wpa_ie_len,
3503 wpabuf_head(hs20), wpabuf_len(hs20));
3504 wpa_ie_len += wpabuf_len(hs20);
3505 }
3506 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003507 }
3508 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003509 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003510#endif /* CONFIG_HS20 */
3511
3512 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3513 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3514 size_t len;
3515
3516 len = max_wpa_ie_len - wpa_ie_len;
3517 if (wpabuf_len(buf) <= len) {
3518 os_memcpy(wpa_ie + wpa_ie_len,
3519 wpabuf_head(buf), wpabuf_len(buf));
3520 wpa_ie_len += wpabuf_len(buf);
3521 }
3522 }
3523
3524#ifdef CONFIG_FST
3525 if (wpa_s->fst_ies) {
3526 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3527
3528 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3529 os_memcpy(wpa_ie + wpa_ie_len,
3530 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3531 wpa_ie_len += fst_ies_len;
3532 }
3533 }
3534#endif /* CONFIG_FST */
3535
3536#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003537 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003538 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003539 int len;
3540
3541 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003542 max_wpa_ie_len - wpa_ie_len,
3543 !!mbo_attr_from_mbo_ie(mbo_ie,
3544 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003545 if (len >= 0)
3546 wpa_ie_len += len;
3547 }
3548#endif /* CONFIG_MBO */
3549
3550#ifdef CONFIG_FILS
3551 if (algs == WPA_AUTH_ALG_FILS) {
3552 size_t len;
3553
3554 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3555 max_wpa_ie_len - wpa_ie_len);
3556 wpa_ie_len += len;
3557 }
3558#endif /* CONFIG_FILS */
3559
3560#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003561#ifdef CONFIG_TESTING_OPTIONS
3562 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3563 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3564 } else
3565#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003566 if (algs == WPA_AUTH_ALG_OPEN &&
3567 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3568 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003569 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003570
Roshan Pius3a1667e2018-07-03 15:17:14 -07003571 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003572 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003573 } else if (wpa_s->assoc_status_code ==
3574 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003575 if (wpa_s->last_owe_group == 19)
3576 group = 20;
3577 else if (wpa_s->last_owe_group == 20)
3578 group = 21;
3579 else
3580 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003581 } else {
3582 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003583 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003584
Roshan Pius3a1667e2018-07-03 15:17:14 -07003585 wpa_s->last_owe_group = group;
3586 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003587 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3588 if (owe_ie &&
3589 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3590 os_memcpy(wpa_ie + wpa_ie_len,
3591 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3592 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003593 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003594 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003595 }
3596#endif /* CONFIG_OWE */
3597
Hai Shalom021b0b52019-04-10 11:17:58 -07003598#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003599 if (DPP_VERSION > 1 &&
3600 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003601 ssid->dpp_netaccesskey &&
3602 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003603 struct rsn_pmksa_cache_entry *pmksa;
3604
3605 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3606 if (!pmksa || !pmksa->dpp_pfs)
3607 goto pfs_fail;
3608
Hai Shalom021b0b52019-04-10 11:17:58 -07003609 dpp_pfs_free(wpa_s->dpp_pfs);
3610 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3611 ssid->dpp_netaccesskey_len);
3612 if (!wpa_s->dpp_pfs) {
3613 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3614 /* Try to continue without PFS */
3615 goto pfs_fail;
3616 }
3617 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3618 max_wpa_ie_len - wpa_ie_len) {
3619 os_memcpy(wpa_ie + wpa_ie_len,
3620 wpabuf_head(wpa_s->dpp_pfs->ie),
3621 wpabuf_len(wpa_s->dpp_pfs->ie));
3622 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3623 }
3624 }
3625pfs_fail:
3626#endif /* CONFIG_DPP2 */
3627
Roshan Pius3a1667e2018-07-03 15:17:14 -07003628#ifdef CONFIG_IEEE80211R
3629 /*
3630 * Add MDIE under these conditions: the network profile allows FT,
3631 * the AP supports FT, and the mobility domain ID matches.
3632 */
3633 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3634 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3635
3636 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3637 size_t len = 0;
3638 const u8 *md = mdie + 2;
3639 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3640
3641 if (os_memcmp(md, wpa_md,
3642 MOBILITY_DOMAIN_ID_LEN) == 0) {
3643 /* Add mobility domain IE */
3644 len = wpa_ft_add_mdie(
3645 wpa_s->wpa, wpa_ie + wpa_ie_len,
3646 max_wpa_ie_len - wpa_ie_len, mdie);
3647 wpa_ie_len += len;
3648 }
3649#ifdef CONFIG_SME
3650 if (len > 0 && wpa_s->sme.ft_used &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00003651 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003652 wpa_dbg(wpa_s, MSG_DEBUG,
3653 "SME: Trying to use FT over-the-air");
3654 algs |= WPA_AUTH_ALG_FT;
3655 }
3656#endif /* CONFIG_SME */
3657 }
3658 }
3659#endif /* CONFIG_IEEE80211R */
3660
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003661#ifdef CONFIG_TESTING_OPTIONS
3662 if (wpa_s->rsnxe_override_assoc &&
3663 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3664 max_wpa_ie_len - wpa_ie_len) {
3665 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3666 os_memcpy(wpa_ie + wpa_ie_len,
3667 wpabuf_head(wpa_s->rsnxe_override_assoc),
3668 wpabuf_len(wpa_s->rsnxe_override_assoc));
3669 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3670 } else
3671#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003672 if (wpa_s->rsnxe_len > 0 &&
3673 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3674 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3675 wpa_ie_len += wpa_s->rsnxe_len;
3676 }
3677
Hai Shalomc1a21442022-02-04 13:43:00 -08003678#ifdef CONFIG_TESTING_OPTIONS
3679 if (wpa_s->disable_mscs_support)
3680 goto mscs_end;
3681#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003682 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3683 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003684 struct wpabuf *mscs_ie;
3685 size_t mscs_ie_len, buf_len;
3686
Hai Shalom899fcc72020-10-19 14:38:18 -07003687 buf_len = 3 + /* MSCS descriptor IE header */
3688 1 + /* Request type */
3689 2 + /* User priority control */
3690 4 + /* Stream timeout */
3691 3 + /* TCLAS Mask IE header */
3692 wpa_s->robust_av.frame_classifier_len;
3693 mscs_ie = wpabuf_alloc(buf_len);
3694 if (!mscs_ie) {
3695 wpa_printf(MSG_INFO,
3696 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003697 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003698 }
3699
3700 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3701 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3702 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3703 mscs_ie_len = wpabuf_len(mscs_ie);
3704 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3705 mscs_ie_len);
3706 wpa_ie_len += mscs_ie_len;
3707 }
3708
3709 wpabuf_free(mscs_ie);
3710 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003711mscs_end:
3712
3713 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3714 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003715
Hai Shalom74f70d42019-02-11 14:42:39 -08003716 if (ssid->multi_ap_backhaul_sta) {
3717 size_t multi_ap_ie_len;
3718
3719 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3720 max_wpa_ie_len - wpa_ie_len,
3721 MULTI_AP_BACKHAUL_STA);
3722 if (multi_ap_ie_len == 0) {
3723 wpa_printf(MSG_ERROR,
3724 "Multi-AP: Failed to build Multi-AP IE");
3725 os_free(wpa_ie);
3726 return NULL;
3727 }
3728 wpa_ie_len += multi_ap_ie_len;
3729 }
3730
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003731 params->wpa_ie = wpa_ie;
3732 params->wpa_ie_len = wpa_ie_len;
3733 params->auth_alg = algs;
3734 if (mask)
3735 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3736
3737 return wpa_ie;
3738}
3739
3740
Hai Shalomc3565922019-10-28 11:58:20 -07003741#ifdef CONFIG_OWE
3742static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3743{
3744 struct wpa_driver_associate_params params;
3745 u8 *wpa_ie;
3746
3747 os_memset(&params, 0, sizeof(params));
3748 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3749 wpa_s->current_ssid, &params, NULL);
3750 if (!wpa_ie)
3751 return;
3752
3753 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3754 os_free(wpa_ie);
3755}
3756#endif /* CONFIG_OWE */
3757
3758
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003759#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3760static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3761{
3762 struct wpa_driver_associate_params params;
3763 enum wpa_drv_update_connect_params_mask mask = 0;
3764 u8 *wpa_ie;
3765
3766 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3767 return; /* nothing to do */
3768
3769 os_memset(&params, 0, sizeof(params));
3770 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3771 wpa_s->current_ssid, &params, &mask);
3772 if (!wpa_ie)
3773 return;
3774
Hai Shalomc1a21442022-02-04 13:43:00 -08003775 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3776 wpa_s->auth_alg = params.auth_alg;
3777 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003778 }
3779
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003780 os_free(wpa_ie);
3781}
3782#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3783
3784
Hai Shalomc3565922019-10-28 11:58:20 -07003785static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3786{
3787 if (!edmg_ie || edmg_ie[1] < 6)
3788 return 0;
3789 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3790}
3791
3792
3793static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3794{
3795 if (!edmg_ie || edmg_ie[1] < 6)
3796 return 0;
3797 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3798}
3799
3800
3801/* Returns the intersection of two EDMG configurations.
3802 * Note: The current implementation is limited to CB2 only (CB1 included),
3803 * i.e., the implementation supports up to 2 contiguous channels.
3804 * For supporting non-contiguous (aggregated) channels and for supporting
3805 * CB3 and above, this function will need to be extended.
3806 */
3807static struct ieee80211_edmg_config
3808get_edmg_intersection(struct ieee80211_edmg_config a,
3809 struct ieee80211_edmg_config b,
3810 u8 primary_channel)
3811{
3812 struct ieee80211_edmg_config result;
3813 int i, contiguous = 0;
3814 int max_contiguous = 0;
3815
3816 result.channels = b.channels & a.channels;
3817 if (!result.channels) {
3818 wpa_printf(MSG_DEBUG,
3819 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3820 a.channels, b.channels);
3821 goto fail;
3822 }
3823
3824 if (!(result.channels & BIT(primary_channel - 1))) {
3825 wpa_printf(MSG_DEBUG,
3826 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3827 primary_channel, result.channels);
3828 goto fail;
3829 }
3830
3831 /* Find max contiguous channels */
3832 for (i = 0; i < 6; i++) {
3833 if (result.channels & BIT(i))
3834 contiguous++;
3835 else
3836 contiguous = 0;
3837
3838 if (contiguous > max_contiguous)
3839 max_contiguous = contiguous;
3840 }
3841
3842 /* Assuming AP and STA supports ONLY contiguous channels,
3843 * bw configuration can have value between 4-7.
3844 */
3845 if ((b.bw_config < a.bw_config))
3846 result.bw_config = b.bw_config;
3847 else
3848 result.bw_config = a.bw_config;
3849
3850 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3851 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3852 wpa_printf(MSG_DEBUG,
3853 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3854 max_contiguous);
3855 goto fail;
3856 }
3857
3858 return result;
3859
3860fail:
3861 result.channels = 0;
3862 result.bw_config = 0;
3863 return result;
3864}
3865
3866
3867static struct ieee80211_edmg_config
3868get_supported_edmg(struct wpa_supplicant *wpa_s,
3869 struct hostapd_freq_params *freq,
3870 struct ieee80211_edmg_config request_edmg)
3871{
3872 enum hostapd_hw_mode hw_mode;
3873 struct hostapd_hw_modes *mode = NULL;
3874 u8 primary_channel;
3875
3876 if (!wpa_s->hw.modes)
3877 goto fail;
3878
3879 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3880 if (hw_mode == NUM_HOSTAPD_MODES)
3881 goto fail;
3882
Hai Shalom60840252021-02-19 19:02:11 -08003883 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003884 if (!mode)
3885 goto fail;
3886
3887 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3888
3889fail:
3890 request_edmg.channels = 0;
3891 request_edmg.bw_config = 0;
3892 return request_edmg;
3893}
3894
3895
Hai Shalom021b0b52019-04-10 11:17:58 -07003896#ifdef CONFIG_MBO
3897void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3898{
3899 struct wpa_driver_associate_params params;
3900 u8 *wpa_ie;
3901
3902 /*
3903 * Update MBO connect params only in case of change of MBO attributes
3904 * when connected, if the AP support MBO.
3905 */
3906
3907 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3908 !wpa_s->current_bss ||
3909 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3910 return;
3911
3912 os_memset(&params, 0, sizeof(params));
3913 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3914 wpa_s->current_ssid, &params, NULL);
3915 if (!wpa_ie)
3916 return;
3917
3918 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3919 os_free(wpa_ie);
3920}
3921#endif /* CONFIG_MBO */
3922
3923
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003924static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3925{
3926 struct wpa_connect_work *cwork = work->ctx;
3927 struct wpa_bss *bss = cwork->bss;
3928 struct wpa_ssid *ssid = cwork->ssid;
3929 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003930 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003931 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003932 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003933 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003934 struct wpa_driver_associate_params params;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003935 u8 psk[PMK_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003936#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003937 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003938#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003939 int assoc_failed = 0;
3940 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003941 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003942#ifdef CONFIG_HT_OVERRIDES
3943 struct ieee80211_ht_capabilities htcaps;
3944 struct ieee80211_ht_capabilities htcaps_mask;
3945#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003946#ifdef CONFIG_VHT_OVERRIDES
3947 struct ieee80211_vht_capabilities vhtcaps;
3948 struct ieee80211_vht_capabilities vhtcaps_mask;
3949#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003950
Hai Shalomc1a21442022-02-04 13:43:00 -08003951 wpa_s->roam_in_progress = false;
3952#ifdef CONFIG_WNM
3953 wpa_s->bss_trans_mgmt_in_progress = false;
3954#endif /* CONFIG_WNM */
3955
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003956 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003957 if (work->started) {
3958 wpa_s->connect_work = NULL;
3959
3960 /* cancel possible auth. timeout */
3961 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3962 NULL);
3963 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003964 wpas_connect_work_free(cwork);
3965 return;
3966 }
3967
3968 wpa_s->connect_work = work;
3969
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003970 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3971 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003972 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3973 wpas_connect_work_done(wpa_s);
3974 return;
3975 }
3976
Dmitry Shmidte4663042016-04-04 10:07:49 -07003977 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978 os_memset(&params, 0, sizeof(params));
3979 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003980 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003981
3982 /* Starting new association, so clear the possibly used WPA IE from the
3983 * previous association. */
3984 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3985 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3986 wpa_s->rsnxe_len = 0;
3987 wpa_s->mscs_setup_done = false;
3988
3989 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3990 if (!wpa_ie) {
3991 wpas_connect_work_done(wpa_s);
3992 return;
3993 }
3994
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003995 if (bss &&
3996 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997#ifdef CONFIG_IEEE80211R
3998 const u8 *ie, *md = NULL;
3999#endif /* CONFIG_IEEE80211R */
4000 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
4001 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
4002 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
4003 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
4004 os_memset(wpa_s->bssid, 0, ETH_ALEN);
4005 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4006 if (bssid_changed)
4007 wpas_notify_bssid_changed(wpa_s);
4008#ifdef CONFIG_IEEE80211R
4009 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
4010 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
4011 md = ie + 2;
4012 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
4013 if (md) {
4014 /* Prepare for the next transition */
4015 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
4016 }
4017#endif /* CONFIG_IEEE80211R */
4018#ifdef CONFIG_WPS
4019 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
4020 wpa_s->conf->ap_scan == 2 &&
4021 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
4022 /* Use ap_scan==1 style network selection to find the network
4023 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004024 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004025 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004026 wpa_s->reassociate = 1;
4027 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08004028 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004029 return;
4030#endif /* CONFIG_WPS */
4031 } else {
4032 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
4033 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004034 if (bss)
4035 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
4036 else
4037 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004038 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004039 if (!wpa_s->pno)
4040 wpa_supplicant_cancel_sched_scan(wpa_s);
4041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004042 wpa_supplicant_cancel_scan(wpa_s);
4043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
4045 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004046 cipher_pairwise = wpa_s->pairwise_cipher;
4047 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004048 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004049 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
4050 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4051 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
4052 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004053#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004054 if (wpa_set_wep_keys(wpa_s, ssid)) {
4055 use_crypt = 1;
4056 wep_keys_set = 1;
4057 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004058#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004059 }
4060 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
4061 use_crypt = 0;
4062
4063#ifdef IEEE8021X_EAPOL
4064 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4065 if ((ssid->eapol_flags &
4066 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4067 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
4068 !wep_keys_set) {
4069 use_crypt = 0;
4070 } else {
4071 /* Assume that dynamic WEP-104 keys will be used and
4072 * set cipher suites in order for drivers to expect
4073 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004074 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 }
4076 }
4077#endif /* IEEE8021X_EAPOL */
4078
4079 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4080 /* Set the key before (and later after) association */
4081 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4082 }
4083
Sunil8cd6f4d2022-06-28 18:40:46 +00004084 /* Set current_ssid before changing state to ASSOCIATING, so that the
4085 * selected SSID is available to wpas_notify_state_changed(). */
4086 old_ssid = wpa_s->current_ssid;
4087 wpa_s->current_ssid = ssid;
4088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
4090 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004091 params.ssid = bss->ssid;
4092 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004093 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
4094 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004095 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
4096 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004097 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07004098 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004099 ssid->bssid_set,
4100 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004101 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004102 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004103 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004104 params.bssid_hint = bss->bssid;
4105 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004106 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004108 if (ssid->bssid_hint_set)
4109 params.bssid_hint = ssid->bssid_hint;
4110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111 params.ssid = ssid->ssid;
4112 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004113 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004115
4116 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
4117 wpa_s->conf->ap_scan == 2) {
4118 params.bssid = ssid->bssid;
4119 params.fixed_bssid = 1;
4120 }
4121
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004122 /* Initial frequency for IBSS/mesh */
4123 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004124 ssid->frequency > 0 && params.freq.freq == 0)
4125 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004126
4127 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004128 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004129 if (ssid->beacon_int)
4130 params.beacon_int = ssid->beacon_int;
4131 else
4132 params.beacon_int = wpa_s->conf->beacon_int;
4133 }
4134
Hai Shalomc3565922019-10-28 11:58:20 -07004135 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08004136 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
4137 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07004138 else
4139 edmg_ie_oper = NULL;
4140
4141 if (edmg_ie_oper) {
4142 params.freq.edmg.channels =
4143 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
4144 params.freq.edmg.bw_config =
4145 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
4146 wpa_printf(MSG_DEBUG,
4147 "AP supports EDMG channels 0x%x, bw_config %d",
4148 params.freq.edmg.channels,
4149 params.freq.edmg.bw_config);
4150
4151 /* User may ask for specific EDMG channel for EDMG connection
4152 * (must be supported by AP)
4153 */
4154 if (ssid->edmg_channel) {
4155 struct ieee80211_edmg_config configured_edmg;
4156 enum hostapd_hw_mode hw_mode;
4157 u8 primary_channel;
4158
4159 hw_mode = ieee80211_freq_to_chan(bss->freq,
4160 &primary_channel);
4161 if (hw_mode == NUM_HOSTAPD_MODES)
4162 goto edmg_fail;
4163
4164 hostapd_encode_edmg_chan(ssid->enable_edmg,
4165 ssid->edmg_channel,
4166 primary_channel,
4167 &configured_edmg);
4168
4169 if (ieee802_edmg_is_allowed(params.freq.edmg,
4170 configured_edmg)) {
4171 params.freq.edmg = configured_edmg;
4172 wpa_printf(MSG_DEBUG,
4173 "Use EDMG channel %d for connection",
4174 ssid->edmg_channel);
4175 } else {
4176 edmg_fail:
4177 params.freq.edmg.channels = 0;
4178 params.freq.edmg.bw_config = 0;
4179 wpa_printf(MSG_WARNING,
4180 "EDMG channel %d not supported by AP, fallback to DMG",
4181 ssid->edmg_channel);
4182 }
4183 }
4184
4185 if (params.freq.edmg.channels) {
4186 wpa_printf(MSG_DEBUG,
4187 "EDMG before: channels 0x%x, bw_config %d",
4188 params.freq.edmg.channels,
4189 params.freq.edmg.bw_config);
4190 params.freq.edmg = get_supported_edmg(wpa_s,
4191 &params.freq,
4192 params.freq.edmg);
4193 wpa_printf(MSG_DEBUG,
4194 "EDMG after: channels 0x%x, bw_config %d",
4195 params.freq.edmg.channels,
4196 params.freq.edmg.bw_config);
4197 }
4198 }
4199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004200 params.pairwise_suite = cipher_pairwise;
4201 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004202 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004203 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004204 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004205 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004206 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004208 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004209#ifdef CONFIG_WEP
4210 {
4211 int i;
4212
4213 for (i = 0; i < NUM_WEP_KEYS; i++) {
4214 if (ssid->wep_key_len[i])
4215 params.wep_key[i] = ssid->wep_key[i];
4216 params.wep_key_len[i] = ssid->wep_key_len[i];
4217 }
4218 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004219 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004220#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004221
Hai Shalom74f70d42019-02-11 14:42:39 -08004222 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004223#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004224 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4225 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304226#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004227 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4228 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4229 (params.allowed_key_mgmts &
4230 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004231#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004232 params.passphrase = ssid->passphrase;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004233 if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4234 params.psk = psk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004235 }
4236
Hai Shalom74f70d42019-02-11 14:42:39 -08004237 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4238 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4239 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4240 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4241 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004242 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004243
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004244 if (wpa_s->conf->key_mgmt_offload) {
4245 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4246 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004247 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4248 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004249 params.req_key_mgmt_offload =
4250 ssid->proactive_key_caching < 0 ?
4251 wpa_s->conf->okc : ssid->proactive_key_caching;
4252 else
4253 params.req_key_mgmt_offload = 1;
4254
Winnie Chen4138eec2022-11-10 16:32:53 +08004255#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004256 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004257 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4258 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004259#else
4260 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4261 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004262#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004263 wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) == 0)
4264 params.psk = psk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004265 }
4266
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004267 params.drop_unencrypted = use_crypt;
4268
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004269 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004270 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4272 struct wpa_ie_data ie;
4273 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4274 ie.capabilities &
4275 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4276 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4277 "MFP: require MFP");
4278 params.mgmt_frame_protection =
4279 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004280#ifdef CONFIG_OWE
4281 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4282 !ssid->owe_only) {
4283 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4284#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 }
4286 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004288 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004289
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004290 if (wpa_s->p2pdev->set_sta_uapsd)
4291 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 else
4293 params.uapsd = -1;
4294
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004295#ifdef CONFIG_HT_OVERRIDES
4296 os_memset(&htcaps, 0, sizeof(htcaps));
4297 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4298 params.htcaps = (u8 *) &htcaps;
4299 params.htcaps_mask = (u8 *) &htcaps_mask;
4300 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4301#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004302#ifdef CONFIG_VHT_OVERRIDES
4303 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4304 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4305 params.vhtcaps = &vhtcaps;
4306 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004307 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004308#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004309#ifdef CONFIG_HE_OVERRIDES
4310 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4311#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00004312 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004313
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004314#ifdef CONFIG_P2P
4315 /*
4316 * If multi-channel concurrency is not supported, check for any
4317 * frequency conflict. In case of any frequency conflict, remove the
4318 * least prioritized connection.
4319 */
4320 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004321 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00004322 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004323 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004324 wpa_printf(MSG_DEBUG,
4325 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004326 freq, params.freq.freq);
4327 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004328 wpa_s, params.freq.freq, ssid) < 0) {
4329 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004330 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004331 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004332 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004333 }
4334 }
4335#endif /* CONFIG_P2P */
4336
Dmitry Shmidte4663042016-04-04 10:07:49 -07004337 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004338 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004339 params.prev_bssid = prev_bssid;
4340
Hai Shalom60840252021-02-19 19:02:11 -08004341#ifdef CONFIG_SAE
4342 params.sae_pwe = wpa_s->conf->sae_pwe;
4343#endif /* CONFIG_SAE */
4344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004345 ret = wpa_drv_associate(wpa_s, &params);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004346 forced_memzero(psk, sizeof(psk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004347 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 if (ret < 0) {
4349 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4350 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004352 /*
4353 * The driver is known to mean what is saying, so we
4354 * can stop right here; the association will not
4355 * succeed.
4356 */
4357 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004358 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004359 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004360 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004361 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4362 return;
4363 }
4364 /* try to continue anyway; new association will be tried again
4365 * after timeout */
4366 assoc_failed = 1;
4367 }
4368
4369 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4370 /* Set the key after the association just in case association
4371 * cleared the previously configured key. */
4372 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4373 /* No need to timeout authentication since there is no key
4374 * management. */
4375 wpa_supplicant_cancel_auth_timeout(wpa_s);
4376 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4377#ifdef CONFIG_IBSS_RSN
4378 } else if (ssid->mode == WPAS_MODE_IBSS &&
4379 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4380 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4381 /*
4382 * RSN IBSS authentication is per-STA and we can disable the
4383 * per-BSSID authentication.
4384 */
4385 wpa_supplicant_cancel_auth_timeout(wpa_s);
4386#endif /* CONFIG_IBSS_RSN */
4387 } else {
4388 /* Timeout for IEEE 802.11 authentication and association */
4389 int timeout = 60;
4390
4391 if (assoc_failed) {
4392 /* give IBSS a bit more time */
4393 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4394 } else if (wpa_s->conf->ap_scan == 1) {
4395 /* give IBSS a bit more time */
4396 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4397 }
4398 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4399 }
4400
Hai Shalomfdcde762020-04-02 11:19:20 -07004401#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004402 if (wep_keys_set &&
4403 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 /* Set static WEP keys again */
4405 wpa_set_wep_keys(wpa_s, ssid);
4406 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004407#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408
Sunil8cd6f4d2022-06-28 18:40:46 +00004409 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 /*
4411 * Do not allow EAP session resumption between different
4412 * network configurations.
4413 */
4414 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4415 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004416
4417 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004418 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004419#ifdef CONFIG_HS20
4420 hs20_configure_frame_filters(wpa_s);
4421#endif /* CONFIG_HS20 */
4422 }
4423
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004424 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4425 wpa_supplicant_initiate_eapol(wpa_s);
4426 if (old_ssid != wpa_s->current_ssid)
4427 wpas_notify_network_changed(wpa_s);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004428 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
4429 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004430}
4431
4432
4433static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4434 const u8 *addr)
4435{
4436 struct wpa_ssid *old_ssid;
4437
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004438 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004439 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004440 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004441 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004442 wpa_sm_set_config(wpa_s->wpa, NULL);
4443 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4444 if (old_ssid != wpa_s->current_ssid)
4445 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004446
4447 wpas_scs_deinit(wpa_s);
4448 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004449 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4450}
4451
4452
4453/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4455 * @wpa_s: Pointer to wpa_supplicant data
4456 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4457 *
4458 * This function is used to request %wpa_supplicant to deauthenticate from the
4459 * current AP.
4460 */
4461void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004462 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463{
4464 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004465 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004466 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004468 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004469 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004470 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004471 reason_code, reason2str(reason_code),
4472 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004473
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004474 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4475 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4476 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004477 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004478 else if (!is_zero_ether_addr(wpa_s->bssid))
4479 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004480 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4481 /*
4482 * When using driver-based BSS selection, we may not know the
4483 * BSSID with which we are currently trying to associate. We
4484 * need to notify the driver of this disconnection even in such
4485 * a case, so use the all zeros address here.
4486 */
4487 addr = wpa_s->bssid;
4488 zero_addr = 1;
4489 }
4490
Hai Shalom74f70d42019-02-11 14:42:39 -08004491 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4492 wpa_s->enabled_4addr_mode = 0;
4493
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004494#ifdef CONFIG_TDLS
4495 wpa_tdls_teardown_peers(wpa_s->wpa);
4496#endif /* CONFIG_TDLS */
4497
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004498#ifdef CONFIG_MESH
4499 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004500 struct mesh_conf *mconf;
4501
4502 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004503 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4504 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004505 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4506 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004507 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004508 }
4509#endif /* CONFIG_MESH */
4510
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004511 if (addr) {
4512 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004513 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004514 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004515 event.deauth_info.locally_generated = 1;
4516 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004517 if (zero_addr)
4518 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519 }
4520
4521 wpa_supplicant_clear_connection(wpa_s, addr);
4522}
4523
Hai Shalomfdcde762020-04-02 11:19:20 -07004524
4525void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4526{
4527 wpa_s->own_reconnect_req = 1;
4528 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4529
4530}
4531
4532
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004533static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4534 struct wpa_ssid *ssid)
4535{
4536 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4537 return;
4538
4539 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004540 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004541 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4542 wpas_notify_network_enabled_changed(wpa_s, ssid);
4543
4544 /*
4545 * Try to reassociate since there is no current configuration and a new
4546 * network was made available.
4547 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004548 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004549 wpa_s->reassociate = 1;
4550}
4551
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004552
Roshan Pius950bec92016-07-19 09:49:24 -07004553/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004554 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004555 * @wpa_s: wpa_supplicant structure for a network interface
4556 * Returns: The new network configuration or %NULL if operation failed
4557 *
4558 * This function performs the following operations:
4559 * 1. Adds a new network.
4560 * 2. Send network addition notification.
4561 * 3. Marks the network disabled.
4562 * 4. Set network default parameters.
4563 */
4564struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4565{
4566 struct wpa_ssid *ssid;
4567
4568 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004569 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004570 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004571 wpas_notify_network_added(wpa_s, ssid);
4572 ssid->disabled = 1;
4573 wpa_config_set_network_defaults(ssid);
4574
4575 return ssid;
4576}
4577
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004578
Roshan Pius950bec92016-07-19 09:49:24 -07004579/**
4580 * wpa_supplicant_remove_network - Remove a configured network based on id
4581 * @wpa_s: wpa_supplicant structure for a network interface
4582 * @id: Unique network id to search for
4583 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4584 * could not be removed
4585 *
4586 * This function performs the following operations:
4587 * 1. Removes the network.
4588 * 2. Send network removal notification.
4589 * 3. Update internal state machines.
4590 * 4. Stop any running sched scans.
4591 */
4592int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4593{
Sunil Ravia04bd252022-05-02 22:54:18 -07004594 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004595 int was_disabled;
4596
4597 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004598 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004599 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004600 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004601
Sunil Ravia04bd252022-05-02 22:54:18 -07004602 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004603#ifdef CONFIG_SME
4604 wpa_s->sme.prev_bssid_set = 0;
4605#endif /* CONFIG_SME */
4606 /*
4607 * Invalidate the EAP session cache if the current or
4608 * previously used network is removed.
4609 */
4610 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4611 }
4612
Sunil Ravia04bd252022-05-02 22:54:18 -07004613 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004614 wpa_sm_set_config(wpa_s->wpa, NULL);
4615 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4616
4617 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4618 wpa_s->own_disconnect_req = 1;
4619 wpa_supplicant_deauthenticate(wpa_s,
4620 WLAN_REASON_DEAUTH_LEAVING);
4621 }
4622
4623 was_disabled = ssid->disabled;
4624
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004625 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004626 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004627
4628 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004629 wpa_printf(MSG_DEBUG,
4630 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004631 wpa_supplicant_cancel_sched_scan(wpa_s);
4632 wpa_supplicant_req_scan(wpa_s, 0, 0);
4633 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004634
Roshan Pius950bec92016-07-19 09:49:24 -07004635 return 0;
4636}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004639/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004640 * wpa_supplicant_remove_all_networks - Remove all configured networks
4641 * @wpa_s: wpa_supplicant structure for a network interface
4642 * Returns: 0 on success (errors are currently ignored)
4643 *
4644 * This function performs the following operations:
4645 * 1. Remove all networks.
4646 * 2. Send network removal notifications.
4647 * 3. Update internal state machines.
4648 * 4. Stop any running sched scans.
4649 */
4650int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4651{
4652 struct wpa_ssid *ssid;
4653
4654 if (wpa_s->sched_scanning)
4655 wpa_supplicant_cancel_sched_scan(wpa_s);
4656
4657 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4658 if (wpa_s->current_ssid) {
4659#ifdef CONFIG_SME
4660 wpa_s->sme.prev_bssid_set = 0;
4661#endif /* CONFIG_SME */
4662 wpa_sm_set_config(wpa_s->wpa, NULL);
4663 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4664 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4665 wpa_s->own_disconnect_req = 1;
4666 wpa_supplicant_deauthenticate(
4667 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4668 }
4669 ssid = wpa_s->conf->ssid;
4670 while (ssid) {
4671 struct wpa_ssid *remove_ssid = ssid;
4672 int id;
4673
4674 id = ssid->id;
4675 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004676 wpas_notify_network_removed(wpa_s, remove_ssid);
4677 wpa_config_remove_network(wpa_s->conf, id);
4678 }
4679 return 0;
4680}
4681
4682
4683/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004684 * wpa_supplicant_enable_network - Mark a configured network as enabled
4685 * @wpa_s: wpa_supplicant structure for a network interface
4686 * @ssid: wpa_ssid structure for a configured network or %NULL
4687 *
4688 * Enables the specified network or all networks if no network specified.
4689 */
4690void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4691 struct wpa_ssid *ssid)
4692{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004693 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004694 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4695 wpa_supplicant_enable_one_network(wpa_s, ssid);
4696 } else
4697 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004699 if (wpa_s->reassociate && !wpa_s->disconnected &&
4700 (!wpa_s->current_ssid ||
4701 wpa_s->wpa_state == WPA_DISCONNECTED ||
4702 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004703 if (wpa_s->sched_scanning) {
4704 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4705 "new network to scan filters");
4706 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004707 }
4708
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004709 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4710 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004711 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004712 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 }
4714}
4715
4716
4717/**
4718 * wpa_supplicant_disable_network - Mark a configured network as disabled
4719 * @wpa_s: wpa_supplicant structure for a network interface
4720 * @ssid: wpa_ssid structure for a configured network or %NULL
4721 *
4722 * Disables the specified network or all networks if no network specified.
4723 */
4724void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4725 struct wpa_ssid *ssid)
4726{
4727 struct wpa_ssid *other_ssid;
4728 int was_disabled;
4729
4730 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004731 if (wpa_s->sched_scanning)
4732 wpa_supplicant_cancel_sched_scan(wpa_s);
4733
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4735 other_ssid = other_ssid->next) {
4736 was_disabled = other_ssid->disabled;
4737 if (was_disabled == 2)
4738 continue; /* do not change persistent P2P group
4739 * data */
4740
4741 other_ssid->disabled = 1;
4742
4743 if (was_disabled != other_ssid->disabled)
4744 wpas_notify_network_enabled_changed(
4745 wpa_s, other_ssid);
4746 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004747 if (wpa_s->current_ssid) {
4748 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4749 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004750 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004752 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004753 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004754 if (ssid == wpa_s->current_ssid) {
4755 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4756 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004757 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004759 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004760
4761 was_disabled = ssid->disabled;
4762
4763 ssid->disabled = 1;
4764
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004765 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004767 if (wpa_s->sched_scanning) {
4768 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4769 "to remove network from filters");
4770 wpa_supplicant_cancel_sched_scan(wpa_s);
4771 wpa_supplicant_req_scan(wpa_s, 0, 0);
4772 }
4773 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004774 }
4775}
4776
4777
4778/**
4779 * wpa_supplicant_select_network - Attempt association with a network
4780 * @wpa_s: wpa_supplicant structure for a network interface
4781 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4782 */
4783void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4784 struct wpa_ssid *ssid)
4785{
4786
4787 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004788 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004789
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004790 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004791 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4792 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004793 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004794 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004795 disconnected = 1;
4796 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004798 if (ssid)
4799 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 /*
4802 * Mark all other networks disabled or mark all networks enabled if no
4803 * network specified.
4804 */
4805 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4806 other_ssid = other_ssid->next) {
4807 int was_disabled = other_ssid->disabled;
4808 if (was_disabled == 2)
4809 continue; /* do not change persistent P2P group data */
4810
4811 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004812 if (was_disabled && !other_ssid->disabled)
4813 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004814
4815 if (was_disabled != other_ssid->disabled)
4816 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4817 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004818
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004819 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4820 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004821 /* We are already associated with the selected network */
4822 wpa_printf(MSG_DEBUG, "Already associated with the "
4823 "selected network - do nothing");
4824 return;
4825 }
4826
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004827 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004828 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004829 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004830 wpa_s->connect_without_scan =
4831 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004832
4833 /*
4834 * Don't optimize next scan freqs since a new ESS has been
4835 * selected.
4836 */
4837 os_free(wpa_s->next_scan_freqs);
4838 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004839 } else {
4840 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004841 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004843 wpa_s->disconnected = 0;
4844 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004845 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004846 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004847 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004848 ssid->owe_transition_bss_select_count = 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07004849 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Hai Shalomc3565922019-10-28 11:58:20 -07004850 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004851
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004852 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004853 wpa_supplicant_fast_associate(wpa_s) != 1) {
4854 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004855 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004856 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004857 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004858
4859 if (ssid)
4860 wpas_notify_network_selected(wpa_s, ssid);
4861}
4862
4863
4864/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004865 * wpas_remove_cred - Remove the specified credential and all the network
4866 * entries created based on the removed credential
4867 * @wpa_s: wpa_supplicant structure for a network interface
4868 * @cred: The credential to remove
4869 * Returns: 0 on success, -1 on failure
4870 */
4871int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4872{
4873 struct wpa_ssid *ssid, *next;
4874 int id;
4875
4876 if (!cred) {
4877 wpa_printf(MSG_DEBUG, "Could not find cred");
4878 return -1;
4879 }
4880
4881 id = cred->id;
4882 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4883 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4884 return -1;
4885 }
4886
4887 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4888
4889 /* Remove any network entry created based on the removed credential */
4890 ssid = wpa_s->conf->ssid;
4891 while (ssid) {
4892 next = ssid->next;
4893
4894 if (ssid->parent_cred == cred) {
4895 wpa_printf(MSG_DEBUG,
4896 "Remove network id %d since it used the removed credential",
4897 ssid->id);
4898 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4899 -1) {
4900 wpa_printf(MSG_DEBUG,
4901 "Could not find network id=%d",
4902 ssid->id);
4903 }
4904 }
4905
4906 ssid = next;
4907 }
4908
4909 return 0;
4910}
4911
4912
4913/**
4914 * wpas_remove_cred - Remove all the Interworking credentials
4915 * @wpa_s: wpa_supplicant structure for a network interface
4916 * Returns: 0 on success, -1 on failure
4917 */
4918int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4919{
4920 int res, ret = 0;
4921 struct wpa_cred *cred, *prev;
4922
4923 cred = wpa_s->conf->cred;
4924 while (cred) {
4925 prev = cred;
4926 cred = cred->next;
4927 res = wpas_remove_cred(wpa_s, prev);
4928 if (res < 0) {
4929 wpa_printf(MSG_DEBUG,
4930 "Removal of all credentials failed - failed to remove credential id=%d",
4931 prev->id);
4932 ret = -1;
4933 }
4934 }
4935
4936 return ret;
4937}
4938
4939
4940/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004941 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4942 * @wpa_s: wpa_supplicant structure for a network interface
4943 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4944 * @pkcs11_module_path: PKCS #11 module path or NULL
4945 * Returns: 0 on success; -1 on failure
4946 *
4947 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4948 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4949 * module path fails the paths will be reset to the default value (NULL).
4950 */
4951int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4952 const char *pkcs11_engine_path,
4953 const char *pkcs11_module_path)
4954{
4955 char *pkcs11_engine_path_copy = NULL;
4956 char *pkcs11_module_path_copy = NULL;
4957
4958 if (pkcs11_engine_path != NULL) {
4959 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4960 if (pkcs11_engine_path_copy == NULL)
4961 return -1;
4962 }
4963 if (pkcs11_module_path != NULL) {
4964 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004965 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004966 os_free(pkcs11_engine_path_copy);
4967 return -1;
4968 }
4969 }
4970
4971 os_free(wpa_s->conf->pkcs11_engine_path);
4972 os_free(wpa_s->conf->pkcs11_module_path);
4973 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4974 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4975
4976 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4977 eapol_sm_deinit(wpa_s->eapol);
4978 wpa_s->eapol = NULL;
4979 if (wpa_supplicant_init_eapol(wpa_s)) {
4980 /* Error -> Reset paths to the default value (NULL) once. */
4981 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4982 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4983 NULL);
4984
4985 return -1;
4986 }
4987 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4988
4989 return 0;
4990}
4991
4992
4993/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004994 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4995 * @wpa_s: wpa_supplicant structure for a network interface
4996 * @ap_scan: AP scan mode
4997 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4998 *
4999 */
5000int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
5001{
5002
5003 int old_ap_scan;
5004
5005 if (ap_scan < 0 || ap_scan > 2)
5006 return -1;
5007
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005008 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5009 wpa_printf(MSG_INFO,
5010 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5011 }
5012
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005013#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005014 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
5015 wpa_s->wpa_state >= WPA_ASSOCIATING &&
5016 wpa_s->wpa_state < WPA_COMPLETED) {
5017 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
5018 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005019 return 0;
5020 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005021#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07005022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005023 old_ap_scan = wpa_s->conf->ap_scan;
5024 wpa_s->conf->ap_scan = ap_scan;
5025
5026 if (old_ap_scan != wpa_s->conf->ap_scan)
5027 wpas_notify_ap_scan_changed(wpa_s);
5028
5029 return 0;
5030}
5031
5032
5033/**
5034 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
5035 * @wpa_s: wpa_supplicant structure for a network interface
5036 * @expire_age: Expiration age in seconds
5037 * Returns: 0 if succeed or -1 if expire_age has an invalid value
5038 *
5039 */
5040int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
5041 unsigned int bss_expire_age)
5042{
5043 if (bss_expire_age < 10) {
5044 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
5045 bss_expire_age);
5046 return -1;
5047 }
5048 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
5049 bss_expire_age);
5050 wpa_s->conf->bss_expiration_age = bss_expire_age;
5051
5052 return 0;
5053}
5054
5055
5056/**
5057 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
5058 * @wpa_s: wpa_supplicant structure for a network interface
5059 * @expire_count: number of scans after which an unseen BSS is reclaimed
5060 * Returns: 0 if succeed or -1 if expire_count has an invalid value
5061 *
5062 */
5063int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
5064 unsigned int bss_expire_count)
5065{
5066 if (bss_expire_count < 1) {
5067 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
5068 bss_expire_count);
5069 return -1;
5070 }
5071 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
5072 bss_expire_count);
5073 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
5074
5075 return 0;
5076}
5077
5078
5079/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07005080 * wpa_supplicant_set_scan_interval - Set scan interval
5081 * @wpa_s: wpa_supplicant structure for a network interface
5082 * @scan_interval: scan interval in seconds
5083 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
5084 *
5085 */
5086int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
5087 int scan_interval)
5088{
5089 if (scan_interval < 0) {
5090 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
5091 scan_interval);
5092 return -1;
5093 }
5094 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
5095 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005096 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005097
5098 return 0;
5099}
5100
5101
5102/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005103 * wpa_supplicant_set_debug_params - Set global debug params
5104 * @global: wpa_global structure
5105 * @debug_level: debug level
5106 * @debug_timestamp: determines if show timestamp in debug data
5107 * @debug_show_keys: determines if show keys in debug data
5108 * Returns: 0 if succeed or -1 if debug_level has wrong value
5109 */
5110int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
5111 int debug_timestamp, int debug_show_keys)
5112{
5113
5114 int old_level, old_timestamp, old_show_keys;
5115
5116 /* check for allowed debuglevels */
5117 if (debug_level != MSG_EXCESSIVE &&
5118 debug_level != MSG_MSGDUMP &&
5119 debug_level != MSG_DEBUG &&
5120 debug_level != MSG_INFO &&
5121 debug_level != MSG_WARNING &&
5122 debug_level != MSG_ERROR)
5123 return -1;
5124
5125 old_level = wpa_debug_level;
5126 old_timestamp = wpa_debug_timestamp;
5127 old_show_keys = wpa_debug_show_keys;
5128
5129 wpa_debug_level = debug_level;
5130 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
5131 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
5132
5133 if (wpa_debug_level != old_level)
5134 wpas_notify_debug_level_changed(global);
5135 if (wpa_debug_timestamp != old_timestamp)
5136 wpas_notify_debug_timestamp_changed(global);
5137 if (wpa_debug_show_keys != old_show_keys)
5138 wpas_notify_debug_show_keys_changed(global);
5139
5140 return 0;
5141}
5142
5143
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005144#ifdef CONFIG_OWE
5145static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
5146 const u8 *entry_ssid, size_t entry_ssid_len)
5147{
5148 const u8 *owe, *pos, *end;
5149 u8 ssid_len;
5150 struct wpa_bss *bss;
5151
5152 /* Check network profile SSID aganst the SSID in the
5153 * OWE Transition Mode element. */
5154
5155 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5156 if (!bss)
5157 return 0;
5158
5159 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5160 if (!owe)
5161 return 0;
5162
5163 pos = owe + 6;
5164 end = owe + 2 + owe[1];
5165
5166 if (end - pos < ETH_ALEN + 1)
5167 return 0;
5168 pos += ETH_ALEN;
5169 ssid_len = *pos++;
5170 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5171 return 0;
5172
5173 return entry_ssid_len == ssid_len &&
5174 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5175}
5176#endif /* CONFIG_OWE */
5177
5178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005179/**
5180 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5181 * @wpa_s: Pointer to wpa_supplicant data
5182 * Returns: A pointer to the current network structure or %NULL on failure
5183 */
5184struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5185{
5186 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005187 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005188 int res;
5189 size_t ssid_len;
5190 u8 bssid[ETH_ALEN];
5191 int wired;
5192
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005193 res = wpa_drv_get_ssid(wpa_s, ssid);
5194 if (res < 0) {
5195 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5196 "driver");
5197 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005198 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005199 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005201 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5203 "driver");
5204 return NULL;
5205 }
5206
5207 wired = wpa_s->conf->ap_scan == 0 &&
5208 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5209
5210 entry = wpa_s->conf->ssid;
5211 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005212 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005213 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005214 (!entry->ssid ||
5215 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5216 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005217 (!entry->bssid_set ||
5218 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5219 return entry;
5220#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005221 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5223 (entry->ssid == NULL || entry->ssid_len == 0) &&
5224 (!entry->bssid_set ||
5225 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5226 return entry;
5227#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005228
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005229#ifdef CONFIG_OWE
5230 if (!wpas_network_disabled(wpa_s, entry) &&
5231 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5232 entry->ssid_len) &&
5233 (!entry->bssid_set ||
5234 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5235 return entry;
5236#endif /* CONFIG_OWE */
5237
Dmitry Shmidt04949592012-07-19 12:16:46 -07005238 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005239 entry->ssid_len == 0 &&
5240 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5241 return entry;
5242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005243 entry = entry->next;
5244 }
5245
5246 return NULL;
5247}
5248
5249
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005250static int select_driver(struct wpa_supplicant *wpa_s, int i)
5251{
5252 struct wpa_global *global = wpa_s->global;
5253
5254 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005255 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005256 if (global->drv_priv[i] == NULL) {
5257 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5258 "'%s'", wpa_drivers[i]->name);
5259 return -1;
5260 }
5261 }
5262
5263 wpa_s->driver = wpa_drivers[i];
5264 wpa_s->global_drv_priv = global->drv_priv[i];
5265
5266 return 0;
5267}
5268
5269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005270static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5271 const char *name)
5272{
5273 int i;
5274 size_t len;
5275 const char *pos, *driver = name;
5276
5277 if (wpa_s == NULL)
5278 return -1;
5279
5280 if (wpa_drivers[0] == NULL) {
5281 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5282 "wpa_supplicant");
5283 return -1;
5284 }
5285
5286 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005287 /* Default to first successful driver in the list */
5288 for (i = 0; wpa_drivers[i]; i++) {
5289 if (select_driver(wpa_s, i) == 0)
5290 return 0;
5291 }
5292 /* Drivers have each reported failure, so no wpa_msg() here. */
5293 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005294 }
5295
5296 do {
5297 pos = os_strchr(driver, ',');
5298 if (pos)
5299 len = pos - driver;
5300 else
5301 len = os_strlen(driver);
5302
5303 for (i = 0; wpa_drivers[i]; i++) {
5304 if (os_strlen(wpa_drivers[i]->name) == len &&
5305 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005306 0) {
5307 /* First driver that succeeds wins */
5308 if (select_driver(wpa_s, i) == 0)
5309 return 0;
5310 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005311 }
5312
5313 driver = pos + 1;
5314 } while (pos);
5315
5316 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5317 return -1;
5318}
5319
5320
5321/**
5322 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5323 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5324 * with struct wpa_driver_ops::init()
5325 * @src_addr: Source address of the EAPOL frame
5326 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5327 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005328 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329 *
5330 * This function is called for each received EAPOL frame. Most driver
5331 * interfaces rely on more generic OS mechanism for receiving frames through
5332 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5333 * take care of received EAPOL frames and deliver them to the core supplicant
5334 * code by calling this function.
5335 */
5336void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005337 const u8 *buf, size_t len,
5338 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005339{
5340 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005341 const u8 *connected_addr = wpa_s->valid_links ?
5342 wpa_s->ap_mld_addr : wpa_s->bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005343
Sunil8cd6f4d2022-06-28 18:40:46 +00005344 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5345 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005346 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5347
Hai Shalomc1a21442022-02-04 13:43:00 -08005348 if (wpa_s->own_disconnect_req) {
5349 wpa_printf(MSG_DEBUG,
5350 "Drop received EAPOL frame as we are disconnecting");
5351 return;
5352 }
5353
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005354#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005355 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5356 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005357 if (wpa_s->ignore_auth_resp) {
5358 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5359 return;
5360 }
5361#endif /* CONFIG_TESTING_OPTIONS */
5362
Jouni Malinena05074c2012-12-21 21:35:35 +02005363 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5364 (wpa_s->last_eapol_matches_bssid &&
5365#ifdef CONFIG_AP
5366 !wpa_s->ap_iface &&
5367#endif /* CONFIG_AP */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005368 os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005369 /*
5370 * There is possible race condition between receiving the
5371 * association event and the EAPOL frame since they are coming
5372 * through different paths from the driver. In order to avoid
5373 * issues in trying to process the EAPOL frame before receiving
5374 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005375 * the association event is received. This may also be needed in
5376 * driver-based roaming case, so also use src_addr != BSSID as a
5377 * trigger if we have previously confirmed that the
5378 * Authenticator uses BSSID as the src_addr (which is not the
5379 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005380 */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005381 wpa_dbg(wpa_s, MSG_DEBUG,
5382 "Not associated - Delay processing of received EAPOL frame (state=%s connected_addr="
5383 MACSTR ")",
Jouni Malinena05074c2012-12-21 21:35:35 +02005384 wpa_supplicant_state_txt(wpa_s->wpa_state),
Sunil Ravi77d572f2023-01-17 23:58:31 +00005385 MAC2STR(connected_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005386 wpabuf_free(wpa_s->pending_eapol_rx);
5387 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5388 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005389 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005390 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5391 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005392 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005393 }
5394 return;
5395 }
5396
Jouni Malinena05074c2012-12-21 21:35:35 +02005397 wpa_s->last_eapol_matches_bssid =
Sunil Ravi77d572f2023-01-17 23:58:31 +00005398 os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
Jouni Malinena05074c2012-12-21 21:35:35 +02005399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005400#ifdef CONFIG_AP
5401 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005402 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5403 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005404 return;
5405 }
5406#endif /* CONFIG_AP */
5407
5408 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5409 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5410 "no key management is configured");
5411 return;
5412 }
5413
5414 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005415 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005416 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5417 wpa_s->wpa_state != WPA_COMPLETED) &&
5418 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005419 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005420 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005421 int timeout = 10;
5422
5423 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5424 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5425 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5426 /* Use longer timeout for IEEE 802.1X/EAP */
5427 timeout = 70;
5428 }
5429
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005430#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005431 if (wpa_s->current_ssid && wpa_s->current_bss &&
5432 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5433 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5434 /*
5435 * Use shorter timeout if going through WPS AP iteration
5436 * for PIN config method with an AP that does not
5437 * advertise Selected Registrar.
5438 */
5439 struct wpabuf *wps_ie;
5440
5441 wps_ie = wpa_bss_get_vendor_ie_multi(
5442 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5443 if (wps_ie &&
5444 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5445 timeout = 10;
5446 wpabuf_free(wps_ie);
5447 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005448#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005449
5450 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005451 }
5452 wpa_s->eapol_received++;
5453
5454 if (wpa_s->countermeasures) {
5455 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5456 "EAPOL packet");
5457 return;
5458 }
5459
5460#ifdef CONFIG_IBSS_RSN
5461 if (wpa_s->current_ssid &&
5462 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005463 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5464 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005465 return;
5466 }
5467#endif /* CONFIG_IBSS_RSN */
5468
5469 /* Source address of the incoming EAPOL frame could be compared to the
5470 * current BSSID. However, it is possible that a centralized
5471 * Authenticator could be using another MAC address than the BSSID of
5472 * an AP, so just allow any address to be used for now. The replies are
5473 * still sent to the current BSSID (if available), though. */
5474
5475 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5476 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005477 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5478 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005479 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5480 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005481 return;
5482 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005483 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005484 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005485 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5486 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005487 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005488 * handshake processing which would normally set portValid. We
5489 * need this to allow the EAPOL state machines to be completed
5490 * without going through EAPOL-Key handshake.
5491 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005492 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005493 }
5494}
5495
5496
Sunil8cd6f4d2022-06-28 18:40:46 +00005497static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5498 const u8 *buf, size_t len)
5499{
5500 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5501 FRAME_ENCRYPTION_UNKNOWN);
5502}
5503
5504
Hai Shalomb755a2a2020-04-23 21:49:02 -07005505static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5506{
5507 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5508 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5509}
5510
5511
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005512int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005514 u8 prev_mac_addr[ETH_ALEN];
5515
5516 os_memcpy(prev_mac_addr, wpa_s->own_addr, ETH_ALEN);
5517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005518 if ((!wpa_s->p2p_mgmt ||
5519 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5520 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005521 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5523 wpa_drv_get_mac_addr(wpa_s),
5524 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005525 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005526 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005527 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005528 if (wpa_s->l2 == NULL)
5529 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005530
5531 if (l2_packet_set_packet_filter(wpa_s->l2,
5532 L2_PACKET_FILTER_PKTTYPE))
5533 wpa_dbg(wpa_s, MSG_DEBUG,
5534 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005535
5536 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5537 wpa_msg(wpa_s, MSG_ERROR,
5538 "Failed to get own L2 address");
5539 return -1;
5540 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541 } else {
5542 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5543 if (addr)
5544 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5545 }
5546
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005547 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005548 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005549
Hai Shalomc3565922019-10-28 11:58:20 -07005550#ifdef CONFIG_FST
5551 if (wpa_s->fst)
5552 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5553#endif /* CONFIG_FST */
5554
Sunil Ravi77d572f2023-01-17 23:58:31 +00005555 if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
5556 wpas_notify_mac_address_changed(wpa_s);
5557
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005558 return 0;
5559}
5560
5561
Dmitry Shmidt04949592012-07-19 12:16:46 -07005562static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5563 const u8 *buf, size_t len)
5564{
5565 struct wpa_supplicant *wpa_s = ctx;
5566 const struct l2_ethhdr *eth;
5567
5568 if (len < sizeof(*eth))
5569 return;
5570 eth = (const struct l2_ethhdr *) buf;
5571
5572 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5573 !(eth->h_dest[0] & 0x01)) {
5574 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5575 " (bridge - not for this interface - ignore)",
5576 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5577 return;
5578 }
5579
5580 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5581 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5582 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005583 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005584}
5585
5586
Hai Shalom899fcc72020-10-19 14:38:18 -07005587int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5588 const char *bridge_ifname)
5589{
5590 if (wpa_s->wpa_state > WPA_SCANNING)
5591 return -EBUSY;
5592
5593 if (bridge_ifname &&
5594 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5595 return -EINVAL;
5596
5597 if (!bridge_ifname)
5598 bridge_ifname = "";
5599
5600 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5601 return 0;
5602
5603 if (wpa_s->l2_br) {
5604 l2_packet_deinit(wpa_s->l2_br);
5605 wpa_s->l2_br = NULL;
5606 }
5607
5608 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5609 sizeof(wpa_s->bridge_ifname));
5610
5611 if (wpa_s->bridge_ifname[0]) {
5612 wpa_dbg(wpa_s, MSG_DEBUG,
5613 "Receiving packets from bridge interface '%s'",
5614 wpa_s->bridge_ifname);
5615 wpa_s->l2_br = l2_packet_init_bridge(
5616 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5617 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5618 if (!wpa_s->l2_br) {
5619 wpa_msg(wpa_s, MSG_ERROR,
5620 "Failed to open l2_packet connection for the bridge interface '%s'",
5621 wpa_s->bridge_ifname);
5622 goto fail;
5623 }
5624 }
5625
5626#ifdef CONFIG_TDLS
5627 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5628 goto fail;
5629#endif /* CONFIG_TDLS */
5630
5631 return 0;
5632fail:
5633 wpa_s->bridge_ifname[0] = 0;
5634 if (wpa_s->l2_br) {
5635 l2_packet_deinit(wpa_s->l2_br);
5636 wpa_s->l2_br = NULL;
5637 }
5638#ifdef CONFIG_TDLS
5639 if (!wpa_s->p2p_mgmt)
5640 wpa_tdls_init(wpa_s->wpa);
5641#endif /* CONFIG_TDLS */
5642 return -EIO;
5643}
5644
5645
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005646/**
5647 * wpa_supplicant_driver_init - Initialize driver interface parameters
5648 * @wpa_s: Pointer to wpa_supplicant data
5649 * Returns: 0 on success, -1 on failure
5650 *
5651 * This function is called to initialize driver interface parameters.
5652 * wpa_drv_init() must have been called before this function to initialize the
5653 * driver interface.
5654 */
5655int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5656{
5657 static int interface_count = 0;
5658
5659 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5660 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005661
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005662 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5663 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005664 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005665 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5666
Hai Shalomb755a2a2020-04-23 21:49:02 -07005667 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005668 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5669 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005670 wpa_s->l2_br = l2_packet_init_bridge(
5671 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5672 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005673 if (wpa_s->l2_br == NULL) {
5674 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5675 "connection for the bridge interface '%s'",
5676 wpa_s->bridge_ifname);
5677 return -1;
5678 }
5679 }
5680
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005681 if (wpa_s->conf->ap_scan == 2 &&
5682 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5683 wpa_printf(MSG_INFO,
5684 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5685 }
5686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005687 wpa_clear_keys(wpa_s, NULL);
5688
5689 /* Make sure that TKIP countermeasures are not left enabled (could
5690 * happen if wpa_supplicant is killed during countermeasures. */
5691 wpa_drv_set_countermeasures(wpa_s, 0);
5692
5693 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5694 wpa_drv_flush_pmkid(wpa_s);
5695
5696 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005697 wpa_s->prev_scan_wildcard = 0;
5698
Dmitry Shmidt04949592012-07-19 12:16:46 -07005699 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005700 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5701 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5702 interface_count = 0;
5703 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005704#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005705 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005706 wpa_supplicant_delayed_sched_scan(wpa_s,
5707 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005708 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005709 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005710 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005711#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005712 interface_count++;
5713 } else
5714 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5715
5716 return 0;
5717}
5718
5719
5720static int wpa_supplicant_daemon(const char *pid_file)
5721{
5722 wpa_printf(MSG_DEBUG, "Daemonize..");
5723 return os_daemonize(pid_file);
5724}
5725
5726
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005727static struct wpa_supplicant *
5728wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005729{
5730 struct wpa_supplicant *wpa_s;
5731
5732 wpa_s = os_zalloc(sizeof(*wpa_s));
5733 if (wpa_s == NULL)
5734 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005735 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005736 wpa_s->scan_interval = 5;
5737 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005738 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005739 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005740 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005741 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005742
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005743 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005744 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005745#ifdef CONFIG_TESTING_OPTIONS
5746 dl_list_init(&wpa_s->drv_signal_override);
5747#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005748 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005750 return wpa_s;
5751}
5752
5753
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005754#ifdef CONFIG_HT_OVERRIDES
5755
5756static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5757 struct ieee80211_ht_capabilities *htcaps,
5758 struct ieee80211_ht_capabilities *htcaps_mask,
5759 const char *ht_mcs)
5760{
5761 /* parse ht_mcs into hex array */
5762 int i;
5763 const char *tmp = ht_mcs;
5764 char *end = NULL;
5765
5766 /* If ht_mcs is null, do not set anything */
5767 if (!ht_mcs)
5768 return 0;
5769
5770 /* This is what we are setting in the kernel */
5771 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5772
5773 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5774
5775 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005776 long v;
5777
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005778 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005779 v = strtol(tmp, &end, 16);
5780
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005781 if (errno == 0) {
5782 wpa_msg(wpa_s, MSG_DEBUG,
5783 "htcap value[%i]: %ld end: %p tmp: %p",
5784 i, v, end, tmp);
5785 if (end == tmp)
5786 break;
5787
5788 htcaps->supported_mcs_set[i] = v;
5789 tmp = end;
5790 } else {
5791 wpa_msg(wpa_s, MSG_ERROR,
5792 "Failed to parse ht-mcs: %s, error: %s\n",
5793 ht_mcs, strerror(errno));
5794 return -1;
5795 }
5796 }
5797
5798 /*
5799 * If we were able to parse any values, then set mask for the MCS set.
5800 */
5801 if (i) {
5802 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5803 IEEE80211_HT_MCS_MASK_LEN - 1);
5804 /* skip the 3 reserved bits */
5805 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5806 0x1f;
5807 }
5808
5809 return 0;
5810}
5811
5812
5813static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5814 struct ieee80211_ht_capabilities *htcaps,
5815 struct ieee80211_ht_capabilities *htcaps_mask,
5816 int disabled)
5817{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005818 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005819
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005820 if (disabled == -1)
5821 return 0;
5822
Hai Shalom74f70d42019-02-11 14:42:39 -08005823 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5824
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005825 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5826 htcaps_mask->ht_capabilities_info |= msk;
5827 if (disabled)
5828 htcaps->ht_capabilities_info &= msk;
5829 else
5830 htcaps->ht_capabilities_info |= msk;
5831
5832 return 0;
5833}
5834
5835
5836static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5837 struct ieee80211_ht_capabilities *htcaps,
5838 struct ieee80211_ht_capabilities *htcaps_mask,
5839 int factor)
5840{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005841 if (factor == -1)
5842 return 0;
5843
Hai Shalom74f70d42019-02-11 14:42:39 -08005844 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5845
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005846 if (factor < 0 || factor > 3) {
5847 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5848 "Must be 0-3 or -1", factor);
5849 return -EINVAL;
5850 }
5851
5852 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5853 htcaps->a_mpdu_params &= ~0x3;
5854 htcaps->a_mpdu_params |= factor & 0x3;
5855
5856 return 0;
5857}
5858
5859
5860static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5861 struct ieee80211_ht_capabilities *htcaps,
5862 struct ieee80211_ht_capabilities *htcaps_mask,
5863 int density)
5864{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005865 if (density == -1)
5866 return 0;
5867
Hai Shalom74f70d42019-02-11 14:42:39 -08005868 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5869
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005870 if (density < 0 || density > 7) {
5871 wpa_msg(wpa_s, MSG_ERROR,
5872 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5873 density);
5874 return -EINVAL;
5875 }
5876
5877 htcaps_mask->a_mpdu_params |= 0x1C;
5878 htcaps->a_mpdu_params &= ~(0x1C);
5879 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5880
5881 return 0;
5882}
5883
5884
5885static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5886 struct ieee80211_ht_capabilities *htcaps,
5887 struct ieee80211_ht_capabilities *htcaps_mask,
5888 int disabled)
5889{
Hai Shalom74f70d42019-02-11 14:42:39 -08005890 if (disabled)
5891 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005892
Paul Stewart092955c2017-02-06 09:13:09 -08005893 set_disable_ht40(htcaps, disabled);
5894 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005895
5896 return 0;
5897}
5898
5899
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005900static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5901 struct ieee80211_ht_capabilities *htcaps,
5902 struct ieee80211_ht_capabilities *htcaps_mask,
5903 int disabled)
5904{
5905 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005906 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5907 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005908
Hai Shalom74f70d42019-02-11 14:42:39 -08005909 if (disabled)
5910 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005911
5912 if (disabled)
5913 htcaps->ht_capabilities_info &= ~msk;
5914 else
5915 htcaps->ht_capabilities_info |= msk;
5916
5917 htcaps_mask->ht_capabilities_info |= msk;
5918
5919 return 0;
5920}
5921
5922
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005923static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5924 struct ieee80211_ht_capabilities *htcaps,
5925 struct ieee80211_ht_capabilities *htcaps_mask,
5926 int disabled)
5927{
5928 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005929 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005930
Hai Shalom74f70d42019-02-11 14:42:39 -08005931 if (disabled)
5932 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005933
5934 if (disabled)
5935 htcaps->ht_capabilities_info &= ~msk;
5936 else
5937 htcaps->ht_capabilities_info |= msk;
5938
5939 htcaps_mask->ht_capabilities_info |= msk;
5940
5941 return 0;
5942}
5943
5944
Hai Shalom74f70d42019-02-11 14:42:39 -08005945static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5946 struct ieee80211_ht_capabilities *htcaps,
5947 struct ieee80211_ht_capabilities *htcaps_mask,
5948 int tx_stbc)
5949{
5950 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5951
5952 if (tx_stbc == -1)
5953 return 0;
5954
5955 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5956
5957 if (tx_stbc < 0 || tx_stbc > 1) {
5958 wpa_msg(wpa_s, MSG_ERROR,
5959 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5960 return -EINVAL;
5961 }
5962
5963 htcaps_mask->ht_capabilities_info |= msk;
5964 htcaps->ht_capabilities_info &= ~msk;
5965 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5966
5967 return 0;
5968}
5969
5970
5971static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5972 struct ieee80211_ht_capabilities *htcaps,
5973 struct ieee80211_ht_capabilities *htcaps_mask,
5974 int rx_stbc)
5975{
5976 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5977
5978 if (rx_stbc == -1)
5979 return 0;
5980
5981 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5982
5983 if (rx_stbc < 0 || rx_stbc > 3) {
5984 wpa_msg(wpa_s, MSG_ERROR,
5985 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5986 return -EINVAL;
5987 }
5988
5989 htcaps_mask->ht_capabilities_info |= msk;
5990 htcaps->ht_capabilities_info &= ~msk;
5991 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5992
5993 return 0;
5994}
5995
5996
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005997void wpa_supplicant_apply_ht_overrides(
5998 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5999 struct wpa_driver_associate_params *params)
6000{
6001 struct ieee80211_ht_capabilities *htcaps;
6002 struct ieee80211_ht_capabilities *htcaps_mask;
6003
6004 if (!ssid)
6005 return;
6006
6007 params->disable_ht = ssid->disable_ht;
6008 if (!params->htcaps || !params->htcaps_mask)
6009 return;
6010
6011 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
6012 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
6013 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
6014 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
6015 ssid->disable_max_amsdu);
6016 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
6017 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
6018 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006019 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006020 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08006021 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
6022 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006023
6024 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006025 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07006026 htcaps->ht_capabilities_info |= bit;
6027 htcaps_mask->ht_capabilities_info |= bit;
6028 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006029}
6030
6031#endif /* CONFIG_HT_OVERRIDES */
6032
6033
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006034#ifdef CONFIG_VHT_OVERRIDES
6035void wpa_supplicant_apply_vht_overrides(
6036 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6037 struct wpa_driver_associate_params *params)
6038{
6039 struct ieee80211_vht_capabilities *vhtcaps;
6040 struct ieee80211_vht_capabilities *vhtcaps_mask;
6041
6042 if (!ssid)
6043 return;
6044
6045 params->disable_vht = ssid->disable_vht;
6046
6047 vhtcaps = (void *) params->vhtcaps;
6048 vhtcaps_mask = (void *) params->vhtcaps_mask;
6049
6050 if (!vhtcaps || !vhtcaps_mask)
6051 return;
6052
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006053 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
6054 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006055
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006056#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08006057 if (ssid->disable_sgi) {
6058 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
6059 VHT_CAP_SHORT_GI_160);
6060 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
6061 VHT_CAP_SHORT_GI_160);
6062 wpa_msg(wpa_s, MSG_DEBUG,
6063 "disable-sgi override specified, vht-caps: 0x%x",
6064 vhtcaps->vht_capabilities_info);
6065 }
6066
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006067 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006068 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
6069 int max_ampdu;
6070
6071 max_ampdu = (ssid->vht_capa &
6072 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
6073 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006074
6075 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
6076 wpa_set_ampdu_factor(wpa_s,
6077 (void *) params->htcaps,
6078 (void *) params->htcaps_mask,
6079 max_ampdu);
6080 }
6081#endif /* CONFIG_HT_OVERRIDES */
6082
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006083#define OVERRIDE_MCS(i) \
6084 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
6085 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006086 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006087 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006088 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
6089 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006090 } \
6091 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
6092 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006093 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006094 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006095 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
6096 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006097 }
6098
6099 OVERRIDE_MCS(1);
6100 OVERRIDE_MCS(2);
6101 OVERRIDE_MCS(3);
6102 OVERRIDE_MCS(4);
6103 OVERRIDE_MCS(5);
6104 OVERRIDE_MCS(6);
6105 OVERRIDE_MCS(7);
6106 OVERRIDE_MCS(8);
6107}
6108#endif /* CONFIG_VHT_OVERRIDES */
6109
6110
Hai Shalomfdcde762020-04-02 11:19:20 -07006111#ifdef CONFIG_HE_OVERRIDES
6112void wpa_supplicant_apply_he_overrides(
6113 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6114 struct wpa_driver_associate_params *params)
6115{
6116 if (!ssid)
6117 return;
6118
6119 params->disable_he = ssid->disable_he;
6120}
6121#endif /* CONFIG_HE_OVERRIDES */
6122
6123
Sunil Ravi77d572f2023-01-17 23:58:31 +00006124void wpa_supplicant_apply_eht_overrides(
6125 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
6126 struct wpa_driver_associate_params *params)
6127{
6128 if (!ssid)
6129 return;
6130
6131 params->disable_eht = ssid->disable_eht;
6132}
6133
6134
Dmitry Shmidt04949592012-07-19 12:16:46 -07006135static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
6136{
6137#ifdef PCSC_FUNCS
6138 size_t len;
6139
6140 if (!wpa_s->conf->pcsc_reader)
6141 return 0;
6142
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006143 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006144 if (!wpa_s->scard)
6145 return 1;
6146
6147 if (wpa_s->conf->pcsc_pin &&
6148 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
6149 scard_deinit(wpa_s->scard);
6150 wpa_s->scard = NULL;
6151 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
6152 return -1;
6153 }
6154
6155 len = sizeof(wpa_s->imsi) - 1;
6156 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
6157 scard_deinit(wpa_s->scard);
6158 wpa_s->scard = NULL;
6159 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
6160 return -1;
6161 }
6162 wpa_s->imsi[len] = '\0';
6163
6164 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
6165
6166 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
6167 wpa_s->imsi, wpa_s->mnc_len);
6168
6169 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
6170 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6171#endif /* PCSC_FUNCS */
6172
6173 return 0;
6174}
6175
6176
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006177int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6178{
6179 char *val, *pos;
6180
6181 ext_password_deinit(wpa_s->ext_pw);
6182 wpa_s->ext_pw = NULL;
6183 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6184
6185 if (!wpa_s->conf->ext_password_backend)
6186 return 0;
6187
6188 val = os_strdup(wpa_s->conf->ext_password_backend);
6189 if (val == NULL)
6190 return -1;
6191 pos = os_strchr(val, ':');
6192 if (pos)
6193 *pos++ = '\0';
6194
6195 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6196
6197 wpa_s->ext_pw = ext_password_init(val, pos);
6198 os_free(val);
6199 if (wpa_s->ext_pw == NULL) {
6200 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6201 return -1;
6202 }
6203 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6204
6205 return 0;
6206}
6207
6208
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006209#ifdef CONFIG_FST
6210
6211static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6212{
6213 struct wpa_supplicant *wpa_s = ctx;
6214
6215 return (is_zero_ether_addr(wpa_s->bssid) ||
6216 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6217}
6218
6219
6220static void wpas_fst_get_channel_info_cb(void *ctx,
6221 enum hostapd_hw_mode *hw_mode,
6222 u8 *channel)
6223{
6224 struct wpa_supplicant *wpa_s = ctx;
6225
6226 if (wpa_s->current_bss) {
6227 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6228 channel);
6229 } else if (wpa_s->hw.num_modes) {
6230 *hw_mode = wpa_s->hw.modes[0].mode;
6231 } else {
6232 WPA_ASSERT(0);
6233 *hw_mode = 0;
6234 }
6235}
6236
6237
6238static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6239{
6240 struct wpa_supplicant *wpa_s = ctx;
6241
6242 *modes = wpa_s->hw.modes;
6243 return wpa_s->hw.num_modes;
6244}
6245
6246
6247static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6248{
6249 struct wpa_supplicant *wpa_s = ctx;
6250
6251 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6252 wpa_s->fst_ies = fst_ies;
6253}
6254
6255
6256static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6257{
6258 struct wpa_supplicant *wpa_s = ctx;
6259
Paul Stewart092955c2017-02-06 09:13:09 -08006260 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6261 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6262 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6263 return -1;
6264 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006265 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006266 wpa_s->own_addr, wpa_s->bssid,
6267 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006268 0);
6269}
6270
6271
6272static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6273{
6274 struct wpa_supplicant *wpa_s = ctx;
6275
6276 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6277 return wpa_s->received_mb_ies;
6278}
6279
6280
6281static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6282 const u8 *buf, size_t size)
6283{
6284 struct wpa_supplicant *wpa_s = ctx;
6285 struct mb_ies_info info;
6286
6287 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6288
6289 if (!mb_ies_info_by_ies(&info, buf, size)) {
6290 wpabuf_free(wpa_s->received_mb_ies);
6291 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6292 }
6293}
6294
6295
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006296static const u8 * wpas_fst_get_peer_first(void *ctx,
6297 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006298 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006299{
6300 struct wpa_supplicant *wpa_s = ctx;
6301
6302 *get_ctx = NULL;
6303 if (!is_zero_ether_addr(wpa_s->bssid))
6304 return (wpa_s->received_mb_ies || !mb_only) ?
6305 wpa_s->bssid : NULL;
6306 return NULL;
6307}
6308
6309
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006310static const u8 * wpas_fst_get_peer_next(void *ctx,
6311 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006312 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006313{
6314 return NULL;
6315}
6316
6317void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6318 struct fst_wpa_obj *iface_obj)
6319{
Sunil8cd6f4d2022-06-28 18:40:46 +00006320 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006321 iface_obj->ctx = wpa_s;
6322 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6323 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6324 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6325 iface_obj->set_ies = wpas_fst_set_ies_cb;
6326 iface_obj->send_action = wpas_fst_send_action_cb;
6327 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6328 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6329 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6330 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6331}
6332#endif /* CONFIG_FST */
6333
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006334static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006335 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006336{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006337 struct wowlan_triggers *triggers;
6338 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006339
6340 if (!wpa_s->conf->wowlan_triggers)
6341 return 0;
6342
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006343 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6344 if (triggers) {
6345 ret = wpa_drv_wowlan(wpa_s, triggers);
6346 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006347 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006348 return ret;
6349}
6350
6351
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006352enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006353{
6354 if (freq < 3000)
6355 return BAND_2_4_GHZ;
6356 if (freq > 50000)
6357 return BAND_60_GHZ;
6358 return BAND_5_GHZ;
6359}
6360
6361
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006362unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006363{
6364 int i;
6365 unsigned int band = 0;
6366
6367 if (freqs) {
6368 /* freqs are specified for the radio work */
6369 for (i = 0; freqs[i]; i++)
6370 band |= wpas_freq_to_band(freqs[i]);
6371 } else {
6372 /*
6373 * freqs are not specified, implies all
6374 * the supported freqs by HW
6375 */
6376 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6377 if (wpa_s->hw.modes[i].num_channels != 0) {
6378 if (wpa_s->hw.modes[i].mode ==
6379 HOSTAPD_MODE_IEEE80211B ||
6380 wpa_s->hw.modes[i].mode ==
6381 HOSTAPD_MODE_IEEE80211G)
6382 band |= BAND_2_4_GHZ;
6383 else if (wpa_s->hw.modes[i].mode ==
6384 HOSTAPD_MODE_IEEE80211A)
6385 band |= BAND_5_GHZ;
6386 else if (wpa_s->hw.modes[i].mode ==
6387 HOSTAPD_MODE_IEEE80211AD)
6388 band |= BAND_60_GHZ;
6389 else if (wpa_s->hw.modes[i].mode ==
6390 HOSTAPD_MODE_IEEE80211ANY)
6391 band = BAND_2_4_GHZ | BAND_5_GHZ |
6392 BAND_60_GHZ;
6393 }
6394 }
6395 }
6396
6397 return band;
6398}
6399
6400
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006401static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6402 const char *rn)
6403{
6404 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6405 struct wpa_radio *radio;
6406
6407 while (rn && iface) {
6408 radio = iface->radio;
6409 if (radio && os_strcmp(rn, radio->name) == 0) {
6410 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6411 wpa_s->ifname, rn);
6412 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6413 return radio;
6414 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006415
6416 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006417 }
6418
6419 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6420 wpa_s->ifname, rn ? rn : "N/A");
6421 radio = os_zalloc(sizeof(*radio));
6422 if (radio == NULL)
6423 return NULL;
6424
6425 if (rn)
6426 os_strlcpy(radio->name, rn, sizeof(radio->name));
6427 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006428 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006429 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6430
6431 return radio;
6432}
6433
6434
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006435static void radio_work_free(struct wpa_radio_work *work)
6436{
6437 if (work->wpa_s->scan_work == work) {
6438 /* This should not really happen. */
6439 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6440 work->type, work, work->started);
6441 work->wpa_s->scan_work = NULL;
6442 }
6443
6444#ifdef CONFIG_P2P
6445 if (work->wpa_s->p2p_scan_work == work) {
6446 /* This should not really happen. */
6447 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6448 work->type, work, work->started);
6449 work->wpa_s->p2p_scan_work = NULL;
6450 }
6451#endif /* CONFIG_P2P */
6452
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006453 if (work->started) {
6454 work->wpa_s->radio->num_active_works--;
6455 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006456 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006457 work->type, work,
6458 work->wpa_s->radio->num_active_works);
6459 }
6460
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006461 dl_list_del(&work->list);
6462 os_free(work);
6463}
6464
6465
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006466static int radio_work_is_connect(struct wpa_radio_work *work)
6467{
6468 return os_strcmp(work->type, "sme-connect") == 0 ||
6469 os_strcmp(work->type, "connect") == 0;
6470}
6471
6472
6473static int radio_work_is_scan(struct wpa_radio_work *work)
6474{
6475 return os_strcmp(work->type, "scan") == 0 ||
6476 os_strcmp(work->type, "p2p-scan") == 0;
6477}
6478
6479
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006480static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6481{
6482 struct wpa_radio_work *active_work = NULL;
6483 struct wpa_radio_work *tmp;
6484
6485 /* Get the active work to know the type and band. */
6486 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6487 if (tmp->started) {
6488 active_work = tmp;
6489 break;
6490 }
6491 }
6492
6493 if (!active_work) {
6494 /* No active work, start one */
6495 radio->num_active_works = 0;
6496 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6497 list) {
6498 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006499 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006500 (((struct wpa_driver_scan_params *)
6501 tmp->ctx)->only_new_results ||
6502 tmp->wpa_s->clear_driver_scan_cache))
6503 continue;
6504 return tmp;
6505 }
6506 return NULL;
6507 }
6508
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006509 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006510 /*
6511 * If the active work is either connect or sme-connect,
6512 * do not parallelize them with other radio works.
6513 */
6514 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6515 "Do not parallelize radio work with %s",
6516 active_work->type);
6517 return NULL;
6518 }
6519
6520 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6521 if (tmp->started)
6522 continue;
6523
6524 /*
6525 * If connect or sme-connect are enqueued, parallelize only
6526 * those operations ahead of them in the queue.
6527 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006528 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006529 break;
6530
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006531 /* Serialize parallel scan and p2p_scan operations on the same
6532 * interface since the driver_nl80211 mechanism for tracking
6533 * scan cookies does not yet have support for this. */
6534 if (active_work->wpa_s == tmp->wpa_s &&
6535 radio_work_is_scan(active_work) &&
6536 radio_work_is_scan(tmp)) {
6537 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6538 "Do not start work '%s' when another work '%s' is already scheduled",
6539 tmp->type, active_work->type);
6540 continue;
6541 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006542 /*
6543 * Check that the radio works are distinct and
6544 * on different bands.
6545 */
6546 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6547 (active_work->bands != tmp->bands)) {
6548 /*
6549 * If a scan has to be scheduled through nl80211 scan
6550 * interface and if an external scan is already running,
6551 * do not schedule the scan since it is likely to get
6552 * rejected by kernel.
6553 */
6554 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006555 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006556 (((struct wpa_driver_scan_params *)
6557 tmp->ctx)->only_new_results ||
6558 tmp->wpa_s->clear_driver_scan_cache))
6559 continue;
6560
6561 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6562 "active_work:%s new_work:%s",
6563 active_work->type, tmp->type);
6564 return tmp;
6565 }
6566 }
6567
6568 /* Did not find a radio work to schedule in parallel. */
6569 return NULL;
6570}
6571
6572
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006573static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6574{
6575 struct wpa_radio *radio = eloop_ctx;
6576 struct wpa_radio_work *work;
6577 struct os_reltime now, diff;
6578 struct wpa_supplicant *wpa_s;
6579
6580 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006581 if (work == NULL) {
6582 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006583 return;
6584 }
6585
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006586 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6587 radio_list);
6588
6589 if (!(wpa_s &&
6590 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6591 if (work->started)
6592 return; /* already started and still in progress */
6593
Hai Shalom60840252021-02-19 19:02:11 -08006594 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006595 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6596 return;
6597 }
6598 } else {
6599 work = NULL;
6600 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6601 /* get the work to schedule next */
6602 work = radio_work_get_next_work(radio);
6603 }
6604 if (!work)
6605 return;
6606 }
6607
6608 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006609 os_get_reltime(&now);
6610 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006611 wpa_dbg(wpa_s, MSG_DEBUG,
6612 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006613 work->type, work, diff.sec, diff.usec);
6614 work->started = 1;
6615 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006616 radio->num_active_works++;
6617
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006618 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006619
6620 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6621 radio->num_active_works < MAX_ACTIVE_WORKS)
6622 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006623}
6624
6625
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006626/*
6627 * This function removes both started and pending radio works running on
6628 * the provided interface's radio.
6629 * Prior to the removal of the radio work, its callback (cb) is called with
6630 * deinit set to be 1. Each work's callback is responsible for clearing its
6631 * internal data and restoring to a correct state.
6632 * @wpa_s: wpa_supplicant data
6633 * @type: type of works to be removed
6634 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6635 * this interface's works.
6636 */
6637void radio_remove_works(struct wpa_supplicant *wpa_s,
6638 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006639{
6640 struct wpa_radio_work *work, *tmp;
6641 struct wpa_radio *radio = wpa_s->radio;
6642
6643 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6644 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006645 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006646 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006647
6648 /* skip other ifaces' works */
6649 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006650 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006651
6652 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6653 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006654 work->cb(work, 1);
6655 radio_work_free(work);
6656 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006657
6658 /* in case we removed the started work */
6659 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006660}
6661
6662
Roshan Pius3a1667e2018-07-03 15:17:14 -07006663void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6664{
6665 struct wpa_radio_work *work;
6666 struct wpa_radio *radio = wpa_s->radio;
6667
6668 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6669 if (work->ctx != ctx)
6670 continue;
6671 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6672 work->type, work, work->started ? " (started)" : "");
6673 radio_work_free(work);
6674 break;
6675 }
6676}
6677
6678
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006679static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6680{
6681 struct wpa_radio *radio = wpa_s->radio;
6682
6683 if (!radio)
6684 return;
6685
6686 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6687 wpa_s->ifname, radio->name);
6688 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006689 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006690 /* If the interface that triggered the external scan was removed, the
6691 * external scan is no longer running. */
6692 if (wpa_s == radio->external_scan_req_interface)
6693 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006694 wpa_s->radio = NULL;
6695 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006696 return; /* Interfaces remain for this radio */
6697
6698 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006699 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006700 os_free(radio);
6701}
6702
6703
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006704void radio_work_check_next(struct wpa_supplicant *wpa_s)
6705{
6706 struct wpa_radio *radio = wpa_s->radio;
6707
6708 if (dl_list_empty(&radio->work))
6709 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006710 if (wpa_s->ext_work_in_progress) {
6711 wpa_printf(MSG_DEBUG,
6712 "External radio work in progress - delay start of pending item");
6713 return;
6714 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006715 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6716 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6717}
6718
6719
6720/**
6721 * radio_add_work - Add a radio work item
6722 * @wpa_s: Pointer to wpa_supplicant data
6723 * @freq: Frequency of the offchannel operation in MHz or 0
6724 * @type: Unique identifier for each type of work
6725 * @next: Force as the next work to be executed
6726 * @cb: Callback function for indicating when radio is available
6727 * @ctx: Context pointer for the work (work->ctx in cb())
6728 * Returns: 0 on success, -1 on failure
6729 *
6730 * This function is used to request time for an operation that requires
6731 * exclusive radio control. Once the radio is available, the registered callback
6732 * function will be called. radio_work_done() must be called once the exclusive
6733 * radio operation has been completed, so that the radio is freed for other
6734 * operations. The special case of deinit=1 is used to free the context data
6735 * during interface removal. That does not allow the callback function to start
6736 * the radio operation, i.e., it must free any resources allocated for the radio
6737 * work and return.
6738 *
6739 * The @freq parameter can be used to indicate a single channel on which the
6740 * offchannel operation will occur. This may allow multiple radio work
6741 * operations to be performed in parallel if they apply for the same channel.
6742 * Setting this to 0 indicates that the work item may use multiple channels or
6743 * requires exclusive control of the radio.
6744 */
6745int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6746 const char *type, int next,
6747 void (*cb)(struct wpa_radio_work *work, int deinit),
6748 void *ctx)
6749{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006750 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006751 struct wpa_radio_work *work;
6752 int was_empty;
6753
6754 work = os_zalloc(sizeof(*work));
6755 if (work == NULL)
6756 return -1;
6757 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6758 os_get_reltime(&work->time);
6759 work->freq = freq;
6760 work->type = type;
6761 work->wpa_s = wpa_s;
6762 work->cb = cb;
6763 work->ctx = ctx;
6764
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006765 if (freq)
6766 work->bands = wpas_freq_to_band(freq);
6767 else if (os_strcmp(type, "scan") == 0 ||
6768 os_strcmp(type, "p2p-scan") == 0)
6769 work->bands = wpas_get_bands(wpa_s,
6770 ((struct wpa_driver_scan_params *)
6771 ctx)->freqs);
6772 else
6773 work->bands = wpas_get_bands(wpa_s, NULL);
6774
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006775 was_empty = dl_list_empty(&wpa_s->radio->work);
6776 if (next)
6777 dl_list_add(&wpa_s->radio->work, &work->list);
6778 else
6779 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6780 if (was_empty) {
6781 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6782 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006783 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6784 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6785 wpa_dbg(wpa_s, MSG_DEBUG,
6786 "Try to schedule a radio work (num_active_works=%u)",
6787 radio->num_active_works);
6788 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006789 }
6790
6791 return 0;
6792}
6793
6794
6795/**
6796 * radio_work_done - Indicate that a radio work item has been completed
6797 * @work: Completed work
6798 *
6799 * This function is called once the callback function registered with
6800 * radio_add_work() has completed its work.
6801 */
6802void radio_work_done(struct wpa_radio_work *work)
6803{
6804 struct wpa_supplicant *wpa_s = work->wpa_s;
6805 struct os_reltime now, diff;
6806 unsigned int started = work->started;
6807
6808 os_get_reltime(&now);
6809 os_reltime_sub(&now, &work->time, &diff);
6810 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6811 work->type, work, started ? "done" : "canceled",
6812 diff.sec, diff.usec);
6813 radio_work_free(work);
6814 if (started)
6815 radio_work_check_next(wpa_s);
6816}
6817
6818
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006819struct wpa_radio_work *
6820radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006821{
6822 struct wpa_radio_work *work;
6823 struct wpa_radio *radio = wpa_s->radio;
6824
6825 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6826 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006827 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006828 }
6829
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006830 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006831}
6832
6833
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006834static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006835 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006836{
6837 const char *ifname, *driver, *rn;
6838
6839 driver = iface->driver;
6840next_driver:
6841 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6842 return -1;
6843
6844 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6845 if (wpa_s->drv_priv == NULL) {
6846 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006847 int level = MSG_ERROR;
6848
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006849 pos = driver ? os_strchr(driver, ',') : NULL;
6850 if (pos) {
6851 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6852 "driver interface - try next driver wrapper");
6853 driver = pos + 1;
6854 goto next_driver;
6855 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006856
6857#ifdef CONFIG_MATCH_IFACE
6858 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6859 level = MSG_DEBUG;
6860#endif /* CONFIG_MATCH_IFACE */
6861 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006862 return -1;
6863 }
6864 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6865 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6866 "driver_param '%s'", wpa_s->conf->driver_param);
6867 return -1;
6868 }
6869
6870 ifname = wpa_drv_get_ifname(wpa_s);
6871 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6872 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6873 "interface name with '%s'", ifname);
6874 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6875 }
6876
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006877 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006878 if (rn && rn[0] == '\0')
6879 rn = NULL;
6880
6881 wpa_s->radio = radio_add_interface(wpa_s, rn);
6882 if (wpa_s->radio == NULL)
6883 return -1;
6884
6885 return 0;
6886}
6887
6888
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006889#ifdef CONFIG_GAS_SERVER
6890
6891static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6892 unsigned int freq, const u8 *dst,
6893 const u8 *src, const u8 *bssid,
6894 const u8 *data, size_t data_len,
6895 enum offchannel_send_action_result result)
6896{
6897 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6898 " result=%s",
6899 freq, MAC2STR(dst),
6900 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6901 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6902 "FAILED"));
6903 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6904 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6905}
6906
6907
6908static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6909 struct wpabuf *buf, unsigned int wait_time)
6910{
6911 struct wpa_supplicant *wpa_s = ctx;
6912 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6913
6914 if (wait_time > wpa_s->max_remain_on_chan)
6915 wait_time = wpa_s->max_remain_on_chan;
6916
6917 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6918 wpabuf_head(buf), wpabuf_len(buf),
6919 wait_time, wpas_gas_server_tx_status, 0);
6920}
6921
6922#endif /* CONFIG_GAS_SERVER */
6923
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006924static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006925 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006926{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006927 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006928 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006929 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006930
6931 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6932 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6933 iface->confname ? iface->confname : "N/A",
6934 iface->driver ? iface->driver : "default",
6935 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6936 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6937
6938 if (iface->confname) {
6939#ifdef CONFIG_BACKEND_FILE
6940 wpa_s->confname = os_rel2abs_path(iface->confname);
6941 if (wpa_s->confname == NULL) {
6942 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6943 "for configuration file '%s'.",
6944 iface->confname);
6945 return -1;
6946 }
6947 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6948 iface->confname, wpa_s->confname);
6949#else /* CONFIG_BACKEND_FILE */
6950 wpa_s->confname = os_strdup(iface->confname);
6951#endif /* CONFIG_BACKEND_FILE */
Sunil Ravi77d572f2023-01-17 23:58:31 +00006952 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006953 if (wpa_s->conf == NULL) {
6954 wpa_printf(MSG_ERROR, "Failed to read or parse "
6955 "configuration '%s'.", wpa_s->confname);
6956 return -1;
6957 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006958 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006959 if (wpa_s->confanother &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00006960 !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006961 wpa_printf(MSG_ERROR,
6962 "Failed to read or parse configuration '%s'.",
6963 wpa_s->confanother);
6964 return -1;
6965 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006966
6967 /*
6968 * Override ctrl_interface and driver_param if set on command
6969 * line.
6970 */
6971 if (iface->ctrl_interface) {
6972 os_free(wpa_s->conf->ctrl_interface);
6973 wpa_s->conf->ctrl_interface =
6974 os_strdup(iface->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006975 if (!wpa_s->conf->ctrl_interface) {
6976 wpa_printf(MSG_ERROR,
6977 "Failed to duplicate control interface '%s'.",
6978 iface->ctrl_interface);
6979 return -1;
6980 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006981 }
6982
6983 if (iface->driver_param) {
6984 os_free(wpa_s->conf->driver_param);
6985 wpa_s->conf->driver_param =
6986 os_strdup(iface->driver_param);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006987 if (!wpa_s->conf->driver_param) {
6988 wpa_printf(MSG_ERROR,
6989 "Failed to duplicate driver param '%s'.",
6990 iface->driver_param);
6991 return -1;
6992 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006993 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006994
6995 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6996 os_free(wpa_s->conf->ctrl_interface);
6997 wpa_s->conf->ctrl_interface = NULL;
6998 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006999 } else
7000 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
7001 iface->driver_param);
7002
7003 if (wpa_s->conf == NULL) {
7004 wpa_printf(MSG_ERROR, "\nNo configuration found.");
7005 return -1;
7006 }
7007
7008 if (iface->ifname == NULL) {
7009 wpa_printf(MSG_ERROR, "\nInterface name is required.");
7010 return -1;
7011 }
7012 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
7013 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
7014 iface->ifname);
7015 return -1;
7016 }
7017 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07007018#ifdef CONFIG_MATCH_IFACE
7019 wpa_s->matched = iface->matched;
7020#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007021
7022 if (iface->bridge_ifname) {
7023 if (os_strlen(iface->bridge_ifname) >=
7024 sizeof(wpa_s->bridge_ifname)) {
7025 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
7026 "name '%s'.", iface->bridge_ifname);
7027 return -1;
7028 }
7029 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
7030 sizeof(wpa_s->bridge_ifname));
7031 }
7032
7033 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07007034 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
7035 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007036
7037 /* Initialize driver interface and register driver event handler before
7038 * L2 receive handler so that association events are processed before
7039 * EAPOL-Key packets if both become available for the same select()
7040 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007041 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007042 return -1;
7043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007044 if (wpa_supplicant_init_wpa(wpa_s) < 0)
7045 return -1;
7046
7047 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
7048 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
7049 NULL);
7050 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
7051
7052 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
7053 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
7054 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
7055 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7056 "dot11RSNAConfigPMKLifetime");
7057 return -1;
7058 }
7059
7060 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
7061 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
7062 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
7063 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7064 "dot11RSNAConfigPMKReauthThreshold");
7065 return -1;
7066 }
7067
7068 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
7069 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
7070 wpa_s->conf->dot11RSNAConfigSATimeout)) {
7071 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
7072 "dot11RSNAConfigSATimeout");
7073 return -1;
7074 }
7075
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007076 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
7077 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007078 &wpa_s->hw.flags,
7079 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007080 if (wpa_s->hw.modes) {
7081 u16 i;
7082
7083 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7084 if (wpa_s->hw.modes[i].vht_capab) {
7085 wpa_s->hw_capab = CAPAB_VHT;
7086 break;
7087 }
7088
7089 if (wpa_s->hw.modes[i].ht_capab &
7090 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
7091 wpa_s->hw_capab = CAPAB_HT40;
7092 else if (wpa_s->hw.modes[i].ht_capab &&
7093 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
7094 wpa_s->hw_capab = CAPAB_HT;
7095 }
7096 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007097
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007098 capa_res = wpa_drv_get_capa(wpa_s, &capa);
7099 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007100 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007101 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07007102 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007103 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007104 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07007105 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007106 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007107 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007108 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007109 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
7110 wpa_s->max_sched_scan_plan_interval =
7111 capa.max_sched_scan_plan_interval;
7112 wpa_s->max_sched_scan_plan_iterations =
7113 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007114 wpa_s->sched_scan_supported = capa.sched_scan_supported;
7115 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007116 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
7117 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007118 wpa_s->extended_capa = capa.extended_capa;
7119 wpa_s->extended_capa_mask = capa.extended_capa_mask;
7120 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007121 wpa_s->num_multichan_concurrent =
7122 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007123 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07007124 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007125
7126 if (capa.mac_addr_rand_scan_supported)
7127 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
7128 if (wpa_s->sched_scan_supported &&
7129 capa.mac_addr_rand_sched_scan_supported)
7130 wpa_s->mac_addr_rand_supported |=
7131 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08007132
7133 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
7134 if (wpa_s->extended_capa &&
7135 wpa_s->extended_capa_len >= 3 &&
7136 wpa_s->extended_capa[2] & 0x40)
7137 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007138 }
Sunil Ravi89eba102022-09-13 21:04:37 -07007139#ifdef CONFIG_PASN
7140 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
7141#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007142 if (wpa_s->max_remain_on_chan == 0)
7143 wpa_s->max_remain_on_chan = 1000;
7144
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007145 /*
7146 * Only take p2p_mgmt parameters when P2P Device is supported.
7147 * Doing it here as it determines whether l2_packet_init() will be done
7148 * during wpa_supplicant_driver_init().
7149 */
7150 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
7151 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007152
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007153 if (wpa_s->num_multichan_concurrent == 0)
7154 wpa_s->num_multichan_concurrent = 1;
7155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007156 if (wpa_supplicant_driver_init(wpa_s) < 0)
7157 return -1;
7158
7159#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07007160 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007161 return -1;
7162#endif /* CONFIG_TDLS */
7163
7164 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
7165 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
7166 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
7167 return -1;
7168 }
7169
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007170#ifdef CONFIG_FST
7171 if (wpa_s->conf->fst_group_id) {
7172 struct fst_iface_cfg cfg;
7173 struct fst_wpa_obj iface_obj;
7174
7175 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
7176 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
7177 sizeof(cfg.group_id));
7178 cfg.priority = wpa_s->conf->fst_priority;
7179 cfg.llt = wpa_s->conf->fst_llt;
7180
7181 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
7182 &iface_obj, &cfg);
7183 if (!wpa_s->fst) {
7184 wpa_msg(wpa_s, MSG_ERROR,
7185 "FST: Cannot attach iface %s to group %s",
7186 wpa_s->ifname, cfg.group_id);
7187 return -1;
7188 }
7189 }
7190#endif /* CONFIG_FST */
7191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007192 if (wpas_wps_init(wpa_s))
7193 return -1;
7194
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007195#ifdef CONFIG_GAS_SERVER
7196 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7197 if (!wpa_s->gas_server) {
7198 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7199 return -1;
7200 }
7201#endif /* CONFIG_GAS_SERVER */
7202
7203#ifdef CONFIG_DPP
7204 if (wpas_dpp_init(wpa_s) < 0)
7205 return -1;
7206#endif /* CONFIG_DPP */
7207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007208 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7209 return -1;
7210 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7211
7212 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7213 if (wpa_s->ctrl_iface == NULL) {
7214 wpa_printf(MSG_ERROR,
7215 "Failed to initialize control interface '%s'.\n"
7216 "You may have another wpa_supplicant process "
7217 "already running or the file was\n"
7218 "left by an unclean termination of wpa_supplicant "
7219 "in which case you will need\n"
7220 "to manually remove this file before starting "
7221 "wpa_supplicant again.\n",
7222 wpa_s->conf->ctrl_interface);
7223 return -1;
7224 }
7225
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007226 wpa_s->gas = gas_query_init(wpa_s);
7227 if (wpa_s->gas == NULL) {
7228 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7229 return -1;
7230 }
7231
Roshan Pius3a1667e2018-07-03 15:17:14 -07007232 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7233 wpa_s->p2p_mgmt) &&
7234 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007235 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7236 return -1;
7237 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007238
7239 if (wpa_bss_init(wpa_s) < 0)
7240 return -1;
7241
Paul Stewart092955c2017-02-06 09:13:09 -08007242#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7243#ifdef CONFIG_MESH
7244 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7245#endif /* CONFIG_MESH */
7246#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7247
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007248 /*
7249 * Set Wake-on-WLAN triggers, if configured.
7250 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7251 * have effect anyway when the interface is down).
7252 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007253 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007254 return -1;
7255
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007256#ifdef CONFIG_EAP_PROXY
7257{
7258 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007259 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7260 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007261 if (wpa_s->mnc_len > 0) {
7262 wpa_s->imsi[len] = '\0';
7263 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7264 wpa_s->imsi, wpa_s->mnc_len);
7265 } else {
7266 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7267 }
7268}
7269#endif /* CONFIG_EAP_PROXY */
7270
Dmitry Shmidt04949592012-07-19 12:16:46 -07007271 if (pcsc_reader_init(wpa_s) < 0)
7272 return -1;
7273
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007274 if (wpas_init_ext_pw(wpa_s) < 0)
7275 return -1;
7276
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007277 wpas_rrm_reset(wpa_s);
7278
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007279 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7280
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007281#ifdef CONFIG_HS20
7282 hs20_init(wpa_s);
7283#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007284#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007285 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007286 if ((wpa_s->conf->oce & OCE_STA) &&
7287 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7288 wpa_s->enable_oce = OCE_STA;
7289 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7290 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7291 /* TODO: Need to add STA-CFON support */
7292 wpa_printf(MSG_ERROR,
7293 "OCE STA-CFON feature is not yet supported");
7294 }
7295 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007296 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7297#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007298
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007299 wpa_supplicant_set_default_scan_ies(wpa_s);
7300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007301 return 0;
7302}
7303
7304
7305static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007306 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007307{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007308 struct wpa_global *global = wpa_s->global;
7309 struct wpa_supplicant *iface, *prev;
7310
Jimmy Chen0e73c002021-08-18 13:21:30 +08007311 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007312 wpas_p2p_group_remove(wpa_s, "*");
7313
7314 iface = global->ifaces;
7315 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007316 if (iface->p2pdev == wpa_s)
7317 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007318 if (iface == wpa_s || iface->parent != wpa_s) {
7319 iface = iface->next;
7320 continue;
7321 }
7322 wpa_printf(MSG_DEBUG,
7323 "Remove remaining child interface %s from parent %s",
7324 iface->ifname, wpa_s->ifname);
7325 prev = iface;
7326 iface = iface->next;
7327 wpa_supplicant_remove_iface(global, prev, terminate);
7328 }
7329
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007330 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007331 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007332 /*
7333 * Don't deauthenticate if WoWLAN is enable and not explicitly
7334 * been configured to disconnect.
7335 */
7336 if (!wpa_drv_get_wowlan(wpa_s) ||
7337 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007338 wpa_supplicant_deauthenticate(
7339 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007340
Hai Shalomfdcde762020-04-02 11:19:20 -07007341 wpa_drv_set_countermeasures(wpa_s, 0);
7342 wpa_clear_keys(wpa_s, NULL);
7343 } else {
7344 wpa_msg(wpa_s, MSG_INFO,
7345 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7346 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007347 }
7348
7349 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007350 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007351
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007352 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007353 radio_remove_interface(wpa_s);
7354
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007355#ifdef CONFIG_FST
7356 if (wpa_s->fst) {
7357 fst_detach(wpa_s->fst);
7358 wpa_s->fst = NULL;
7359 }
7360 if (wpa_s->received_mb_ies) {
7361 wpabuf_free(wpa_s->received_mb_ies);
7362 wpa_s->received_mb_ies = NULL;
7363 }
7364#endif /* CONFIG_FST */
7365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007366 if (wpa_s->drv_priv)
7367 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007368
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007369 if (notify)
7370 wpas_notify_iface_removed(wpa_s);
7371
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007372 if (terminate)
7373 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007374
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007375 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7376 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007377
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007378#ifdef CONFIG_MESH
7379 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007380 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007381 wpa_s->ifmsh = NULL;
7382 }
7383#endif /* CONFIG_MESH */
7384
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007385 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007386 wpa_config_free(wpa_s->conf);
7387 wpa_s->conf = NULL;
7388 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007389
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007390 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007391 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007392
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007393 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007394}
7395
7396
Dmitry Shmidte4663042016-04-04 10:07:49 -07007397#ifdef CONFIG_MATCH_IFACE
7398
7399/**
7400 * wpa_supplicant_match_iface - Match an interface description to a name
7401 * @global: Pointer to global data from wpa_supplicant_init()
7402 * @ifname: Name of the interface to match
7403 * Returns: Pointer to the created interface description or %NULL on failure
7404 */
7405struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7406 const char *ifname)
7407{
7408 int i;
7409 struct wpa_interface *iface, *miface;
7410
7411 for (i = 0; i < global->params.match_iface_count; i++) {
7412 miface = &global->params.match_ifaces[i];
7413 if (!miface->ifname ||
7414 fnmatch(miface->ifname, ifname, 0) == 0) {
7415 iface = os_zalloc(sizeof(*iface));
7416 if (!iface)
7417 return NULL;
7418 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007419 if (!miface->ifname)
7420 iface->matched = WPA_IFACE_MATCHED_NULL;
7421 else
7422 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007423 iface->ifname = ifname;
7424 return iface;
7425 }
7426 }
7427
7428 return NULL;
7429}
7430
7431
7432/**
7433 * wpa_supplicant_match_existing - Match existing interfaces
7434 * @global: Pointer to global data from wpa_supplicant_init()
7435 * Returns: 0 on success, -1 on failure
7436 */
7437static int wpa_supplicant_match_existing(struct wpa_global *global)
7438{
7439 struct if_nameindex *ifi, *ifp;
7440 struct wpa_supplicant *wpa_s;
7441 struct wpa_interface *iface;
7442
7443 ifp = if_nameindex();
7444 if (!ifp) {
7445 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7446 return -1;
7447 }
7448
7449 for (ifi = ifp; ifi->if_name; ifi++) {
7450 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7451 if (wpa_s)
7452 continue;
7453 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7454 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007455 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007456 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007457 }
7458 }
7459
7460 if_freenameindex(ifp);
7461 return 0;
7462}
7463
7464#endif /* CONFIG_MATCH_IFACE */
7465
7466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467/**
7468 * wpa_supplicant_add_iface - Add a new network interface
7469 * @global: Pointer to global data from wpa_supplicant_init()
7470 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007471 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007472 * Returns: Pointer to the created interface or %NULL on failure
7473 *
7474 * This function is used to add new network interfaces for %wpa_supplicant.
7475 * This can be called before wpa_supplicant_run() to add interfaces before the
7476 * main event loop has been started. In addition, new interfaces can be added
7477 * dynamically while %wpa_supplicant is already running. This could happen,
7478 * e.g., when a hotplug network adapter is inserted.
7479 */
7480struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007481 struct wpa_interface *iface,
7482 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483{
7484 struct wpa_supplicant *wpa_s;
7485 struct wpa_interface t_iface;
7486 struct wpa_ssid *ssid;
7487
7488 if (global == NULL || iface == NULL)
7489 return NULL;
7490
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007491 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007492 if (wpa_s == NULL)
7493 return NULL;
7494
7495 wpa_s->global = global;
7496
7497 t_iface = *iface;
7498 if (global->params.override_driver) {
7499 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7500 "('%s' -> '%s')",
7501 iface->driver, global->params.override_driver);
7502 t_iface.driver = global->params.override_driver;
7503 }
7504 if (global->params.override_ctrl_interface) {
7505 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7506 "ctrl_interface ('%s' -> '%s')",
7507 iface->ctrl_interface,
7508 global->params.override_ctrl_interface);
7509 t_iface.ctrl_interface =
7510 global->params.override_ctrl_interface;
7511 }
7512 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7513 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7514 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007515 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007516 return NULL;
7517 }
7518
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007519 /* Notify the control interfaces about new iface */
7520 if (wpas_notify_iface_added(wpa_s)) {
7521 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7522 return NULL;
7523 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007524
Jimmy Chene2206be2022-07-10 10:25:21 +08007525 /* Notify the control interfaces about new networks */
7526 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7527 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007528 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007529 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7530 && os_strncmp((const char *) ssid->ssid,
7531 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7532 wpas_notify_persistent_group_added(wpa_s, ssid);
7533 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007534 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007535
7536 wpa_s->next = global->ifaces;
7537 global->ifaces = wpa_s;
7538
7539 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007540 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007541
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007542#ifdef CONFIG_P2P
7543 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007544 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007545 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007546 wpas_p2p_add_p2pdev_interface(
7547 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007548 wpa_printf(MSG_INFO,
7549 "P2P: Failed to enable P2P Device interface");
7550 /* Try to continue without. P2P will be disabled. */
7551 }
7552#endif /* CONFIG_P2P */
7553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007554 return wpa_s;
7555}
7556
7557
7558/**
7559 * wpa_supplicant_remove_iface - Remove a network interface
7560 * @global: Pointer to global data from wpa_supplicant_init()
7561 * @wpa_s: Pointer to the network interface to be removed
7562 * Returns: 0 if interface was removed, -1 if interface was not found
7563 *
7564 * This function can be used to dynamically remove network interfaces from
7565 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7566 * addition, this function is used to remove all remaining interfaces when
7567 * %wpa_supplicant is terminated.
7568 */
7569int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007570 struct wpa_supplicant *wpa_s,
7571 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007572{
7573 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007574#ifdef CONFIG_MESH
7575 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7576 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007577 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007578#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007579
7580 /* Remove interface from the global list of interfaces */
7581 prev = global->ifaces;
7582 if (prev == wpa_s) {
7583 global->ifaces = wpa_s->next;
7584 } else {
7585 while (prev && prev->next != wpa_s)
7586 prev = prev->next;
7587 if (prev == NULL)
7588 return -1;
7589 prev->next = wpa_s->next;
7590 }
7591
7592 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7593
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007594#ifdef CONFIG_MESH
7595 if (mesh_if_created) {
7596 ifname = os_strdup(wpa_s->ifname);
7597 if (ifname == NULL) {
7598 wpa_dbg(wpa_s, MSG_ERROR,
7599 "mesh: Failed to malloc ifname");
7600 return -1;
7601 }
7602 }
7603#endif /* CONFIG_MESH */
7604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007605 if (global->p2p_group_formation == wpa_s)
7606 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007607 if (global->p2p_invite_group == wpa_s)
7608 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007609 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007610
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007611#ifdef CONFIG_MESH
7612 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007613 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007614 os_free(ifname);
7615 }
7616#endif /* CONFIG_MESH */
7617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007618 return 0;
7619}
7620
7621
7622/**
7623 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7624 * @wpa_s: Pointer to the network interface
7625 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7626 */
7627const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7628{
7629 const char *eapol_method;
7630
7631 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7632 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7633 return "NO-EAP";
7634 }
7635
7636 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7637 if (eapol_method == NULL)
7638 return "UNKNOWN-EAP";
7639
7640 return eapol_method;
7641}
7642
7643
7644/**
7645 * wpa_supplicant_get_iface - Get a new network interface
7646 * @global: Pointer to global data from wpa_supplicant_init()
7647 * @ifname: Interface name
7648 * Returns: Pointer to the interface or %NULL if not found
7649 */
7650struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7651 const char *ifname)
7652{
7653 struct wpa_supplicant *wpa_s;
7654
7655 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7656 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7657 return wpa_s;
7658 }
7659 return NULL;
7660}
7661
7662
7663#ifndef CONFIG_NO_WPA_MSG
7664static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7665{
7666 struct wpa_supplicant *wpa_s = ctx;
7667 if (wpa_s == NULL)
7668 return NULL;
7669 return wpa_s->ifname;
7670}
7671#endif /* CONFIG_NO_WPA_MSG */
7672
7673
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007674#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7675#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7676#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7677
7678/* Periodic cleanup tasks */
7679static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7680{
7681 struct wpa_global *global = eloop_ctx;
7682 struct wpa_supplicant *wpa_s;
7683
7684 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7685 wpas_periodic, global, NULL);
7686
7687#ifdef CONFIG_P2P
7688 if (global->p2p)
7689 p2p_expire_peers(global->p2p);
7690#endif /* CONFIG_P2P */
7691
7692 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7693 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7694#ifdef CONFIG_AP
7695 ap_periodic(wpa_s);
7696#endif /* CONFIG_AP */
7697 }
7698}
7699
7700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007701/**
7702 * wpa_supplicant_init - Initialize %wpa_supplicant
7703 * @params: Parameters for %wpa_supplicant
7704 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7705 *
7706 * This function is used to initialize %wpa_supplicant. After successful
7707 * initialization, the returned data pointer can be used to add and remove
7708 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7709 */
7710struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7711{
7712 struct wpa_global *global;
7713 int ret, i;
7714
7715 if (params == NULL)
7716 return NULL;
7717
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007718#ifdef CONFIG_DRIVER_NDIS
7719 {
7720 void driver_ndis_init_ops(void);
7721 driver_ndis_init_ops();
7722 }
7723#endif /* CONFIG_DRIVER_NDIS */
7724
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007725#ifndef CONFIG_NO_WPA_MSG
7726 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7727#endif /* CONFIG_NO_WPA_MSG */
7728
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007729 if (params->wpa_debug_file_path)
7730 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007731 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007732 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007733 if (params->wpa_debug_syslog)
7734 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007735 if (params->wpa_debug_tracing) {
7736 ret = wpa_debug_open_linux_tracing();
7737 if (ret) {
7738 wpa_printf(MSG_ERROR,
7739 "Failed to enable trace logging");
7740 return NULL;
7741 }
7742 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007743
7744 ret = eap_register_methods();
7745 if (ret) {
7746 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7747 if (ret == -2)
7748 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7749 "the same EAP type.");
7750 return NULL;
7751 }
7752
7753 global = os_zalloc(sizeof(*global));
7754 if (global == NULL)
7755 return NULL;
7756 dl_list_init(&global->p2p_srv_bonjour);
7757 dl_list_init(&global->p2p_srv_upnp);
7758 global->params.daemonize = params->daemonize;
7759 global->params.wait_for_monitor = params->wait_for_monitor;
7760 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
Sunil Ravi77d572f2023-01-17 23:58:31 +00007761
7762 if (params->pid_file) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007763 global->params.pid_file = os_strdup(params->pid_file);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007764 if (!global->params.pid_file) {
7765 wpa_supplicant_deinit(global);
7766 return NULL;
7767 }
7768 }
7769
7770 if (params->ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771 global->params.ctrl_interface =
7772 os_strdup(params->ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007773 if (!global->params.ctrl_interface) {
7774 wpa_supplicant_deinit(global);
7775 return NULL;
7776 }
7777 }
7778
7779 if (params->ctrl_interface_group) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007780 global->params.ctrl_interface_group =
7781 os_strdup(params->ctrl_interface_group);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007782 if (!global->params.ctrl_interface_group) {
7783 wpa_supplicant_deinit(global);
7784 return NULL;
7785 }
7786 }
7787
7788 if (params->override_driver) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007789 global->params.override_driver =
7790 os_strdup(params->override_driver);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007791 if (!global->params.override_driver) {
7792 wpa_supplicant_deinit(global);
7793 return NULL;
7794 }
7795 }
7796
7797 if (params->override_ctrl_interface) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007798 global->params.override_ctrl_interface =
7799 os_strdup(params->override_ctrl_interface);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007800 if (!global->params.override_ctrl_interface) {
7801 wpa_supplicant_deinit(global);
7802 return NULL;
7803 }
7804 }
7805
Dmitry Shmidte4663042016-04-04 10:07:49 -07007806#ifdef CONFIG_MATCH_IFACE
7807 global->params.match_iface_count = params->match_iface_count;
7808 if (params->match_iface_count) {
7809 global->params.match_ifaces =
7810 os_calloc(params->match_iface_count,
7811 sizeof(struct wpa_interface));
Sunil Ravi77d572f2023-01-17 23:58:31 +00007812 if (!global->params.match_ifaces) {
7813 wpa_printf(MSG_ERROR,
7814 "Failed to allocate match interfaces");
7815 wpa_supplicant_deinit(global);
7816 return NULL;
7817 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07007818 os_memcpy(global->params.match_ifaces,
7819 params->match_ifaces,
7820 params->match_iface_count *
7821 sizeof(struct wpa_interface));
7822 }
7823#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007824#ifdef CONFIG_P2P
Sunil Ravi77d572f2023-01-17 23:58:31 +00007825 if (params->conf_p2p_dev) {
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007826 global->params.conf_p2p_dev =
7827 os_strdup(params->conf_p2p_dev);
Sunil Ravi77d572f2023-01-17 23:58:31 +00007828 if (!global->params.conf_p2p_dev) {
7829 wpa_printf(MSG_ERROR, "Failed to allocate conf p2p");
7830 wpa_supplicant_deinit(global);
7831 return NULL;
7832 }
7833 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007834#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007835 wpa_debug_level = global->params.wpa_debug_level =
7836 params->wpa_debug_level;
7837 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7838 params->wpa_debug_show_keys;
7839 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7840 params->wpa_debug_timestamp;
7841
Hai Shalomfdcde762020-04-02 11:19:20 -07007842 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007843
7844 if (eloop_init()) {
7845 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7846 wpa_supplicant_deinit(global);
7847 return NULL;
7848 }
7849
Jouni Malinen75ecf522011-06-27 15:19:46 -07007850 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007851
7852 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7853 if (global->ctrl_iface == NULL) {
7854 wpa_supplicant_deinit(global);
7855 return NULL;
7856 }
7857
7858 if (wpas_notify_supplicant_initialized(global)) {
7859 wpa_supplicant_deinit(global);
7860 return NULL;
7861 }
7862
7863 for (i = 0; wpa_drivers[i]; i++)
7864 global->drv_count++;
7865 if (global->drv_count == 0) {
7866 wpa_printf(MSG_ERROR, "No drivers enabled");
7867 wpa_supplicant_deinit(global);
7868 return NULL;
7869 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007870 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007871 if (global->drv_priv == NULL) {
7872 wpa_supplicant_deinit(global);
7873 return NULL;
7874 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007875
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007876#ifdef CONFIG_WIFI_DISPLAY
7877 if (wifi_display_init(global) < 0) {
7878 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7879 wpa_supplicant_deinit(global);
7880 return NULL;
7881 }
7882#endif /* CONFIG_WIFI_DISPLAY */
7883
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007884 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7885 wpas_periodic, global, NULL);
7886
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007887 return global;
7888}
7889
7890
7891/**
7892 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7893 * @global: Pointer to global data from wpa_supplicant_init()
7894 * Returns: 0 after successful event loop run, -1 on failure
7895 *
7896 * This function starts the main event loop and continues running as long as
7897 * there are any remaining events. In most cases, this function is running as
7898 * long as the %wpa_supplicant process in still in use.
7899 */
7900int wpa_supplicant_run(struct wpa_global *global)
7901{
7902 struct wpa_supplicant *wpa_s;
7903
7904 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007905 (wpa_supplicant_daemon(global->params.pid_file) ||
7906 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007907 return -1;
7908
Dmitry Shmidte4663042016-04-04 10:07:49 -07007909#ifdef CONFIG_MATCH_IFACE
7910 if (wpa_supplicant_match_existing(global))
7911 return -1;
7912#endif
7913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007914 if (global->params.wait_for_monitor) {
7915 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007916 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007917 wpa_supplicant_ctrl_iface_wait(
7918 wpa_s->ctrl_iface);
7919 }
7920
7921 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7922 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7923
7924 eloop_run();
7925
7926 return 0;
7927}
7928
7929
7930/**
7931 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7932 * @global: Pointer to global data from wpa_supplicant_init()
7933 *
7934 * This function is called to deinitialize %wpa_supplicant and to free all
7935 * allocated resources. Remaining network interfaces will also be removed.
7936 */
7937void wpa_supplicant_deinit(struct wpa_global *global)
7938{
7939 int i;
7940
7941 if (global == NULL)
7942 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007943
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007944 eloop_cancel_timeout(wpas_periodic, global, NULL);
7945
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007946#ifdef CONFIG_WIFI_DISPLAY
7947 wifi_display_deinit(global);
7948#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007949
7950 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007951 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007952
7953 if (global->ctrl_iface)
7954 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7955
7956 wpas_notify_supplicant_deinitialized(global);
7957
7958 eap_peer_unregister_methods();
7959#ifdef CONFIG_AP
7960 eap_server_unregister_methods();
7961#endif /* CONFIG_AP */
7962
7963 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7964 if (!global->drv_priv[i])
7965 continue;
7966 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7967 }
7968 os_free(global->drv_priv);
7969
7970 random_deinit();
7971
7972 eloop_destroy();
7973
7974 if (global->params.pid_file) {
7975 os_daemonize_terminate(global->params.pid_file);
7976 os_free(global->params.pid_file);
7977 }
7978 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007979 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007980 os_free(global->params.override_driver);
7981 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007982#ifdef CONFIG_MATCH_IFACE
7983 os_free(global->params.match_ifaces);
7984#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007985#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007986 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007987#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007988
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007989 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007990 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007991 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007992
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007993 os_free(global);
7994 wpa_debug_close_syslog();
7995 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007996 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007997}
7998
7999
8000void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
8001{
8002 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8003 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8004 char country[3];
8005 country[0] = wpa_s->conf->country[0];
8006 country[1] = wpa_s->conf->country[1];
8007 country[2] = '\0';
8008 if (wpa_drv_set_country(wpa_s, country) < 0) {
8009 wpa_printf(MSG_ERROR, "Failed to set country code "
8010 "'%s'", country);
8011 }
8012 }
8013
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008014 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
8015 wpas_init_ext_pw(wpa_s);
8016
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008017 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
8018 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
8019
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008020 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
8021 struct wpa_driver_capa capa;
8022 int res = wpa_drv_get_capa(wpa_s, &capa);
8023
8024 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
8025 wpa_printf(MSG_ERROR,
8026 "Failed to update wowlan_triggers to '%s'",
8027 wpa_s->conf->wowlan_triggers);
8028 }
8029
Hai Shalom81f62d82019-07-22 12:10:00 -07008030 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
8031 wpa_supplicant_set_default_scan_ies(wpa_s);
8032
Hai Shalom899fcc72020-10-19 14:38:18 -07008033#ifdef CONFIG_BGSCAN
8034 /*
8035 * We default to global bgscan parameters only when per-network bgscan
8036 * parameters aren't set. Only bother resetting bgscan parameters if
8037 * this is the case.
8038 */
8039 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
8040 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
8041 wpa_s->wpa_state == WPA_COMPLETED)
8042 wpa_supplicant_reset_bgscan(wpa_s);
8043#endif /* CONFIG_BGSCAN */
8044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008045#ifdef CONFIG_WPS
8046 wpas_wps_update_config(wpa_s);
8047#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008048 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008049 wpa_s->conf->changed_parameters = 0;
8050}
8051
8052
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008053void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008054{
8055 int i;
8056
8057 for (i = 0; i < *num_freqs; i++) {
8058 if (freqs[i] == freq)
8059 return;
8060 }
8061
8062 freqs[*num_freqs] = freq;
8063 (*num_freqs)++;
8064}
8065
8066
8067static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
8068{
8069 struct wpa_bss *bss, *cbss;
8070 const int max_freqs = 10;
8071 int *freqs;
8072 int num_freqs = 0;
8073
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008074 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008075 if (freqs == NULL)
8076 return NULL;
8077
8078 cbss = wpa_s->current_bss;
8079
8080 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
8081 if (bss == cbss)
8082 continue;
8083 if (bss->ssid_len == cbss->ssid_len &&
8084 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08008085 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008086 add_freq(freqs, &num_freqs, bss->freq);
8087 if (num_freqs == max_freqs)
8088 break;
8089 }
8090 }
8091
8092 if (num_freqs == 0) {
8093 os_free(freqs);
8094 freqs = NULL;
8095 }
8096
8097 return freqs;
8098}
8099
8100
8101void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
8102{
8103 int timeout;
8104 int count;
8105 int *freqs = NULL;
8106
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008107 wpas_connect_work_done(wpa_s);
8108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008109 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008110 * Remove possible authentication timeout since the connection failed.
8111 */
8112 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
8113
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008114 /*
Hai Shalom60840252021-02-19 19:02:11 -08008115 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008116 * generated based on local request to disconnect.
8117 */
Hai Shalomfdcde762020-04-02 11:19:20 -07008118 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008119 wpa_s->own_disconnect_req = 0;
8120 wpa_dbg(wpa_s, MSG_DEBUG,
8121 "Ignore connection failure due to local request to disconnect");
8122 return;
8123 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008124 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008125 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8126 "indication since interface has been put into "
8127 "disconnected state");
8128 return;
8129 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08008130 if (wpa_s->auto_reconnect_disabled) {
8131 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
8132 "indication since auto connect is disabled");
8133 return;
8134 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008135
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008136 /*
Hai Shalom60840252021-02-19 19:02:11 -08008137 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008138 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008139 */
Hai Shalom60840252021-02-19 19:02:11 -08008140 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008141 if (count == 1 && wpa_s->current_bss) {
8142 /*
Hai Shalom60840252021-02-19 19:02:11 -08008143 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008144 * another BSS available for the same ESS, we should try that
8145 * next. Otherwise, we may as well try this one once more
8146 * before allowing other, likely worse, ESSes to be considered.
8147 */
8148 freqs = get_bss_freqs_in_ess(wpa_s);
8149 if (freqs) {
8150 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
8151 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08008152 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008153 /*
8154 * On the next scan, go through only the known channels
8155 * used in this ESS based on previous scans to speed up
8156 * common load balancing use case.
8157 */
8158 os_free(wpa_s->next_scan_freqs);
8159 wpa_s->next_scan_freqs = freqs;
8160 }
8161 }
8162
Hai Shalom899fcc72020-10-19 14:38:18 -07008163 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008164
Hai Shalom899fcc72020-10-19 14:38:18 -07008165 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008166 wpa_printf(MSG_DEBUG, "Continuous association failures - "
8167 "consider temporary network disabling");
Sunil Ravi77d572f2023-01-17 23:58:31 +00008168 wpas_auth_failed(wpa_s, "CONN_FAILED", bssid);
Dmitry Shmidt4b060592013-04-29 16:42:49 -07008169 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008170 /*
8171 * Multiple consecutive connection failures mean that other APs are
8172 * either not available or have already been tried, so we can start
8173 * increasing the delay here to avoid constant scanning.
8174 */
8175 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008176 case 1:
8177 timeout = 100;
8178 break;
8179 case 2:
8180 timeout = 500;
8181 break;
8182 case 3:
8183 timeout = 1000;
8184 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008185 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008186 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008187 break;
8188 default:
8189 timeout = 10000;
8190 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008191 }
8192
Hai Shalom899fcc72020-10-19 14:38:18 -07008193 wpa_dbg(wpa_s, MSG_DEBUG,
8194 "Consecutive connection failures: %d --> request scan in %d ms",
8195 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008196
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008197 /*
8198 * TODO: if more than one possible AP is available in scan results,
8199 * could try the other ones before requesting a new scan.
8200 */
Hai Shalom021b0b52019-04-10 11:17:58 -07008201
8202 /* speed up the connection attempt with normal scan */
8203 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008204 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
8205 1000 * (timeout % 1000));
8206}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008207
8208
Hai Shalomce48b4a2018-09-05 11:41:35 -07008209#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08008210
8211void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
8212{
8213 struct wpa_ssid *ssid = wpa_s->current_ssid;
8214 const u8 *realm, *username, *rrk;
8215 size_t realm_len, username_len, rrk_len;
8216 u16 next_seq_num;
8217
8218 /* Clear the PMKSA cache entry if FILS authentication was rejected.
8219 * Check for ERP keys existing to limit when this can be done since
8220 * the rejection response is not protected and such triggers should
8221 * really not allow internal state to be modified unless required to
8222 * avoid significant issues in functionality. In addition, drop
8223 * externally configure PMKSA entries even without ERP keys since it
8224 * is possible for an external component to add PMKSA entries for FILS
8225 * authentication without restoring previously generated ERP keys.
8226 *
8227 * In this case, this is needed to allow recovery from cases where the
8228 * AP or authentication server has dropped PMKSAs and ERP keys. */
8229 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8230 return;
8231
8232 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8233 &username, &username_len,
8234 &realm, &realm_len, &next_seq_num,
8235 &rrk, &rrk_len) != 0 ||
8236 !realm) {
8237 wpa_dbg(wpa_s, MSG_DEBUG,
8238 "FILS: Drop external PMKSA cache entry");
8239 wpa_sm_aborted_external_cached(wpa_s->wpa);
8240 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8241 return;
8242 }
8243
8244 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8245 wpa_sm_aborted_cached(wpa_s->wpa);
8246 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8247}
8248
8249
Hai Shalomce48b4a2018-09-05 11:41:35 -07008250void fils_connection_failure(struct wpa_supplicant *wpa_s)
8251{
8252 struct wpa_ssid *ssid = wpa_s->current_ssid;
8253 const u8 *realm, *username, *rrk;
8254 size_t realm_len, username_len, rrk_len;
8255 u16 next_seq_num;
8256
8257 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8258 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8259 &username, &username_len,
8260 &realm, &realm_len, &next_seq_num,
8261 &rrk, &rrk_len) != 0 ||
8262 !realm)
8263 return;
8264
8265 wpa_hexdump_ascii(MSG_DEBUG,
8266 "FILS: Store last connection failure realm",
8267 realm, realm_len);
8268 os_free(wpa_s->last_con_fail_realm);
8269 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8270 if (wpa_s->last_con_fail_realm) {
8271 wpa_s->last_con_fail_realm_len = realm_len;
8272 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8273 }
8274}
8275#endif /* CONFIG_FILS */
8276
8277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008278int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8279{
8280 return wpa_s->conf->ap_scan == 2 ||
8281 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8282}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008283
Dmitry Shmidt04949592012-07-19 12:16:46 -07008284
Gabriel Biren57ededa2021-09-03 16:08:50 +00008285#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008286int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8287 struct wpa_ssid *ssid,
8288 const char *field,
8289 const char *value)
8290{
8291#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008292 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008293
8294 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8295 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8296 (const u8 *) value, os_strlen(value));
8297
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008298 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008299 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008300#else /* IEEE8021X_EAPOL */
8301 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8302 return -1;
8303#endif /* IEEE8021X_EAPOL */
8304}
8305
8306int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8307 struct wpa_ssid *ssid,
8308 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008309 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008310{
8311#ifdef IEEE8021X_EAPOL
8312 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008313 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008314
8315 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008316 case WPA_CTRL_REQ_EAP_IDENTITY:
8317 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008318 os_free(eap->imsi_identity);
8319 if (value == NULL)
8320 return -1;
8321 identity = os_strchr(value, ':');
8322 if (identity == NULL) {
8323 /* plain identity */
8324 eap->identity = (u8 *)os_strdup(value);
8325 eap->identity_len = os_strlen(value);
8326 } else {
8327 /* have both plain identity and encrypted identity */
8328 imsi_identity = value;
8329 *identity++ = '\0';
8330 /* plain identity */
8331 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8332 eap->imsi_identity_len = strlen(imsi_identity);
8333 /* encrypted identity */
8334 eap->identity = (u8 *)dup_binstr(identity,
8335 value_len - strlen(imsi_identity) - 1);
8336 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8337 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008338 eap->pending_req_identity = 0;
8339 if (ssid == wpa_s->current_ssid)
8340 wpa_s->reassociate = 1;
8341 break;
8342 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008343 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008344 eap->password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008345 if (!eap->password)
8346 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008347 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008348 eap->pending_req_password = 0;
8349 if (ssid == wpa_s->current_ssid)
8350 wpa_s->reassociate = 1;
8351 break;
8352 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008353 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008354 eap->new_password = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008355 if (!eap->new_password)
8356 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008357 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008358 eap->pending_req_new_password = 0;
8359 if (ssid == wpa_s->current_ssid)
8360 wpa_s->reassociate = 1;
8361 break;
8362 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008363 str_clear_free(eap->cert.pin);
8364 eap->cert.pin = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008365 if (!eap->cert.pin)
8366 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008367 eap->pending_req_pin = 0;
8368 if (ssid == wpa_s->current_ssid)
8369 wpa_s->reassociate = 1;
8370 break;
8371 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008372 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008373 eap->otp = (u8 *) os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008374 if (!eap->otp)
8375 return -1;
pkanwareb9203e2017-10-26 16:00:35 -07008376 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008377 os_free(eap->pending_req_otp);
8378 eap->pending_req_otp = NULL;
8379 eap->pending_req_otp_len = 0;
8380 break;
8381 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008382 str_clear_free(eap->cert.private_key_passwd);
8383 eap->cert.private_key_passwd = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008384 if (!eap->cert.private_key_passwd)
8385 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008386 eap->pending_req_passphrase = 0;
8387 if (ssid == wpa_s->current_ssid)
8388 wpa_s->reassociate = 1;
8389 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008390 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008391 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008392 eap->external_sim_resp = os_strdup(value);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008393 if (!eap->external_sim_resp)
8394 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008395 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008396 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008397 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8398 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8399 return -1;
8400 ssid->mem_only_psk = 1;
8401 if (ssid->passphrase)
8402 wpa_config_update_psk(ssid);
8403 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8404 wpa_supplicant_req_scan(wpa_s, 0, 0);
8405 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008406 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8407 if (eap->pending_ext_cert_check != PENDING_CHECK)
8408 return -1;
8409 if (os_strcmp(value, "good") == 0)
8410 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8411 else if (os_strcmp(value, "bad") == 0)
8412 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8413 else
8414 return -1;
8415 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008416 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008417 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008418 return -1;
8419 }
8420
8421 return 0;
8422#else /* IEEE8021X_EAPOL */
8423 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8424 return -1;
8425#endif /* IEEE8021X_EAPOL */
8426}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008427#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008428
8429
8430int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8431{
Hai Shalomfdcde762020-04-02 11:19:20 -07008432#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008433 int i;
8434 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008435#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008436
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008437 if (wpa_s->p2p_mgmt)
8438 return 1; /* no normal network profiles on p2p_mgmt interface */
8439
Dmitry Shmidt04949592012-07-19 12:16:46 -07008440 if (ssid == NULL)
8441 return 1;
8442
8443 if (ssid->disabled)
8444 return 1;
8445
Hai Shalomfdcde762020-04-02 11:19:20 -07008446#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008447 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008448 drv_enc = wpa_s->drv_enc;
8449 else
8450 drv_enc = (unsigned int) -1;
8451
8452 for (i = 0; i < NUM_WEP_KEYS; i++) {
8453 size_t len = ssid->wep_key_len[i];
8454 if (len == 0)
8455 continue;
8456 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8457 continue;
8458 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8459 continue;
8460 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8461 continue;
8462 return 1; /* invalid WEP key */
8463 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008464#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008465
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008466 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008467 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008468 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008469 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008470 return 1;
8471
Sunil Ravi89eba102022-09-13 21:04:37 -07008472#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008473#ifdef CRYPTO_RSA_OAEP_SHA256
8474 if (ssid->eap.imsi_privacy_cert) {
8475 struct crypto_rsa_key *key;
8476 bool failed = false;
8477
8478 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8479 if (!key)
8480 failed = true;
8481 crypto_rsa_key_free(key);
8482 if (failed) {
8483 wpa_printf(MSG_DEBUG,
8484 "Invalid imsi_privacy_cert (%s) - disable network",
8485 ssid->eap.imsi_privacy_cert);
8486 return 1;
8487 }
8488 }
8489#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008490#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008491
Dmitry Shmidt04949592012-07-19 12:16:46 -07008492 return 0;
8493}
8494
8495
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008496int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8497{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008498 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8499 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8500 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8501 /*
8502 * Driver does not support BIP -- ignore pmf=1 default
8503 * since the connection with PMF would fail and the
8504 * configuration does not require PMF to be enabled.
8505 */
8506 return NO_MGMT_FRAME_PROTECTION;
8507 }
8508
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008509 if (ssid &&
8510 (ssid->key_mgmt &
8511 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8512 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8513 /*
8514 * Do not use the default PMF value for non-RSN networks
8515 * since PMF is available only with RSN and pmf=2
8516 * configuration would otherwise prevent connections to
8517 * all open networks.
8518 */
8519 return NO_MGMT_FRAME_PROTECTION;
8520 }
8521
Sunil Ravi77d572f2023-01-17 23:58:31 +00008522#ifdef CONFIG_OCV
8523 /* Enable PMF if OCV is being enabled */
8524 if (wpa_s->conf->pmf == NO_MGMT_FRAME_PROTECTION &&
8525 ssid && ssid->ocv)
8526 return MGMT_FRAME_PROTECTION_OPTIONAL;
8527#endif /* CONFIG_OCV */
8528
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008529 return wpa_s->conf->pmf;
8530 }
8531
8532 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008533}
8534
8535
Sunil Ravi77d572f2023-01-17 23:58:31 +00008536#ifdef CONFIG_SAE
8537bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
8538 struct wpa_ssid *ssid,
8539 const struct wpa_ie_data *ie)
8540{
8541 return wpa_s->conf->sae_check_mfp &&
8542 (!(ie->capabilities &
8543 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
8544 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
8545}
8546#endif /* CONFIG_SAE */
8547
8548
Hai Shalomc1a21442022-02-04 13:43:00 -08008549int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8550{
8551 if (wpa_s->current_ssid == NULL ||
8552 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8553 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8554 return 0;
8555 return wpa_sm_pmf_enabled(wpa_s->wpa);
8556}
8557
8558
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008559int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008560{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008561 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008562 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008563 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008564 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008565 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008566}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008567
8568
Sunil Ravi77d572f2023-01-17 23:58:31 +00008569void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
8570 const u8 *bssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008571{
8572 struct wpa_ssid *ssid = wpa_s->current_ssid;
8573 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008574 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008575
8576 if (ssid == NULL) {
8577 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8578 "SSID block");
8579 return;
8580 }
8581
8582 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8583 return;
8584
8585 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008586
8587#ifdef CONFIG_P2P
8588 if (ssid->p2p_group &&
8589 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8590 /*
8591 * Skip the wait time since there is a short timeout on the
8592 * connection to a P2P group.
8593 */
8594 return;
8595 }
8596#endif /* CONFIG_P2P */
8597
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008598 if (ssid->auth_failures > 50)
8599 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008600 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008601 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008602 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008603 dur = 90;
8604 else if (ssid->auth_failures > 3)
8605 dur = 60;
8606 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008607 dur = 30;
8608 else if (ssid->auth_failures > 1)
8609 dur = 20;
8610 else
8611 dur = 10;
8612
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008613 if (ssid->auth_failures > 1 &&
8614 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8615 dur += os_random() % (ssid->auth_failures * 10);
8616
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008617 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008618 if (now.sec + dur <= ssid->disabled_until.sec)
8619 return;
8620
8621 ssid->disabled_until.sec = now.sec + dur;
8622
8623 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008624 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008625 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008626 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008627
8628 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8629 int msg_len = snprintf(NULL, 0, format_str,
8630 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8631 ssid->auth_failures, dur, reason) + 1;
8632 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308633 if (!msg)
8634 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008635 snprintf(msg, msg_len, format_str,
8636 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8637 ssid->auth_failures, dur, reason);
8638 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8639 os_free(msg);
Sunil Ravi77d572f2023-01-17 23:58:31 +00008640
8641 if (bssid)
8642 os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008643}
8644
8645
8646void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8647 struct wpa_ssid *ssid, int clear_failures)
8648{
8649 if (ssid == NULL)
8650 return;
8651
8652 if (ssid->disabled_until.sec) {
8653 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8654 "id=%d ssid=\"%s\"",
8655 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8656 }
8657 ssid->disabled_until.sec = 0;
8658 ssid->disabled_until.usec = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008659 if (clear_failures) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008660 ssid->auth_failures = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008661 } else if (!is_zero_ether_addr(ssid->disabled_due_to)) {
8662 wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR
8663 " ignored to allow a lower priority BSS, if any, to be tried next",
8664 MAC2STR(ssid->disabled_due_to));
8665 wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to);
8666 os_memset(ssid->disabled_due_to, 0, ETH_ALEN);
8667 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008668}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008669
8670
8671int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8672{
8673 size_t i;
8674
8675 if (wpa_s->disallow_aps_bssid == NULL)
8676 return 0;
8677
8678 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8679 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8680 bssid, ETH_ALEN) == 0)
8681 return 1;
8682 }
8683
8684 return 0;
8685}
8686
8687
8688int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8689 size_t ssid_len)
8690{
8691 size_t i;
8692
8693 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8694 return 0;
8695
8696 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8697 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8698 if (ssid_len == s->ssid_len &&
8699 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8700 return 1;
8701 }
8702
8703 return 0;
8704}
8705
8706
8707/**
8708 * wpas_request_connection - Request a new connection
8709 * @wpa_s: Pointer to the network interface
8710 *
8711 * This function is used to request a new connection to be found. It will mark
8712 * the interface to allow reassociation and request a new scan to find a
8713 * suitable network to connect to.
8714 */
8715void wpas_request_connection(struct wpa_supplicant *wpa_s)
8716{
8717 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008718 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008719 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008720 wpa_s->disconnected = 0;
8721 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008722 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008723
8724 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8725 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008726 else
8727 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008728}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008729
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008730
Roshan Pius02242d72016-08-09 15:31:48 -07008731/**
8732 * wpas_request_disconnection - Request disconnection
8733 * @wpa_s: Pointer to the network interface
8734 *
8735 * This function is used to request disconnection from the currently connected
8736 * network. This will stop any ongoing scans and initiate deauthentication.
8737 */
8738void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8739{
8740#ifdef CONFIG_SME
8741 wpa_s->sme.prev_bssid_set = 0;
8742#endif /* CONFIG_SME */
8743 wpa_s->reassociate = 0;
8744 wpa_s->disconnected = 1;
8745 wpa_supplicant_cancel_sched_scan(wpa_s);
8746 wpa_supplicant_cancel_scan(wpa_s);
8747 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8748 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008749 radio_remove_works(wpa_s, "connect", 0);
8750 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008751 wpa_s->roam_in_progress = false;
8752#ifdef CONFIG_WNM
8753 wpa_s->bss_trans_mgmt_in_progress = false;
8754#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008755}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008756
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008757
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008758void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8759 struct wpa_used_freq_data *freqs_data,
8760 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008761{
8762 unsigned int i;
8763
8764 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8765 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008766 for (i = 0; i < len; i++) {
8767 struct wpa_used_freq_data *cur = &freqs_data[i];
8768 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8769 i, cur->freq, cur->flags);
8770 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008771}
8772
8773
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008774/*
8775 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008776 * are using the same radio as the current interface, and in addition, get
8777 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008778 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008779int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8780 struct wpa_used_freq_data *freqs_data,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008781 unsigned int len, bool exclude_current)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008782{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008783 struct wpa_supplicant *ifs;
8784 u8 bssid[ETH_ALEN];
8785 int freq;
8786 unsigned int idx = 0, i;
8787
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008788 wpa_dbg(wpa_s, MSG_DEBUG,
8789 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008790 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008791
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008792 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8793 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008794 if (idx == len)
8795 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008796
Sunil Ravi77d572f2023-01-17 23:58:31 +00008797 if (exclude_current && ifs == wpa_s)
8798 continue;
8799
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008800 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8801 continue;
8802
8803 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008804 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8805 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008806 freq = ifs->current_ssid->frequency;
8807 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8808 freq = ifs->assoc_freq;
8809 else
8810 continue;
8811
8812 /* Hold only distinct freqs */
8813 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008814 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008815 break;
8816
8817 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008818 freqs_data[idx++].freq = freq;
8819
8820 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008821 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008822 WPA_FREQ_USED_BY_P2P_CLIENT :
8823 WPA_FREQ_USED_BY_INFRA_STATION;
8824 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008825 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008826
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008827 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008828 return idx;
8829}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008830
8831
8832/*
8833 * Find the operating frequencies of any of the virtual interfaces that
8834 * are using the same radio as the current interface.
8835 */
8836int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
Sunil Ravi77d572f2023-01-17 23:58:31 +00008837 int *freq_array, unsigned int len,
8838 bool exclude_current)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008839{
8840 struct wpa_used_freq_data *freqs_data;
8841 int num, i;
8842
8843 os_memset(freq_array, 0, sizeof(int) * len);
8844
8845 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8846 if (!freqs_data)
8847 return -1;
8848
Sunil Ravi77d572f2023-01-17 23:58:31 +00008849 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len,
8850 exclude_current);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008851 for (i = 0; i < num; i++)
8852 freq_array[i] = freqs_data[i].freq;
8853
8854 os_free(freqs_data);
8855
8856 return num;
8857}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008858
8859
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008860struct wpa_supplicant *
8861wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8862{
8863 switch (frame) {
8864#ifdef CONFIG_P2P
8865 case VENDOR_ELEM_PROBE_REQ_P2P:
8866 case VENDOR_ELEM_PROBE_RESP_P2P:
8867 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8868 case VENDOR_ELEM_BEACON_P2P_GO:
8869 case VENDOR_ELEM_P2P_PD_REQ:
8870 case VENDOR_ELEM_P2P_PD_RESP:
8871 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8872 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8873 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8874 case VENDOR_ELEM_P2P_INV_REQ:
8875 case VENDOR_ELEM_P2P_INV_RESP:
8876 case VENDOR_ELEM_P2P_ASSOC_REQ:
8877 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008878 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008879#endif /* CONFIG_P2P */
8880 default:
8881 return wpa_s;
8882 }
8883}
8884
8885
8886void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8887{
8888 unsigned int i;
8889 char buf[30];
8890
8891 wpa_printf(MSG_DEBUG, "Update vendor elements");
8892
8893 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8894 if (wpa_s->vendor_elem[i]) {
8895 int res;
8896
8897 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8898 if (!os_snprintf_error(sizeof(buf), res)) {
8899 wpa_hexdump_buf(MSG_DEBUG, buf,
8900 wpa_s->vendor_elem[i]);
8901 }
8902 }
8903 }
8904
8905#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008906 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008907 wpa_s->global->p2p &&
8908 !wpa_s->global->p2p_disabled)
8909 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8910#endif /* CONFIG_P2P */
8911}
8912
8913
8914int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8915 const u8 *elem, size_t len)
8916{
8917 u8 *ie, *end;
8918
8919 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8920 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8921
8922 for (; ie + 1 < end; ie += 2 + ie[1]) {
8923 if (ie + len > end)
8924 break;
8925 if (os_memcmp(ie, elem, len) != 0)
8926 continue;
8927
8928 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8929 wpabuf_free(wpa_s->vendor_elem[frame]);
8930 wpa_s->vendor_elem[frame] = NULL;
8931 } else {
8932 os_memmove(ie, ie + len, end - (ie + len));
8933 wpa_s->vendor_elem[frame]->used -= len;
8934 }
8935 wpas_vendor_elem_update(wpa_s);
8936 return 0;
8937 }
8938
8939 return -1;
8940}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008941
8942
8943struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008944 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008945 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008946{
8947 u16 i;
8948
Hai Shalomc1a21442022-02-04 13:43:00 -08008949 if (!modes)
8950 return NULL;
8951
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008952 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008953 if (modes[i].mode != mode ||
8954 !modes[i].num_channels || !modes[i].channels)
8955 continue;
8956 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8957 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008958 return &modes[i];
8959 }
8960
8961 return NULL;
8962}
8963
8964
Hai Shalomc1a21442022-02-04 13:43:00 -08008965struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8966 u16 num_modes, int freq)
8967{
8968 int i, j;
8969
8970 for (i = 0; i < num_modes; i++) {
8971 for (j = 0; j < modes[i].num_channels; j++) {
8972 if (freq == modes[i].channels[j].freq)
8973 return &modes[i];
8974 }
8975 }
8976
8977 return NULL;
8978}
8979
8980
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008981static struct
8982wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8983 const u8 *bssid)
8984{
8985 struct wpa_bss_tmp_disallowed *bss;
8986
8987 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8988 struct wpa_bss_tmp_disallowed, list) {
8989 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8990 return bss;
8991 }
8992
8993 return NULL;
8994}
8995
8996
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008997static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8998{
8999 struct wpa_bss_tmp_disallowed *tmp;
9000 unsigned int num_bssid = 0;
9001 u8 *bssids;
9002 int ret;
9003
9004 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
9005 if (!bssids)
9006 return -1;
9007 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9008 struct wpa_bss_tmp_disallowed, list) {
9009 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
9010 ETH_ALEN);
9011 num_bssid++;
9012 }
Hai Shalom899fcc72020-10-19 14:38:18 -07009013 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009014 os_free(bssids);
9015 return ret;
9016}
9017
9018
9019static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
9020{
9021 struct wpa_supplicant *wpa_s = eloop_ctx;
9022 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
9023
9024 /* Make sure the bss is not already freed */
9025 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
9026 struct wpa_bss_tmp_disallowed, list) {
9027 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08009028 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009029 wpa_set_driver_tmp_disallow_list(wpa_s);
9030 break;
9031 }
9032 }
9033}
9034
9035
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009036void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08009037 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009038{
9039 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009040
9041 bss = wpas_get_disallowed_bss(wpa_s, bssid);
9042 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009043 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08009044 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009045 }
9046
9047 bss = os_malloc(sizeof(*bss));
9048 if (!bss) {
9049 wpa_printf(MSG_DEBUG,
9050 "Failed to allocate memory for temp disallow BSS");
9051 return;
9052 }
9053
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009054 os_memcpy(bss->bssid, bssid, ETH_ALEN);
9055 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009056 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08009057
9058finish:
9059 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009060 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
9061 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009062}
9063
9064
Hai Shalom74f70d42019-02-11 14:42:39 -08009065int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
9066 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009067{
Hai Shalom74f70d42019-02-11 14:42:39 -08009068 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009069
9070 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
9071 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009072 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
9073 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009074 break;
9075 }
9076 }
Hai Shalom74f70d42019-02-11 14:42:39 -08009077 if (!disallowed)
9078 return 0;
9079
9080 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08009081 bss->level > disallowed->rssi_threshold) {
9082 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
9083 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009084 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08009085 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009086
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009087 return 1;
9088}
Hai Shalom81f62d82019-07-22 12:10:00 -07009089
9090
9091int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9092 unsigned int type, const u8 *addr,
9093 const u8 *mask)
9094{
9095 if ((addr && !mask) || (!addr && mask)) {
9096 wpa_printf(MSG_INFO,
9097 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
9098 return -1;
9099 }
9100
9101 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
9102 wpa_printf(MSG_INFO,
9103 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
9104 return -1;
9105 }
9106
9107 if (type & MAC_ADDR_RAND_SCAN) {
9108 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
9109 addr, mask))
9110 return -1;
9111 }
9112
9113 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
9114 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
9115 addr, mask))
9116 return -1;
9117
9118 if (wpa_s->sched_scanning && !wpa_s->pno)
9119 wpas_scan_restart_sched_scan(wpa_s);
9120 }
9121
9122 if (type & MAC_ADDR_RAND_PNO) {
9123 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
9124 addr, mask))
9125 return -1;
9126
9127 if (wpa_s->pno) {
9128 wpas_stop_pno(wpa_s);
9129 wpas_start_pno(wpa_s);
9130 }
9131 }
9132
9133 return 0;
9134}
9135
9136
9137int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
9138 unsigned int type)
9139{
9140 wpas_mac_addr_rand_scan_clear(wpa_s, type);
9141 if (wpa_s->pno) {
9142 if (type & MAC_ADDR_RAND_PNO) {
9143 wpas_stop_pno(wpa_s);
9144 wpas_start_pno(wpa_s);
9145 }
9146 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
9147 wpas_scan_restart_sched_scan(wpa_s);
9148 }
9149
9150 return 0;
9151}
Hai Shalomfdcde762020-04-02 11:19:20 -07009152
9153
9154int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
9155 struct wpa_signal_info *si)
9156{
9157 int res;
9158
9159 if (!wpa_s->driver->signal_poll)
9160 return -1;
9161
9162 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
9163
9164#ifdef CONFIG_TESTING_OPTIONS
9165 if (res == 0) {
9166 struct driver_signal_override *dso;
9167
9168 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9169 struct driver_signal_override, list) {
9170 if (os_memcmp(wpa_s->bssid, dso->bssid,
9171 ETH_ALEN) != 0)
9172 continue;
9173 wpa_printf(MSG_DEBUG,
9174 "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 +00009175 si->data.signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009176 dso->si_current_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009177 si->data.avg_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009178 dso->si_avg_signal,
Sunil Ravi77d572f2023-01-17 23:58:31 +00009179 si->data.avg_beacon_signal,
Hai Shalomfdcde762020-04-02 11:19:20 -07009180 dso->si_avg_beacon_signal,
9181 si->current_noise,
9182 dso->si_current_noise);
Sunil Ravi77d572f2023-01-17 23:58:31 +00009183 si->data.signal = dso->si_current_signal;
9184 si->data.avg_signal = dso->si_avg_signal;
9185 si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
Hai Shalomfdcde762020-04-02 11:19:20 -07009186 si->current_noise = dso->si_current_noise;
9187 break;
9188 }
9189 }
9190#endif /* CONFIG_TESTING_OPTIONS */
9191
9192 return res;
9193}
9194
9195
9196struct wpa_scan_results *
9197wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
9198{
9199 struct wpa_scan_results *scan_res;
9200#ifdef CONFIG_TESTING_OPTIONS
9201 size_t idx;
9202#endif /* CONFIG_TESTING_OPTIONS */
9203
9204 if (!wpa_s->driver->get_scan_results2)
9205 return NULL;
9206
9207 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
9208
9209#ifdef CONFIG_TESTING_OPTIONS
9210 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
9211 struct driver_signal_override *dso;
9212 struct wpa_scan_res *res = scan_res->res[idx];
9213
9214 dl_list_for_each(dso, &wpa_s->drv_signal_override,
9215 struct driver_signal_override, list) {
9216 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
9217 continue;
9218 wpa_printf(MSG_DEBUG,
9219 "Override driver scan signal level %d->%d for "
9220 MACSTR,
9221 res->level, dso->scan_level,
9222 MAC2STR(res->bssid));
9223 res->flags |= WPA_SCAN_QUAL_INVALID;
9224 if (dso->scan_level < 0)
9225 res->flags |= WPA_SCAN_LEVEL_DBM;
9226 else
9227 res->flags &= ~WPA_SCAN_LEVEL_DBM;
9228 res->level = dso->scan_level;
9229 break;
9230 }
9231 }
9232#endif /* CONFIG_TESTING_OPTIONS */
9233
9234 return scan_res;
9235}
Sunil Ravi77d572f2023-01-17 23:58:31 +00009236
9237
9238static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
9239{
9240 int i;
9241
9242 if (!wpa_s->valid_links)
9243 return false;
9244
9245 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
9246 if (!(wpa_s->valid_links & BIT(i)))
9247 continue;
9248
9249 if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
9250 return true;
9251 }
9252
9253 return false;
9254}
9255
9256
9257int wpa_drv_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
9258 unsigned int wait, const u8 *dst, const u8 *src,
9259 const u8 *bssid, const u8 *data, size_t data_len,
9260 int no_cck)
9261{
9262 if (!wpa_s->driver->send_action)
9263 return -1;
9264
9265 if (data_len > 0 && data[0] != WLAN_ACTION_PUBLIC) {
9266 if (wpas_ap_link_address(wpa_s, dst))
9267 dst = wpa_s->ap_mld_addr;
9268
9269 if (wpas_ap_link_address(wpa_s, bssid))
9270 bssid = wpa_s->ap_mld_addr;
9271 }
9272
9273 return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
9274 bssid, data, data_len, no_cck);
9275}