blob: 99af85e012961edc6be77c1dd186104555fc91b1 [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"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080044#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080046#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080047#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "wpas_glue.h"
49#include "wps_supplicant.h"
50#include "ibss_rsn.h"
51#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "ap.h"
54#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070055#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "notify.h"
57#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059#include "bss.h"
60#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080061#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070062#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070063#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070064#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080065#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066#include "dpp_supplicant.h"
67#ifdef CONFIG_MESH
68#include "ap/ap_config.h"
69#include "ap/hostapd.h"
70#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070072const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080074"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070076const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080077"This software may be distributed under the terms of the BSD license.\n"
78"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079#ifdef EAP_TLS_OPENSSL
80"\nThis product includes software developed by the OpenSSL Project\n"
81"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
82#endif /* EAP_TLS_OPENSSL */
83;
84
85#ifndef CONFIG_NO_STDOUT_DEBUG
86/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080088"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091"\n"
92"Redistribution and use in source and binary forms, with or without\n"
93"modification, are permitted provided that the following conditions are\n"
94"met:\n"
95"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070096const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097"1. Redistributions of source code must retain the above copyright\n"
98" notice, this list of conditions and the following disclaimer.\n"
99"\n"
100"2. Redistributions in binary form must reproduce the above copyright\n"
101" notice, this list of conditions and the following disclaimer in the\n"
102" documentation and/or other materials provided with the distribution.\n"
103"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
106" names of its contributors may be used to endorse or promote products\n"
107" derived from this software without specific prior written permission.\n"
108"\n"
109"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
110"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
111"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
112"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700113const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
115"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
116"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
117"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
118"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
119"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
120"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
121"\n";
122#endif /* CONFIG_NO_STDOUT_DEBUG */
123
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700124
125static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
126#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
127static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
128#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700129#ifdef CONFIG_OWE
130static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
131#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700132
133
Hai Shalomfdcde762020-04-02 11:19:20 -0700134#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700135/* Configure default/group WEP keys for static WEP */
136int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
137{
138 int i, set = 0;
139
140 for (i = 0; i < NUM_WEP_KEYS; i++) {
141 if (ssid->wep_key_len[i] == 0)
142 continue;
143
144 set = 1;
145 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
146 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700147 ssid->wep_key[i], ssid->wep_key_len[i],
148 i == ssid->wep_tx_keyidx ?
149 KEY_FLAG_GROUP_RX_TX_DEFAULT :
150 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151 }
152
153 return set;
154}
Hai Shalomfdcde762020-04-02 11:19:20 -0700155#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156
157
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700158int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
159 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160{
161 u8 key[32];
162 size_t keylen;
163 enum wpa_alg alg;
164 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800165 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166
167 /* IBSS/WPA-None uses only one key (Group) for both receiving and
168 * sending unicast and multicast packets. */
169
170 if (ssid->mode != WPAS_MODE_IBSS) {
171 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
172 "IBSS/ad-hoc) for WPA-None", ssid->mode);
173 return -1;
174 }
175
176 if (!ssid->psk_set) {
177 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
178 "WPA-None");
179 return -1;
180 }
181
182 switch (wpa_s->group_cipher) {
183 case WPA_CIPHER_CCMP:
184 os_memcpy(key, ssid->psk, 16);
185 keylen = 16;
186 alg = WPA_ALG_CCMP;
187 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700188 case WPA_CIPHER_GCMP:
189 os_memcpy(key, ssid->psk, 16);
190 keylen = 16;
191 alg = WPA_ALG_GCMP;
192 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 case WPA_CIPHER_TKIP:
194 /* WPA-None uses the same Michael MIC key for both TX and RX */
195 os_memcpy(key, ssid->psk, 16 + 8);
196 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
197 keylen = 32;
198 alg = WPA_ALG_TKIP;
199 break;
200 default:
201 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
202 "WPA-None", wpa_s->group_cipher);
203 return -1;
204 }
205
206 /* TODO: should actually remember the previously used seq#, both for TX
207 * and RX from each STA.. */
208
Hai Shalomfdcde762020-04-02 11:19:20 -0700209 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
210 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800211 os_memset(key, 0, sizeof(key));
212 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213}
214
215
216static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
217{
218 struct wpa_supplicant *wpa_s = eloop_ctx;
219 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700220 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
221 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
222 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223 bssid = wpa_s->pending_bssid;
224 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
225 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800226 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700227 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800229 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_s->reassociate = 1;
231
232 /*
233 * If we timed out, the AP or the local radio may be busy.
234 * So, wait a second until scanning again.
235 */
236 wpa_supplicant_req_scan(wpa_s, 1, 0);
237}
238
239
240/**
241 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
242 * @wpa_s: Pointer to wpa_supplicant data
243 * @sec: Number of seconds after which to time out authentication
244 * @usec: Number of microseconds after which to time out authentication
245 *
246 * This function is used to schedule a timeout for the current authentication
247 * attempt.
248 */
249void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
250 int sec, int usec)
251{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700252 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
254 return;
255
256 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
257 "%d usec", sec, usec);
258 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700259 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700260 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
261}
262
263
Roshan Pius3a1667e2018-07-03 15:17:14 -0700264/*
265 * wpas_auth_timeout_restart - Restart and change timeout for authentication
266 * @wpa_s: Pointer to wpa_supplicant data
267 * @sec_diff: difference in seconds applied to original timeout value
268 */
269void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
270{
271 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
272
273 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
274 wpa_dbg(wpa_s, MSG_DEBUG,
275 "Authentication timeout restart: %d sec", new_sec);
276 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
277 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
278 wpa_s, NULL);
279 }
280}
281
282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283/**
284 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
285 * @wpa_s: Pointer to wpa_supplicant data
286 *
287 * This function is used to cancel authentication timeout scheduled with
288 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
289 * been completed.
290 */
291void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
292{
293 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
294 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800295 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700296 os_free(wpa_s->last_con_fail_realm);
297 wpa_s->last_con_fail_realm = NULL;
298 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299}
300
301
302/**
303 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
304 * @wpa_s: Pointer to wpa_supplicant data
305 *
306 * This function is used to configure EAPOL state machine based on the selected
307 * authentication mode.
308 */
309void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
310{
311#ifdef IEEE8021X_EAPOL
312 struct eapol_config eapol_conf;
313 struct wpa_ssid *ssid = wpa_s->current_ssid;
314
315#ifdef CONFIG_IBSS_RSN
316 if (ssid->mode == WPAS_MODE_IBSS &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
319 /*
320 * RSN IBSS authentication is per-STA and we can disable the
321 * per-BSSID EAPOL authentication.
322 */
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700324 eapol_sm_notify_eap_success(wpa_s->eapol, true);
325 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 return;
327 }
328#endif /* CONFIG_IBSS_RSN */
329
Hai Shalome21d4e82020-04-29 16:34:06 -0700330 eapol_sm_notify_eap_success(wpa_s->eapol, false);
331 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
334 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
335 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
336 else
337 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
338
339 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
340 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
341 eapol_conf.accept_802_1x_keys = 1;
342 eapol_conf.required_keys = 0;
343 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
344 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
345 }
346 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
347 eapol_conf.required_keys |=
348 EAPOL_REQUIRE_KEY_BROADCAST;
349 }
350
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 eapol_conf.required_keys = 0;
353 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700354 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 eapol_conf.workaround = ssid->eap_workaround;
356 eapol_conf.eap_disabled =
357 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700360 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800361
362#ifdef CONFIG_WPS
363 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
364 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
365 if (wpa_s->current_bss) {
366 struct wpabuf *ie;
367 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
368 WPS_IE_VENDOR_TYPE);
369 if (ie) {
370 if (wps_is_20(ie))
371 eapol_conf.wps |=
372 EAPOL_PEER_IS_WPS20_AP;
373 wpabuf_free(ie);
374 }
375 }
376 }
377#endif /* CONFIG_WPS */
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700380
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800381#ifdef CONFIG_MACSEC
382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
383 ieee802_1x_create_preshared_mka(wpa_s, ssid);
384 else
385 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
386#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800387#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
391/**
392 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
393 * @wpa_s: Pointer to wpa_supplicant data
394 * @ssid: Configuration data for the network
395 *
396 * This function is used to configure WPA state machine and related parameters
397 * to a mode where WPA is not enabled. This is called as part of the
398 * authentication configuration when the selected network does not use WPA.
399 */
400void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
401 struct wpa_ssid *ssid)
402{
Hai Shalomfdcde762020-04-02 11:19:20 -0700403#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406
407 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
408 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
409 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
410 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
411 else
412 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
413 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
414 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700415 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700417 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
418 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
420 wpa_s->group_cipher = WPA_CIPHER_NONE;
421 wpa_s->mgmt_group_cipher = 0;
422
Hai Shalomfdcde762020-04-02 11:19:20 -0700423#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 for (i = 0; i < NUM_WEP_KEYS; i++) {
425 if (ssid->wep_key_len[i] > 5) {
426 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
427 wpa_s->group_cipher = WPA_CIPHER_WEP104;
428 break;
429 } else if (ssid->wep_key_len[i] > 0) {
430 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
431 wpa_s->group_cipher = WPA_CIPHER_WEP40;
432 break;
433 }
434 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700435#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
440 wpa_s->pairwise_cipher);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
443 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
445 pmksa_cache_clear_current(wpa_s->wpa);
446}
447
448
Dmitry Shmidt04949592012-07-19 12:16:46 -0700449void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800450{
451 int i;
452 if (wpa_s->hw.modes == NULL)
453 return;
454
455 for (i = 0; i < wpa_s->hw.num_modes; i++) {
456 os_free(wpa_s->hw.modes[i].channels);
457 os_free(wpa_s->hw.modes[i].rates);
458 }
459
460 os_free(wpa_s->hw.modes);
461 wpa_s->hw.modes = NULL;
462}
463
464
Hai Shalomc1a21442022-02-04 13:43:00 -0800465static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
466 struct wpa_bss_tmp_disallowed *bss)
467{
468 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
469 dl_list_del(&bss->list);
470 os_free(bss);
471}
472
473
Hai Shalom74f70d42019-02-11 14:42:39 -0800474void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800475{
476 struct wpa_bss_tmp_disallowed *bss, *prev;
477
478 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800479 struct wpa_bss_tmp_disallowed, list)
480 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800481}
482
483
Paul Stewart092955c2017-02-06 09:13:09 -0800484void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
485{
486 struct fils_hlp_req *req;
487
488 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
489 list)) != NULL) {
490 dl_list_del(&req->list);
491 wpabuf_free(req->pkt);
492 os_free(req);
493 }
494}
495
496
Hai Shalomfdcde762020-04-02 11:19:20 -0700497void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
498{
499 struct wpa_supplicant *wpa_s = eloop_ctx;
500
501 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
502 return;
503 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
504 wpa_bss_flush(wpa_s);
505}
506
507
508#ifdef CONFIG_TESTING_OPTIONS
509void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
510{
511 struct driver_signal_override *dso;
512
513 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
514 struct driver_signal_override, list))) {
515 dl_list_del(&dso->list);
516 os_free(dso);
517 }
518}
519#endif /* CONFIG_TESTING_OPTIONS */
520
521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
523{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700524 int i;
525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700527 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528 scard_deinit(wpa_s->scard);
529 wpa_s->scard = NULL;
530 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
531 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
532 l2_packet_deinit(wpa_s->l2);
533 wpa_s->l2 = NULL;
534 if (wpa_s->l2_br) {
535 l2_packet_deinit(wpa_s->l2_br);
536 wpa_s->l2_br = NULL;
537 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800538#ifdef CONFIG_TESTING_OPTIONS
539 l2_packet_deinit(wpa_s->l2_test);
540 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800541 os_free(wpa_s->get_pref_freq_list_override);
542 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700543 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
544 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800545 os_free(wpa_s->extra_sae_rejected_groups);
546 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700547 wpabuf_free(wpa_s->rsne_override_eapol);
548 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800549 wpabuf_free(wpa_s->rsnxe_override_assoc);
550 wpa_s->rsnxe_override_assoc = NULL;
551 wpabuf_free(wpa_s->rsnxe_override_eapol);
552 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700553 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800554#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556 if (wpa_s->conf != NULL) {
557 struct wpa_ssid *ssid;
558 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
559 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 }
561
562 os_free(wpa_s->confname);
563 wpa_s->confname = NULL;
564
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700565 os_free(wpa_s->confanother);
566 wpa_s->confanother = NULL;
567
Hai Shalomce48b4a2018-09-05 11:41:35 -0700568 os_free(wpa_s->last_con_fail_realm);
569 wpa_s->last_con_fail_realm = NULL;
570 wpa_s->last_con_fail_realm_len = 0;
571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572 wpa_sm_set_eapol(wpa_s->wpa, NULL);
573 eapol_sm_deinit(wpa_s->eapol);
574 wpa_s->eapol = NULL;
575
576 rsn_preauth_deinit(wpa_s->wpa);
577
578#ifdef CONFIG_TDLS
579 wpa_tdls_deinit(wpa_s->wpa);
580#endif /* CONFIG_TDLS */
581
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800582 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800584 ptksa_cache_deinit(wpa_s->ptksa);
585 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700586 wpa_sm_deinit(wpa_s->wpa);
587 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800588 wpa_bssid_ignore_clear(wpa_s);
589
590#ifdef CONFIG_PASN
591 wpas_pasn_auth_stop(wpa_s);
592#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593
594 wpa_bss_deinit(wpa_s);
595
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700596 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 wpa_supplicant_cancel_scan(wpa_s);
598 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800599 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
600#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
601 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
602 wpa_s, NULL);
603#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700605 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700606 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700607
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608 wpas_wps_deinit(wpa_s);
609
610 wpabuf_free(wpa_s->pending_eapol_rx);
611 wpa_s->pending_eapol_rx = NULL;
612
613#ifdef CONFIG_IBSS_RSN
614 ibss_rsn_deinit(wpa_s->ibss_rsn);
615 wpa_s->ibss_rsn = NULL;
616#endif /* CONFIG_IBSS_RSN */
617
618 sme_deinit(wpa_s);
619
620#ifdef CONFIG_AP
621 wpa_supplicant_ap_deinit(wpa_s);
622#endif /* CONFIG_AP */
623
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800626#ifdef CONFIG_OFFCHANNEL
627 offchannel_deinit(wpa_s);
628#endif /* CONFIG_OFFCHANNEL */
629
630 wpa_supplicant_cancel_sched_scan(wpa_s);
631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700632 os_free(wpa_s->next_scan_freqs);
633 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800634
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800635 os_free(wpa_s->manual_scan_freqs);
636 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700637 os_free(wpa_s->select_network_scan_freqs);
638 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800639
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700640 os_free(wpa_s->manual_sched_scan_freqs);
641 wpa_s->manual_sched_scan_freqs = NULL;
642
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800643 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
644
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700645 /*
646 * Need to remove any pending gas-query radio work before the
647 * gas_query_deinit() call because gas_query::work has not yet been set
648 * for works that have not been started. gas_query_free() will be unable
649 * to cancel such pending radio works and once the pending gas-query
650 * radio work eventually gets removed, the deinit notification call to
651 * gas_query_start_cb() would result in dereferencing freed memory.
652 */
653 if (wpa_s->radio)
654 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800655 gas_query_deinit(wpa_s->gas);
656 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700657 gas_server_deinit(wpa_s->gas_server);
658 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800659
660 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700661
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700662 ieee802_1x_dealloc_kay_sm(wpa_s);
663
Dmitry Shmidt04949592012-07-19 12:16:46 -0700664 os_free(wpa_s->bssid_filter);
665 wpa_s->bssid_filter = NULL;
666
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800667 os_free(wpa_s->disallow_aps_bssid);
668 wpa_s->disallow_aps_bssid = NULL;
669 os_free(wpa_s->disallow_aps_ssid);
670 wpa_s->disallow_aps_ssid = NULL;
671
Dmitry Shmidt04949592012-07-19 12:16:46 -0700672 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700673#ifdef CONFIG_WNM
674 wnm_deallocate_memory(wpa_s);
675#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700676
677 ext_password_deinit(wpa_s->ext_pw);
678 wpa_s->ext_pw = NULL;
679
680 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800681 wpa_s->last_gas_resp = NULL;
682 wpabuf_free(wpa_s->prev_gas_resp);
683 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700684
685 os_free(wpa_s->last_scan_res);
686 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800687
688#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700689 if (wpa_s->drv_priv)
690 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700691 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800692#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700693
694 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
695 wpabuf_free(wpa_s->vendor_elem[i]);
696 wpa_s->vendor_elem[i] = NULL;
697 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800698
699 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800700
701 wpa_s->sched_scan_plans_num = 0;
702 os_free(wpa_s->sched_scan_plans);
703 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800704
705#ifdef CONFIG_MBO
706 wpa_s->non_pref_chan_num = 0;
707 os_free(wpa_s->non_pref_chan);
708 wpa_s->non_pref_chan = NULL;
709#endif /* CONFIG_MBO */
710
711 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700712
713 wpabuf_free(wpa_s->lci);
714 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800715 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800716
717#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
718#ifdef CONFIG_MESH
719 {
720 struct external_pmksa_cache *entry;
721
722 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
723 struct external_pmksa_cache,
724 list)) != NULL) {
725 dl_list_del(&entry->list);
726 os_free(entry->pmksa_cache);
727 os_free(entry);
728 }
729 }
730#endif /* CONFIG_MESH */
731#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
732
733 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800734
735 wpabuf_free(wpa_s->ric_ies);
736 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700737
738#ifdef CONFIG_DPP
739 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700740 dpp_global_deinit(wpa_s->dpp);
741 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700742#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800743
744#ifdef CONFIG_PASN
745 wpas_pasn_auth_stop(wpa_s);
746#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800747 wpas_scs_deinit(wpa_s);
748 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749}
750
751
752/**
753 * wpa_clear_keys - Clear keys configured for the driver
754 * @wpa_s: Pointer to wpa_supplicant data
755 * @addr: Previously used BSSID or %NULL if not available
756 *
757 * This function clears the encryption keys that has been previously configured
758 * for the driver.
759 */
760void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
761{
Hai Shalomc3565922019-10-28 11:58:20 -0700762 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763
764 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 for (i = 0; i < max; i++) {
766 if (wpa_s->keys_cleared & BIT(i))
767 continue;
768 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700769 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800770 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700771 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
772 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800773 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700774 if (!(wpa_s->keys_cleared & BIT(0)))
775 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
776 0, NULL, 0, KEY_FLAG_PAIRWISE);
777 if (!(wpa_s->keys_cleared & BIT(15)))
778 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
779 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700780 /* MLME-SETPROTECTION.request(None) */
781 wpa_drv_mlme_setprotection(
782 wpa_s, addr,
783 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
784 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
785 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800786 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787}
788
789
790/**
791 * wpa_supplicant_state_txt - Get the connection state name as a text string
792 * @state: State (wpa_state; WPA_*)
793 * Returns: The state name as a printable text string
794 */
795const char * wpa_supplicant_state_txt(enum wpa_states state)
796{
797 switch (state) {
798 case WPA_DISCONNECTED:
799 return "DISCONNECTED";
800 case WPA_INACTIVE:
801 return "INACTIVE";
802 case WPA_INTERFACE_DISABLED:
803 return "INTERFACE_DISABLED";
804 case WPA_SCANNING:
805 return "SCANNING";
806 case WPA_AUTHENTICATING:
807 return "AUTHENTICATING";
808 case WPA_ASSOCIATING:
809 return "ASSOCIATING";
810 case WPA_ASSOCIATED:
811 return "ASSOCIATED";
812 case WPA_4WAY_HANDSHAKE:
813 return "4WAY_HANDSHAKE";
814 case WPA_GROUP_HANDSHAKE:
815 return "GROUP_HANDSHAKE";
816 case WPA_COMPLETED:
817 return "COMPLETED";
818 default:
819 return "UNKNOWN";
820 }
821}
822
823
824#ifdef CONFIG_BGSCAN
825
Hai Shalom899fcc72020-10-19 14:38:18 -0700826static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
827{
828 if (wpa_s->bgscan_ssid) {
829 bgscan_deinit(wpa_s);
830 wpa_s->bgscan_ssid = NULL;
831 }
832}
833
834
835/**
836 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
837 * @wpa_s: Pointer to the wpa_supplicant data
838 *
839 * Stop, start, or reconfigure the scan parameters depending on the method.
840 */
841void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700842{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800843 const char *name;
844
845 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
846 name = wpa_s->current_ssid->bgscan;
847 else
848 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700849 if (!name || name[0] == '\0') {
850 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800851 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700852 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800853 if (wpas_driver_bss_selection(wpa_s))
854 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800855#ifdef CONFIG_P2P
856 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
857 return;
858#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859
860 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800861 if (wpa_s->current_ssid) {
862 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
864 "bgscan");
865 /*
866 * Live without bgscan; it is only used as a roaming
867 * optimization, so the initial connection is not
868 * affected.
869 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700870 } else {
871 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700873 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
874 0);
875 if (scan_res) {
876 bgscan_notify_scan(wpa_s, scan_res);
877 wpa_scan_results_free(scan_res);
878 }
879 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 } else
881 wpa_s->bgscan_ssid = NULL;
882}
883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884#endif /* CONFIG_BGSCAN */
885
886
Dmitry Shmidt04949592012-07-19 12:16:46 -0700887static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
888{
889 if (autoscan_init(wpa_s, 0))
890 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
891}
892
893
894static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
895{
896 autoscan_deinit(wpa_s);
897}
898
899
900void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
901{
902 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
903 wpa_s->wpa_state == WPA_SCANNING) {
904 autoscan_deinit(wpa_s);
905 wpa_supplicant_start_autoscan(wpa_s);
906 }
907}
908
909
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700910/**
911 * wpa_supplicant_set_state - Set current connection state
912 * @wpa_s: Pointer to wpa_supplicant data
913 * @state: The new connection state
914 *
915 * This function is called whenever the connection state changes, e.g.,
916 * association is completed for WPA/WPA2 4-Way Handshake is started.
917 */
918void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
919 enum wpa_states state)
920{
921 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700922#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700923 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700924#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925
926 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
927 wpa_supplicant_state_txt(wpa_s->wpa_state),
928 wpa_supplicant_state_txt(state));
929
Hai Shalom74f70d42019-02-11 14:42:39 -0800930 if (state == WPA_COMPLETED &&
931 os_reltime_initialized(&wpa_s->roam_start)) {
932 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
933 wpa_s->roam_start.sec = 0;
934 wpa_s->roam_start.usec = 0;
935 wpas_notify_auth_changed(wpa_s);
936 wpas_notify_roam_time(wpa_s);
937 wpas_notify_roam_complete(wpa_s);
938 } else if (state == WPA_DISCONNECTED &&
939 os_reltime_initialized(&wpa_s->roam_start)) {
940 wpa_s->roam_start.sec = 0;
941 wpa_s->roam_start.usec = 0;
942 wpa_s->roam_time.sec = 0;
943 wpa_s->roam_time.usec = 0;
944 wpas_notify_roam_complete(wpa_s);
945 }
946
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800947 if (state == WPA_INTERFACE_DISABLED) {
948 /* Assure normal scan when interface is restored */
949 wpa_s->normal_scans = 0;
950 }
951
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700952 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800953 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700954 /* Reinitialize normal_scan counter */
955 wpa_s->normal_scans = 0;
956 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800957
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700958#ifdef CONFIG_P2P
959 /*
960 * P2PS client has to reply to Probe Request frames received on the
961 * group operating channel. Enable Probe Request frame reporting for
962 * P2P connected client in case p2p_cli_probe configuration property is
963 * set to 1.
964 */
965 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
966 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
967 wpa_s->current_ssid->p2p_group) {
968 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
969 wpa_dbg(wpa_s, MSG_DEBUG,
970 "P2P: Enable CLI Probe Request RX reporting");
971 wpa_s->p2p_cli_probe =
972 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
973 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
974 wpa_dbg(wpa_s, MSG_DEBUG,
975 "P2P: Disable CLI Probe Request RX reporting");
976 wpa_s->p2p_cli_probe = 0;
977 wpa_drv_probe_req_report(wpa_s, 0);
978 }
979 }
980#endif /* CONFIG_P2P */
981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982 if (state != WPA_SCANNING)
983 wpa_supplicant_notify_scanning(wpa_s, 0);
984
985 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700987 int fils_hlp_sent = 0;
988
989#ifdef CONFIG_SME
990 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
991 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
992 fils_hlp_sent = 1;
993#endif /* CONFIG_SME */
994 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
995 wpa_auth_alg_fils(wpa_s->auth_alg))
996 fils_hlp_sent = 1;
997
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700998#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001000 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001001 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001003 ssid && ssid->id_str ? ssid->id_str : "",
1004 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001006 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001007 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_drv_set_operstate(wpa_s, 1);
1010#ifndef IEEE8021X_EAPOL
1011 wpa_drv_set_supp_port(wpa_s, 1);
1012#endif /* IEEE8021X_EAPOL */
1013 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001014 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001016
1017 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018
1019#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1020 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001021 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001022#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001023#ifdef CONFIG_OWE
1024 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1025 wpas_update_owe_connect_params(wpa_s);
1026#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001027#ifdef CONFIG_HS20
1028 hs20_configure_frame_filters(wpa_s);
1029#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1031 state == WPA_ASSOCIATED) {
1032 wpa_s->new_connection = 1;
1033 wpa_drv_set_operstate(wpa_s, 0);
1034#ifndef IEEE8021X_EAPOL
1035 wpa_drv_set_supp_port(wpa_s, 0);
1036#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001037 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 }
1039 wpa_s->wpa_state = state;
1040
1041#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001042 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1043 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001044 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 wpa_supplicant_stop_bgscan(wpa_s);
1046#endif /* CONFIG_BGSCAN */
1047
Hai Shalom5f92bc92019-04-18 11:54:11 -07001048 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049 wpa_supplicant_stop_autoscan(wpa_s);
1050
1051 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1052 wpa_supplicant_start_autoscan(wpa_s);
1053
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001054 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1055 wmm_ac_notify_disassoc(wpa_s);
1056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 if (wpa_s->wpa_state != old_state) {
1058 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1059
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001060 /*
1061 * Notify the P2P Device interface about a state change in one
1062 * of the interfaces.
1063 */
1064 wpas_p2p_indicate_state_change(wpa_s);
1065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 if (wpa_s->wpa_state == WPA_COMPLETED ||
1067 old_state == WPA_COMPLETED)
1068 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001069#ifdef CONFIG_DPP2
1070 if (wpa_s->wpa_state == WPA_COMPLETED)
1071 wpas_dpp_connected(wpa_s);
1072#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073 }
Hai Shalomc3565922019-10-28 11:58:20 -07001074#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1075 if (update_fils_connect_params)
1076 wpas_update_fils_connect_params(wpa_s);
1077#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078}
1079
1080
1081void wpa_supplicant_terminate_proc(struct wpa_global *global)
1082{
1083 int pending = 0;
1084#ifdef CONFIG_WPS
1085 struct wpa_supplicant *wpa_s = global->ifaces;
1086 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001088 if (wpas_wps_terminate_pending(wpa_s) == 1)
1089 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001090#ifdef CONFIG_P2P
1091 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1092 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1093 wpas_p2p_disconnect(wpa_s);
1094#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001095 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 }
1097#endif /* CONFIG_WPS */
1098 if (pending)
1099 return;
1100 eloop_terminate();
1101}
1102
1103
1104static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1105{
1106 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107 wpa_supplicant_terminate_proc(global);
1108}
1109
1110
1111void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1112{
1113 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001114 enum wpa_states new_state;
1115
1116 if (old_state == WPA_SCANNING)
1117 new_state = WPA_SCANNING;
1118 else
1119 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120
1121 wpa_s->pairwise_cipher = 0;
1122 wpa_s->group_cipher = 0;
1123 wpa_s->mgmt_group_cipher = 0;
1124 wpa_s->key_mgmt = 0;
1125 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001126 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127
1128 if (wpa_s->wpa_state != old_state)
1129 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1130}
1131
1132
1133/**
1134 * wpa_supplicant_reload_configuration - Reload configuration data
1135 * @wpa_s: Pointer to wpa_supplicant data
1136 * Returns: 0 on success or -1 if configuration parsing failed
1137 *
1138 * This function can be used to request that the configuration data is reloaded
1139 * (e.g., after configuration file change). This function is reloading
1140 * configuration only for one interface, so this may need to be called multiple
1141 * times if %wpa_supplicant is controlling multiple interfaces and all
1142 * interfaces need reconfiguration.
1143 */
1144int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1145{
1146 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001147 int reconf_ctrl;
1148 int old_ap_scan;
1149
1150 if (wpa_s->confname == NULL)
1151 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001152 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001153 if (conf == NULL) {
1154 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1155 "file '%s' - exiting", wpa_s->confname);
1156 return -1;
1157 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001158 if (wpa_s->confanother &&
1159 !wpa_config_read(wpa_s->confanother, conf)) {
1160 wpa_msg(wpa_s, MSG_ERROR,
1161 "Failed to parse the configuration file '%s' - exiting",
1162 wpa_s->confanother);
1163 return -1;
1164 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 conf->changed_parameters = (unsigned int) -1;
1167
1168 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1169 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1170 os_strcmp(conf->ctrl_interface,
1171 wpa_s->conf->ctrl_interface) != 0);
1172
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001173 if (reconf_ctrl) {
1174 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175 wpa_s->ctrl_iface = NULL;
1176 }
1177
1178 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001179 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001180 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1181 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001182 wpa_supplicant_deauthenticate(wpa_s,
1183 WLAN_REASON_DEAUTH_LEAVING);
1184 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185
1186 /*
1187 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001188 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001190 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1191 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1192 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 /*
1194 * Clear forced success to clear EAP state for next
1195 * authentication.
1196 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001197 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 }
1199 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1200 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001201 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1203 rsn_preauth_deinit(wpa_s->wpa);
1204
1205 old_ap_scan = wpa_s->conf->ap_scan;
1206 wpa_config_free(wpa_s->conf);
1207 wpa_s->conf = conf;
1208 if (old_ap_scan != wpa_s->conf->ap_scan)
1209 wpas_notify_ap_scan_changed(wpa_s);
1210
1211 if (reconf_ctrl)
1212 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1213
1214 wpa_supplicant_update_config(wpa_s);
1215
1216 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001217 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218 wpa_s->reassociate = 1;
1219 wpa_supplicant_req_scan(wpa_s, 0, 0);
1220 }
Hai Shalom60840252021-02-19 19:02:11 -08001221 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1223 return 0;
1224}
1225
1226
1227static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1228{
1229 struct wpa_global *global = signal_ctx;
1230 struct wpa_supplicant *wpa_s;
1231 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1232 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1233 sig);
1234 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1235 wpa_supplicant_terminate_proc(global);
1236 }
1237 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001238
1239 if (wpa_debug_reopen_file() < 0) {
1240 /* Ignore errors since we cannot really do much to fix this */
1241 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1242 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001243}
1244
1245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1247 struct wpa_ssid *ssid,
1248 struct wpa_ie_data *ie)
1249{
1250 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1251 if (ret) {
1252 if (ret == -2) {
1253 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1254 "from association info");
1255 }
1256 return -1;
1257 }
1258
1259 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1260 "cipher suites");
1261 if (!(ie->group_cipher & ssid->group_cipher)) {
1262 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1263 "cipher 0x%x (mask 0x%x) - reject",
1264 ie->group_cipher, ssid->group_cipher);
1265 return -1;
1266 }
1267 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1268 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1269 "cipher 0x%x (mask 0x%x) - reject",
1270 ie->pairwise_cipher, ssid->pairwise_cipher);
1271 return -1;
1272 }
1273 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1275 "management 0x%x (mask 0x%x) - reject",
1276 ie->key_mgmt, ssid->key_mgmt);
1277 return -1;
1278 }
1279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001281 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001282 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1283 "that does not support management frame protection - "
1284 "reject");
1285 return -1;
1286 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287
1288 return 0;
1289}
1290
1291
Hai Shalom021b0b52019-04-10 11:17:58 -07001292static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1293 int freq)
1294{
1295 if (!ie->has_group)
1296 ie->group_cipher = wpa_default_rsn_cipher(freq);
1297 if (!ie->has_pairwise)
1298 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1299 return (ie->group_cipher & ssid->group_cipher) &&
1300 (ie->pairwise_cipher & ssid->pairwise_cipher);
1301}
1302
1303
Hai Shalomc1a21442022-02-04 13:43:00 -08001304void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1305 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1306{
1307 int sel;
1308
1309 sel = ie->mgmt_group_cipher;
1310 if (ssid->group_mgmt_cipher)
1311 sel &= ssid->group_mgmt_cipher;
1312 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1313 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1314 sel = 0;
1315 wpa_dbg(wpa_s, MSG_DEBUG,
1316 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1317 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1318 if (sel & WPA_CIPHER_AES_128_CMAC) {
1319 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1320 wpa_dbg(wpa_s, MSG_DEBUG,
1321 "WPA: using MGMT group cipher AES-128-CMAC");
1322 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1323 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1324 wpa_dbg(wpa_s, MSG_DEBUG,
1325 "WPA: using MGMT group cipher BIP-GMAC-128");
1326 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1327 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1328 wpa_dbg(wpa_s, MSG_DEBUG,
1329 "WPA: using MGMT group cipher BIP-GMAC-256");
1330 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1331 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: using MGMT group cipher BIP-CMAC-256");
1334 } else {
1335 wpa_s->mgmt_group_cipher = 0;
1336 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1337 }
1338 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1339 wpa_s->mgmt_group_cipher);
1340 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1341 wpas_get_ssid_pmf(wpa_s, ssid));
1342}
1343
1344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345/**
1346 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1347 * @wpa_s: Pointer to wpa_supplicant data
1348 * @bss: Scan results for the selected BSS, or %NULL if not available
1349 * @ssid: Configuration data for the selected network
1350 * @wpa_ie: Buffer for the WPA/RSN IE
1351 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1352 * used buffer length in case the functions returns success.
1353 * Returns: 0 on success or -1 on failure
1354 *
1355 * This function is used to configure authentication and encryption parameters
1356 * based on the network configuration and scan result for the selected BSS (if
1357 * available).
1358 */
1359int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1360 struct wpa_bss *bss, struct wpa_ssid *ssid,
1361 u8 *wpa_ie, size_t *wpa_ie_len)
1362{
1363 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001364 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001365 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366
1367 if (bss) {
1368 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1369 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001370 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001371 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001372 } else {
1373 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1374 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375
1376 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1377 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001378 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 (ie.key_mgmt & ssid->key_mgmt)) {
1380 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1381 proto = WPA_PROTO_RSN;
1382 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001383 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384 (ie.group_cipher & ssid->group_cipher) &&
1385 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1386 (ie.key_mgmt & ssid->key_mgmt)) {
1387 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1388 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001389#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001390 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1391 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1392 (ie.group_cipher & ssid->group_cipher) &&
1393 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1394 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001395 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001396 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1398 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1399 (ie.group_cipher & ssid->group_cipher) &&
1400 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1401 (ie.key_mgmt & ssid->key_mgmt)) {
1402 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1403 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001404#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 } else if (bss) {
1406 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001407 wpa_dbg(wpa_s, MSG_DEBUG,
1408 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1409 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1410 ssid->key_mgmt);
1411 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1412 MAC2STR(bss->bssid),
1413 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1414 bss_wpa ? " WPA" : "",
1415 bss_rsn ? " RSN" : "",
1416 bss_osen ? " OSEN" : "");
1417 if (bss_rsn) {
1418 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1419 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1420 wpa_dbg(wpa_s, MSG_DEBUG,
1421 "Could not parse RSN element");
1422 } else {
1423 wpa_dbg(wpa_s, MSG_DEBUG,
1424 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1425 ie.pairwise_cipher, ie.group_cipher,
1426 ie.key_mgmt);
1427 }
1428 }
1429 if (bss_wpa) {
1430 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1431 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1432 wpa_dbg(wpa_s, MSG_DEBUG,
1433 "Could not parse WPA element");
1434 } else {
1435 wpa_dbg(wpa_s, MSG_DEBUG,
1436 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1437 ie.pairwise_cipher, ie.group_cipher,
1438 ie.key_mgmt);
1439 }
1440 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441 return -1;
1442 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001443 if (ssid->proto & WPA_PROTO_OSEN)
1444 proto = WPA_PROTO_OSEN;
1445 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 proto = WPA_PROTO_RSN;
1447 else
1448 proto = WPA_PROTO_WPA;
1449 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1450 os_memset(&ie, 0, sizeof(ie));
1451 ie.group_cipher = ssid->group_cipher;
1452 ie.pairwise_cipher = ssid->pairwise_cipher;
1453 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001454 ie.mgmt_group_cipher = 0;
1455 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1456 if (ssid->group_mgmt_cipher &
1457 WPA_CIPHER_BIP_GMAC_256)
1458 ie.mgmt_group_cipher =
1459 WPA_CIPHER_BIP_GMAC_256;
1460 else if (ssid->group_mgmt_cipher &
1461 WPA_CIPHER_BIP_CMAC_256)
1462 ie.mgmt_group_cipher =
1463 WPA_CIPHER_BIP_CMAC_256;
1464 else if (ssid->group_mgmt_cipher &
1465 WPA_CIPHER_BIP_GMAC_128)
1466 ie.mgmt_group_cipher =
1467 WPA_CIPHER_BIP_GMAC_128;
1468 else
1469 ie.mgmt_group_cipher =
1470 WPA_CIPHER_AES_128_CMAC;
1471 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001472#ifdef CONFIG_OWE
1473 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1474 !ssid->owe_only &&
1475 !bss_wpa && !bss_rsn && !bss_osen) {
1476 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1477 wpa_s->wpa_proto = 0;
1478 *wpa_ie_len = 0;
1479 return 0;
1480 }
1481#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1483 "based on configuration");
1484 } else
1485 proto = ie.proto;
1486 }
1487
1488 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1489 "pairwise %d key_mgmt %d proto %d",
1490 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 if (ssid->ieee80211w) {
1492 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1493 ie.mgmt_group_cipher);
1494 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001496 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1498 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001499 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500
1501 if (bss || !wpa_s->ap_ies_from_associnfo) {
1502 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1503 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1504 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001505 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1506 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1507 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 return -1;
1509 }
1510
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001511#ifdef CONFIG_NO_WPA
1512 wpa_s->group_cipher = WPA_CIPHER_NONE;
1513 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1514#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001516 wpa_dbg(wpa_s, MSG_DEBUG,
1517 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1518 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001519 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1520 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1522 "cipher");
1523 return -1;
1524 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001525 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1526 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001527
1528 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001529 wpa_dbg(wpa_s, MSG_DEBUG,
1530 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1531 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001532 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1533 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1535 "cipher");
1536 return -1;
1537 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001538 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1539 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001540#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541
1542 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001543#ifdef CONFIG_SAE
1544 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1545 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1546#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001547#ifdef CONFIG_IEEE80211R
1548 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1549 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1550 sel &= ~WPA_KEY_MGMT_FT;
1551#endif /* CONFIG_IEEE80211R */
1552 wpa_dbg(wpa_s, MSG_DEBUG,
1553 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1554 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001556#ifdef CONFIG_IEEE80211R
1557#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001558 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1559 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001560 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1561 wpa_dbg(wpa_s, MSG_DEBUG,
1562 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001563 if (!ssid->ft_eap_pmksa_caching &&
1564 pmksa_cache_get_current(wpa_s->wpa)) {
1565 /* PMKSA caching with FT may have interoperability
1566 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001567 wpa_dbg(wpa_s, MSG_DEBUG,
1568 "WPA: Disable PMKSA caching for FT/802.1X connection");
1569 pmksa_cache_clear_current(wpa_s->wpa);
1570 }
1571#endif /* CONFIG_SHA384 */
1572#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001573#ifdef CONFIG_SUITEB192
1574 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1575 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1576 wpa_dbg(wpa_s, MSG_DEBUG,
1577 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1578#endif /* CONFIG_SUITEB192 */
1579#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001580 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1581 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1582 wpa_dbg(wpa_s, MSG_DEBUG,
1583 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001584#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001585#ifdef CONFIG_FILS
1586#ifdef CONFIG_IEEE80211R
1587 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1588 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1589 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1590 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1591 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1592 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1593#endif /* CONFIG_IEEE80211R */
1594 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1595 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1596 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1597 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1598 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1599 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1600#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001602 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1603 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1605 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001606 if (!ssid->ft_eap_pmksa_caching &&
1607 pmksa_cache_get_current(wpa_s->wpa)) {
1608 /* PMKSA caching with FT may have interoperability
1609 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001610 wpa_dbg(wpa_s, MSG_DEBUG,
1611 "WPA: Disable PMKSA caching for FT/802.1X connection");
1612 pmksa_cache_clear_current(wpa_s->wpa);
1613 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001614#endif /* CONFIG_IEEE80211R */
1615#ifdef CONFIG_DPP
1616 } else if (sel & WPA_KEY_MGMT_DPP) {
1617 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1618 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1619#endif /* CONFIG_DPP */
1620#ifdef CONFIG_SAE
1621 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1622 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1623 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1624 } else if (sel & WPA_KEY_MGMT_SAE) {
1625 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1626 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1627#endif /* CONFIG_SAE */
1628#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1630 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1631 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1632#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1634 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1635 wpa_dbg(wpa_s, MSG_DEBUG,
1636 "WPA: using KEY_MGMT 802.1X with SHA256");
1637 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1638 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1639 wpa_dbg(wpa_s, MSG_DEBUG,
1640 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1642 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1643 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1644 } else if (sel & WPA_KEY_MGMT_PSK) {
1645 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1646 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1647 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1648 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1649 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001650#ifdef CONFIG_HS20
1651 } else if (sel & WPA_KEY_MGMT_OSEN) {
1652 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1653 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1654#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001655#ifdef CONFIG_OWE
1656 } else if (sel & WPA_KEY_MGMT_OWE) {
1657 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1658 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1659#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001660 } else {
1661 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1662 "authenticated key management type");
1663 return -1;
1664 }
1665
1666 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1668 wpa_s->pairwise_cipher);
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1670
Hai Shalomc3565922019-10-28 11:58:20 -07001671 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1672 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1673 wpa_msg(wpa_s, MSG_INFO,
1674 "RSN: Management frame protection required but the selected AP does not enable it");
1675 return -1;
1676 }
1677
Hai Shalomc1a21442022-02-04 13:43:00 -08001678 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001679#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001680 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1681 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1682 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001683#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001684 sae_pwe = wpa_s->conf->sae_pwe;
1685 if (ssid->sae_password_id && sae_pwe != 3)
1686 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001687 if (bss && is_6ghz_freq(bss->freq)) {
1688 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1689 sae_pwe = 1;
1690 }
1691#ifdef CONFIG_TESTING_OPTIONS
1692 if (wpa_s->force_hunting_and_pecking_pwe) {
1693 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1694 sae_pwe = 0;
1695 }
1696#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001697 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001698#ifdef CONFIG_SAE_PK
1699 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1700 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1701 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1702 ((ssid->sae_password &&
1703 sae_pk_valid_password(ssid->sae_password)) ||
1704 (!ssid->sae_password && ssid->passphrase &&
1705 sae_pk_valid_password(ssid->passphrase))));
1706#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001707#ifdef CONFIG_TESTING_OPTIONS
1708 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1709 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001710 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1711 wpa_s->oci_freq_override_eapol);
1712 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1713 wpa_s->oci_freq_override_eapol_g2);
1714 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1715 wpa_s->oci_freq_override_ft_assoc);
1716 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1717 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001718#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001719
1720 /* Extended Key ID is only supported in infrastructure BSS so far */
1721 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1722 (ssid->proto & WPA_PROTO_RSN) &&
1723 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1724 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1725 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1726 int use_ext_key_id = 0;
1727
1728 wpa_msg(wpa_s, MSG_DEBUG,
1729 "WPA: Enable Extended Key ID support");
1730 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1731 wpa_s->conf->extended_key_id);
1732 if (bss_rsn &&
1733 wpa_s->conf->extended_key_id &&
1734 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1735 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1736 use_ext_key_id = 1;
1737 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1738 use_ext_key_id);
1739 } else {
1740 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1741 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1742 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001743
1744 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1745 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1746 return -1;
1747 }
1748
Hai Shalomc3565922019-10-28 11:58:20 -07001749 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1750 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1751 &wpa_s->rsnxe_len)) {
1752 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1753 return -1;
1754 }
1755
Hai Shalom021b0b52019-04-10 11:17:58 -07001756 if (0) {
1757#ifdef CONFIG_DPP
1758 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1759 /* Use PMK from DPP network introduction (PMKSA entry) */
1760 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001761#ifdef CONFIG_DPP2
1762 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1763#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001764#endif /* CONFIG_DPP */
1765 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001766 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001767 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001768
Roshan Pius3a1667e2018-07-03 15:17:14 -07001769 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1770 WPA_KEY_MGMT_FT_PSK |
1771 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1772
1773 if (ssid->psk_set && !sae_only) {
1774 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1775 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001776 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1777 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001778 psk_set = 1;
1779 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001780
Roshan Pius3a1667e2018-07-03 15:17:14 -07001781 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1782 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783 psk_set = 1;
1784
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001785#ifndef CONFIG_NO_PBKDF2
1786 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001787 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001788 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001789 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1790 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001791 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1792 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001793 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001794 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001795 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001796 }
1797#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001798#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001799 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001800 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1801 ssid->ext_psk);
1802 char pw_str[64 + 1];
1803 u8 psk[PMK_LEN];
1804
1805 if (pw == NULL) {
1806 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1807 "found from external storage");
1808 return -1;
1809 }
1810
1811 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1812 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1813 "PSK length %d in external storage",
1814 (int) wpabuf_len(pw));
1815 ext_password_free(pw);
1816 return -1;
1817 }
1818
1819 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1820 pw_str[wpabuf_len(pw)] = '\0';
1821
1822#ifndef CONFIG_NO_PBKDF2
1823 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1824 {
1825 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1826 4096, psk, PMK_LEN);
1827 os_memset(pw_str, 0, sizeof(pw_str));
1828 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1829 "external passphrase)",
1830 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001831 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1832 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001833 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001834 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001835 } else
1836#endif /* CONFIG_NO_PBKDF2 */
1837 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1838 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1839 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1840 "Invalid PSK hex string");
1841 os_memset(pw_str, 0, sizeof(pw_str));
1842 ext_password_free(pw);
1843 return -1;
1844 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001845 wpa_hexdump_key(MSG_MSGDUMP,
1846 "PSK (from external PSK)",
1847 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001848 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1849 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001850 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001851 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001852 } else {
1853 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1854 "PSK available");
1855 os_memset(pw_str, 0, sizeof(pw_str));
1856 ext_password_free(pw);
1857 return -1;
1858 }
1859
1860 os_memset(pw_str, 0, sizeof(pw_str));
1861 ext_password_free(pw);
1862 }
1863#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001864
1865 if (!psk_set) {
1866 wpa_msg(wpa_s, MSG_INFO,
1867 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001868 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001869 return -1;
1870 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001871#ifdef CONFIG_OWE
1872 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1873 /* OWE Diffie-Hellman exchange in (Re)Association
1874 * Request/Response frames set the PMK, so do not override it
1875 * here. */
1876#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001877 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1879
Hai Shalomfdcde762020-04-02 11:19:20 -07001880 if (ssid->mode != WPAS_MODE_IBSS &&
1881 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1882 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1883 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1884 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1885 wpa_msg(wpa_s, MSG_INFO,
1886 "Disable PTK0 rekey support - replaced with reconnect");
1887 wpa_s->deny_ptk0_rekey = 1;
1888 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1889 } else {
1890 wpa_s->deny_ptk0_rekey = 0;
1891 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1892 }
1893
Vinayak Yadawad14709082022-03-17 14:25:11 +05301894#ifdef CONFIG_DRIVER_NL80211_BRCM
1895 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
1896 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt)) {
1897 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1898 wpa_dbg(wpa_s, MSG_INFO,
1899 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1900 }
1901#endif /* CONFIG_DRIVER_NL80211_BRCM */
1902
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001903 return 0;
1904}
1905
1906
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001907static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1908{
Hai Shalomc1a21442022-02-04 13:43:00 -08001909 bool scs = true, mscs = true;
1910
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001911 *pos = 0x00;
1912
1913 switch (idx) {
1914 case 0: /* Bits 0-7 */
1915 break;
1916 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001917 if (wpa_s->conf->coloc_intf_reporting) {
1918 /* Bit 13 - Collocated Interference Reporting */
1919 *pos |= 0x20;
1920 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001921 break;
1922 case 2: /* Bits 16-23 */
1923#ifdef CONFIG_WNM
1924 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001925 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001926 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001927#endif /* CONFIG_WNM */
1928 break;
1929 case 3: /* Bits 24-31 */
1930#ifdef CONFIG_WNM
1931 *pos |= 0x02; /* Bit 25 - SSID List */
1932#endif /* CONFIG_WNM */
1933#ifdef CONFIG_INTERWORKING
1934 if (wpa_s->conf->interworking)
1935 *pos |= 0x80; /* Bit 31 - Interworking */
1936#endif /* CONFIG_INTERWORKING */
1937 break;
1938 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001939#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001940 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001941 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001942#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001943 break;
1944 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001945#ifdef CONFIG_HS20
1946 if (wpa_s->conf->hs20)
1947 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1948#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001949#ifdef CONFIG_MBO
1950 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1951#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001952 break;
1953 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001954#ifdef CONFIG_TESTING_OPTIONS
1955 if (wpa_s->disable_scs_support)
1956 scs = false;
1957#endif /* CONFIG_TESTING_OPTIONS */
1958 if (scs)
1959 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001960 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001961 case 7: /* Bits 56-63 */
1962 break;
1963 case 8: /* Bits 64-71 */
1964 if (wpa_s->conf->ftm_responder)
1965 *pos |= 0x40; /* Bit 70 - FTM responder */
1966 if (wpa_s->conf->ftm_initiator)
1967 *pos |= 0x80; /* Bit 71 - FTM initiator */
1968 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001969 case 9: /* Bits 72-79 */
1970#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001971 if (!wpa_s->disable_fils)
1972 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001973#endif /* CONFIG_FILS */
1974 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001975 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001976#ifdef CONFIG_TESTING_OPTIONS
1977 if (wpa_s->disable_mscs_support)
1978 mscs = false;
1979#endif /* CONFIG_TESTING_OPTIONS */
1980 if (mscs)
1981 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001982 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001983 }
1984}
1985
1986
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001987int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001988{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001989 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001990 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001991
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001992 if (len < wpa_s->extended_capa_len)
1993 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001994 if (buflen < (size_t) len + 2) {
1995 wpa_printf(MSG_INFO,
1996 "Not enough room for building extended capabilities element");
1997 return -1;
1998 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001999
2000 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002001 *pos++ = len;
2002 for (i = 0; i < len; i++, pos++) {
2003 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002004
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002005 if (i < wpa_s->extended_capa_len) {
2006 *pos &= ~wpa_s->extended_capa_mask[i];
2007 *pos |= wpa_s->extended_capa[i];
2008 }
2009 }
2010
2011 while (len > 0 && buf[1 + len] == 0) {
2012 len--;
2013 buf[1] = len;
2014 }
2015 if (len == 0)
2016 return 0;
2017
2018 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002019}
2020
2021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002022static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2023 struct wpa_bss *test_bss)
2024{
2025 struct wpa_bss *bss;
2026
2027 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2028 if (bss == test_bss)
2029 return 1;
2030 }
2031
2032 return 0;
2033}
2034
2035
2036static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2037 struct wpa_ssid *test_ssid)
2038{
2039 struct wpa_ssid *ssid;
2040
2041 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2042 if (ssid == test_ssid)
2043 return 1;
2044 }
2045
2046 return 0;
2047}
2048
2049
2050int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2051 struct wpa_ssid *test_ssid)
2052{
2053 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2054 return 0;
2055
2056 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2057}
2058
2059
2060void wpas_connect_work_free(struct wpa_connect_work *cwork)
2061{
2062 if (cwork == NULL)
2063 return;
2064 os_free(cwork);
2065}
2066
2067
2068void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2069{
2070 struct wpa_connect_work *cwork;
2071 struct wpa_radio_work *work = wpa_s->connect_work;
2072
2073 if (!work)
2074 return;
2075
2076 wpa_s->connect_work = NULL;
2077 cwork = work->ctx;
2078 work->ctx = NULL;
2079 wpas_connect_work_free(cwork);
2080 radio_work_done(work);
2081}
2082
2083
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002084int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2085{
2086 struct os_reltime now;
2087 u8 addr[ETH_ALEN];
2088
2089 os_get_reltime(&now);
2090 if (wpa_s->last_mac_addr_style == style &&
2091 wpa_s->last_mac_addr_change.sec != 0 &&
2092 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2093 wpa_s->conf->rand_addr_lifetime)) {
2094 wpa_msg(wpa_s, MSG_DEBUG,
2095 "Previously selected random MAC address has not yet expired");
2096 return 0;
2097 }
2098
2099 switch (style) {
2100 case 1:
2101 if (random_mac_addr(addr) < 0)
2102 return -1;
2103 break;
2104 case 2:
2105 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2106 if (random_mac_addr_keep_oui(addr) < 0)
2107 return -1;
2108 break;
2109 default:
2110 return -1;
2111 }
2112
2113 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2114 wpa_msg(wpa_s, MSG_INFO,
2115 "Failed to set random MAC address");
2116 return -1;
2117 }
2118
2119 os_get_reltime(&wpa_s->last_mac_addr_change);
2120 wpa_s->mac_addr_changed = 1;
2121 wpa_s->last_mac_addr_style = style;
2122
2123 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2124 wpa_msg(wpa_s, MSG_INFO,
2125 "Could not update MAC address information");
2126 return -1;
2127 }
2128
2129 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2130 MAC2STR(addr));
2131
2132 return 0;
2133}
2134
2135
2136int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2137{
2138 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2139 !wpa_s->conf->preassoc_mac_addr)
2140 return 0;
2141
2142 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2143}
2144
2145
Hai Shalomc3565922019-10-28 11:58:20 -07002146static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2147{
2148#ifdef CONFIG_SAE
2149 int *groups = conf->sae_groups;
2150 int default_groups[] = { 19, 20, 21, 0 };
2151 const char *password;
2152
2153 if (!groups || groups[0] <= 0)
2154 groups = default_groups;
2155
2156 password = ssid->sae_password;
2157 if (!password)
2158 password = ssid->passphrase;
2159
Hai Shalom899fcc72020-10-19 14:38:18 -07002160 if (!password ||
2161 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2162 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002163 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002164 /* PT derivation not needed */
2165 sae_deinit_pt(ssid->pt);
2166 ssid->pt = NULL;
2167 return;
2168 }
2169
2170 if (ssid->pt)
2171 return; /* PT already derived */
2172 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2173 (const u8 *) password, os_strlen(password),
2174 ssid->sae_password_id);
2175#endif /* CONFIG_SAE */
2176}
2177
2178
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002179static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2180{
2181#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2182 os_free(wpa_s->sme.sae_rejected_groups);
2183 wpa_s->sme.sae_rejected_groups = NULL;
2184#ifdef CONFIG_TESTING_OPTIONS
2185 if (wpa_s->extra_sae_rejected_groups) {
2186 int i, *groups = wpa_s->extra_sae_rejected_groups;
2187
2188 for (i = 0; groups[i]; i++) {
2189 wpa_printf(MSG_DEBUG,
2190 "TESTING: Indicate rejection of an extra SAE group %d",
2191 groups[i]);
2192 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2193 groups[i]);
2194 }
2195 }
2196#endif /* CONFIG_TESTING_OPTIONS */
2197#endif /* CONFIG_SAE && CONFIG_SME */
2198}
2199
2200
Hai Shalom60840252021-02-19 19:02:11 -08002201int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2202{
2203 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2204 wpa_msg(wpa_s, MSG_INFO,
2205 "Could not restore permanent MAC address");
2206 return -1;
2207 }
2208 wpa_s->mac_addr_changed = 0;
2209 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2210 wpa_msg(wpa_s, MSG_INFO,
2211 "Could not update MAC address information");
2212 return -1;
2213 }
2214 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2215 return 0;
2216}
2217
2218
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002219static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2220
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221/**
2222 * wpa_supplicant_associate - Request association
2223 * @wpa_s: Pointer to wpa_supplicant data
2224 * @bss: Scan results for the selected BSS, or %NULL if not available
2225 * @ssid: Configuration data for the selected network
2226 *
2227 * This function is used to request %wpa_supplicant to associate with a BSS.
2228 */
2229void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2230 struct wpa_bss *bss, struct wpa_ssid *ssid)
2231{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002232 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002233 int rand_style;
2234
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002235 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002236 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002237
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002238 /*
2239 * If we are starting a new connection, any previously pending EAPOL
2240 * RX cannot be valid anymore.
2241 */
2242 wpabuf_free(wpa_s->pending_eapol_rx);
2243 wpa_s->pending_eapol_rx = NULL;
2244
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002245 if (ssid->mac_addr == -1)
2246 rand_style = wpa_s->conf->mac_addr;
2247 else
2248 rand_style = ssid->mac_addr;
2249
Hai Shalomfdcde762020-04-02 11:19:20 -07002250 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002251 wmm_ac_clear_saved_tspecs(wpa_s);
2252 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002253 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002254#ifdef CONFIG_TESTING_OPTIONS
2255 wpa_s->testing_resend_assoc = 0;
2256#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002257
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002258 if (wpa_s->last_ssid == ssid) {
2259 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002260 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002261 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2262 wmm_ac_save_tspecs(wpa_s);
2263 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002264 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2265 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002266 }
Hai Shalomc3565922019-10-28 11:58:20 -07002267 } else {
2268#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002269 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002270#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002271 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002272#ifdef CONFIG_SAE
2273 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2274#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002275
2276 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002277 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2278 return;
2279 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002280 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002281 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002282 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002283 }
2284 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002285
2286#ifdef CONFIG_IBSS_RSN
2287 ibss_rsn_deinit(wpa_s->ibss_rsn);
2288 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289#else /* CONFIG_IBSS_RSN */
2290 if (ssid->mode == WPAS_MODE_IBSS &&
2291 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2292 wpa_msg(wpa_s, MSG_INFO,
2293 "IBSS RSN not supported in the build");
2294 return;
2295 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296#endif /* CONFIG_IBSS_RSN */
2297
2298 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2299 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2300#ifdef CONFIG_AP
2301 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2302 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2303 "mode");
2304 return;
2305 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002306 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2307 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002308 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2309 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002310 return;
2311 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 wpa_s->current_bss = bss;
2313#else /* CONFIG_AP */
2314 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2315 "the build");
2316#endif /* CONFIG_AP */
2317 return;
2318 }
2319
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002320 if (ssid->mode == WPAS_MODE_MESH) {
2321#ifdef CONFIG_MESH
2322 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2323 wpa_msg(wpa_s, MSG_INFO,
2324 "Driver does not support mesh mode");
2325 return;
2326 }
2327 if (bss)
2328 ssid->frequency = bss->freq;
2329 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2330 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2331 return;
2332 }
2333 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002334#else /* CONFIG_MESH */
2335 wpa_msg(wpa_s, MSG_ERROR,
2336 "mesh mode support not included in the build");
2337#endif /* CONFIG_MESH */
2338 return;
2339 }
2340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002341 /*
2342 * Set WPA state machine configuration to match the selected network now
2343 * so that the information is available before wpas_start_assoc_cb()
2344 * gets called. This is needed at least for RSN pre-authentication where
2345 * candidate APs are added to a list based on scan result processing
2346 * before completion of the first association.
2347 */
2348 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2349
2350#ifdef CONFIG_DPP
2351 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2352 return;
2353#endif /* CONFIG_DPP */
2354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002355#ifdef CONFIG_TDLS
2356 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002357 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358#endif /* CONFIG_TDLS */
2359
Hai Shalomc3565922019-10-28 11:58:20 -07002360#ifdef CONFIG_MBO
2361 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2362#endif /* CONFIG_MBO */
2363
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002365 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 sme_authenticate(wpa_s, bss, ssid);
2367 return;
2368 }
2369
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002370 if (wpa_s->connect_work) {
2371 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2372 return;
2373 }
2374
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002375 if (radio_work_pending(wpa_s, "connect")) {
2376 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2377 return;
2378 }
2379
Dmitry Shmidt29333592017-01-09 12:27:11 -08002380#ifdef CONFIG_SME
2381 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2382 /* Clear possibly set auth_alg, if any, from last attempt. */
2383 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2384 }
2385#endif /* CONFIG_SME */
2386
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002387 wpas_abort_ongoing_scan(wpa_s);
2388
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002389 cwork = os_zalloc(sizeof(*cwork));
2390 if (cwork == NULL)
2391 return;
2392
2393 cwork->bss = bss;
2394 cwork->ssid = ssid;
2395
2396 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2397 wpas_start_assoc_cb, cwork) < 0) {
2398 os_free(cwork);
2399 }
2400}
2401
2402
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002403static int bss_is_ibss(struct wpa_bss *bss)
2404{
2405 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2406 IEEE80211_CAP_IBSS;
2407}
2408
2409
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002410static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2411 const struct wpa_ssid *ssid)
2412{
2413 enum hostapd_hw_mode hw_mode;
2414 struct hostapd_hw_modes *mode = NULL;
2415 u8 channel;
2416 int i;
2417
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002418 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2419 if (hw_mode == NUM_HOSTAPD_MODES)
2420 return 0;
2421 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2422 if (wpa_s->hw.modes[i].mode == hw_mode) {
2423 mode = &wpa_s->hw.modes[i];
2424 break;
2425 }
2426 }
2427
2428 if (!mode)
2429 return 0;
2430
2431 return mode->vht_capab != 0;
2432}
2433
2434
Hai Shalomc1a21442022-02-04 13:43:00 -08002435static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2436{
2437 int i;
2438
2439 for (i = channel; i < channel + 16; i += 4) {
2440 struct hostapd_channel_data *chan;
2441
2442 chan = hw_get_channel_chan(mode, i, NULL);
2443 if (!chan ||
2444 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2445 return false;
2446 }
2447
2448 return true;
2449}
2450
2451
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002452void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2453 const struct wpa_ssid *ssid,
2454 struct hostapd_freq_params *freq)
2455{
Hai Shalom81f62d82019-07-22 12:10:00 -07002456 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002457 enum hostapd_hw_mode hw_mode;
2458 struct hostapd_hw_modes *mode = NULL;
2459 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2460 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002461 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2462 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2463 6595, 6675, 6755, 6835, 6915, 6995 };
2464 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002465 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2466 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002467 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002468 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002469 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002470 int chwidth, seg0, seg1;
2471 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002472 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002473
2474 freq->freq = ssid->frequency;
2475
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002476 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2477 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2478
2479 if (ssid->mode != WPAS_MODE_IBSS)
2480 break;
2481
2482 /* Don't adjust control freq in case of fixed_freq */
2483 if (ssid->fixed_freq)
2484 break;
2485
2486 if (!bss_is_ibss(bss))
2487 continue;
2488
2489 if (ssid->ssid_len == bss->ssid_len &&
2490 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2491 wpa_printf(MSG_DEBUG,
2492 "IBSS already found in scan results, adjust control freq: %d",
2493 bss->freq);
2494 freq->freq = bss->freq;
2495 obss_scan = 0;
2496 break;
2497 }
2498 }
2499
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002500 /* For IBSS check HT_IBSS flag */
2501 if (ssid->mode == WPAS_MODE_IBSS &&
2502 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2503 return;
2504
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002505 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2506 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2507 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2508 wpa_printf(MSG_DEBUG,
2509 "IBSS: WEP/TKIP detected, do not try to enable HT");
2510 return;
2511 }
2512
2513 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002514 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2515 if (wpa_s->hw.modes[i].mode == hw_mode) {
2516 mode = &wpa_s->hw.modes[i];
2517 break;
2518 }
2519 }
2520
2521 if (!mode)
2522 return;
2523
Hai Shalom60840252021-02-19 19:02:11 -08002524 freq->channel = channel;
2525
Hai Shalomc3565922019-10-28 11:58:20 -07002526 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2527 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002528
Hai Shalomc1a21442022-02-04 13:43:00 -08002529 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2530 * However, HE is mandatory for 6 GHz.
2531 */
2532 is_6ghz = is_6ghz_freq(freq->freq);
2533 if (is_6ghz)
2534 goto skip_to_6ghz;
2535
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002536#ifdef CONFIG_HT_OVERRIDES
2537 if (ssid->disable_ht) {
2538 freq->ht_enabled = 0;
2539 return;
2540 }
2541#endif /* CONFIG_HT_OVERRIDES */
2542
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002543 freq->ht_enabled = ht_supported(mode);
2544 if (!freq->ht_enabled)
2545 return;
2546
Hai Shalomc3565922019-10-28 11:58:20 -07002547 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2548 if (is_24ghz)
2549 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002550#ifdef CONFIG_HE_OVERRIDES
2551 if (is_24ghz && ssid->disable_he)
2552 freq->he_enabled = 0;
2553#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002554
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002555 /* Setup higher BW only for 5 GHz */
2556 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2557 return;
2558
2559 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2560 pri_chan = &mode->channels[chan_idx];
2561 if (pri_chan->chan == channel)
2562 break;
2563 pri_chan = NULL;
2564 }
2565 if (!pri_chan)
2566 return;
2567
2568 /* Check primary channel flags */
2569 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2570 return;
2571
Hai Shalom74f70d42019-02-11 14:42:39 -08002572 freq->channel = pri_chan->chan;
2573
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002574#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002575 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002576#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002577 if (ssid->disable_vht)
2578 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002579#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002580 goto skip_ht40;
2581 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002582#endif /* CONFIG_HT_OVERRIDES */
2583
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002584 /* Check/setup HT40+/HT40- */
2585 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2586 if (ht40plus[j] == channel) {
2587 ht40 = 1;
2588 break;
2589 }
2590 }
2591
2592 /* Find secondary channel */
2593 for (i = 0; i < mode->num_channels; i++) {
2594 sec_chan = &mode->channels[i];
2595 if (sec_chan->chan == channel + ht40 * 4)
2596 break;
2597 sec_chan = NULL;
2598 }
2599 if (!sec_chan)
2600 return;
2601
2602 /* Check secondary channel flags */
2603 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2604 return;
2605
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002606 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002607 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2608 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002609 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002610 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2611 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002612 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002613 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002614
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002615 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002616 struct wpa_scan_results *scan_res;
2617
2618 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2619 if (scan_res == NULL) {
2620 /* Back to HT20 */
2621 freq->sec_channel_offset = 0;
2622 return;
2623 }
2624
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002625 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002626 switch (res) {
2627 case 0:
2628 /* Back to HT20 */
2629 freq->sec_channel_offset = 0;
2630 break;
2631 case 1:
2632 /* Configuration allowed */
2633 break;
2634 case 2:
2635 /* Switch pri/sec channels */
2636 freq->freq = hw_get_freq(mode, sec_chan->chan);
2637 freq->sec_channel_offset = -freq->sec_channel_offset;
2638 freq->channel = sec_chan->chan;
2639 break;
2640 default:
2641 freq->sec_channel_offset = 0;
2642 break;
2643 }
2644
2645 wpa_scan_results_free(scan_res);
2646 }
2647
Hai Shalom74f70d42019-02-11 14:42:39 -08002648#ifdef CONFIG_HT_OVERRIDES
2649skip_ht40:
2650#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002651 wpa_printf(MSG_DEBUG,
2652 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2653 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002654
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002655 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002656 return;
2657
2658 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002659 if (ssid->mode == WPAS_MODE_IBSS &&
2660 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002661 return;
2662
Paul Stewart092955c2017-02-06 09:13:09 -08002663#ifdef CONFIG_VHT_OVERRIDES
2664 if (ssid->disable_vht) {
2665 freq->vht_enabled = 0;
2666 return;
2667 }
2668#endif /* CONFIG_VHT_OVERRIDES */
2669
Hai Shalomc1a21442022-02-04 13:43:00 -08002670skip_to_6ghz:
2671 vht_freq = *freq;
2672
2673 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002674 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002675 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002676 return;
2677
Hai Shalomfdcde762020-04-02 11:19:20 -07002678 /* Enable HE with VHT for 5 GHz */
2679 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002680
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002681 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002682 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2683 if (freq->freq >= bw80[j] &&
2684 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002685 break;
2686 }
2687
Hai Shalomc1a21442022-02-04 13:43:00 -08002688 if (j == ARRAY_SIZE(bw80) ||
2689 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002690 return;
2691
Hai Shalomc1a21442022-02-04 13:43:00 -08002692 /* Back to HT configuration if channel not usable */
2693 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2694 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002695
Hai Shalom81f62d82019-07-22 12:10:00 -07002696 chwidth = CHANWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002697 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002698 seg1 = 0;
2699
Hai Shalomc1a21442022-02-04 13:43:00 -08002700 if ((mode->he_capab[ieee80211_mode].phy_cap[
2701 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2702 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2703 /* In 160 MHz, the initial four 20 MHz channels were validated
2704 * above; check the remaining four 20 MHz channels for the total
2705 * of 160 MHz bandwidth.
2706 */
2707 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2708 return;
2709
2710 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2711 if (freq->freq == bw160[j]) {
2712 chwidth = CHANWIDTH_160MHZ;
2713 seg0 = channel + 14;
2714 break;
2715 }
2716 }
2717 }
2718
Hai Shalom81f62d82019-07-22 12:10:00 -07002719 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002720 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002721 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002722 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002723 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002724 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002725
2726 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2727 NUM_HOSTAPD_MODES)
2728 return;
2729
2730 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002731 struct hostapd_channel_data *chan;
2732
2733 chan = hw_get_channel_chan(mode, i, NULL);
2734 if (!chan)
2735 continue;
2736
2737 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2738 HOSTAPD_CHAN_NO_IR |
2739 HOSTAPD_CHAN_RADAR))
2740 continue;
2741
2742 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002743 chwidth = CHANWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002744 if (!is_6ghz)
2745 vht_caps |=
2746 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2747 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002748 }
2749
Hai Shalom81f62d82019-07-22 12:10:00 -07002750 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002751 break;
2752 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002753 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002754 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002755 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002756 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2757 seg0 = 50;
2758 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002759 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002760 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2761 seg0 = 114;
2762 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002763 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2764 chwidth = CHANWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002765 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002766#ifdef CONFIG_HT_OVERRIDES
2767 if (ssid->disable_ht40)
2768 seg0 = 0;
2769#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002770 }
2771
Hai Shalomfdcde762020-04-02 11:19:20 -07002772#ifdef CONFIG_HE_OVERRIDES
2773 if (ssid->disable_he) {
2774 vht_freq.he_enabled = 0;
2775 freq->he_enabled = 0;
2776 }
2777#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002778 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002779 freq->channel, ssid->enable_edmg,
2780 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002781 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002782 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002783 chwidth, seg0, seg1, vht_caps,
2784 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002785 return;
2786
2787 *freq = vht_freq;
2788
2789 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2790 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002791}
2792
2793
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002794#ifdef CONFIG_FILS
2795static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2796 size_t ie_buf_len)
2797{
2798 struct fils_hlp_req *req;
2799 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2800 const u8 *pos;
2801 u8 *buf = ie_buf;
2802
2803 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2804 list) {
2805 rem_len = ie_buf_len - ie_len;
2806 pos = wpabuf_head(req->pkt);
2807 hdr_len = 1 + 2 * ETH_ALEN + 6;
2808 hlp_len = wpabuf_len(req->pkt);
2809
2810 if (rem_len < 2 + hdr_len + hlp_len) {
2811 wpa_printf(MSG_ERROR,
2812 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2813 (unsigned long) rem_len,
2814 (unsigned long) (2 + hdr_len + hlp_len));
2815 break;
2816 }
2817
2818 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2819 /* Element ID */
2820 *buf++ = WLAN_EID_EXTENSION;
2821 /* Length */
2822 *buf++ = len;
2823 /* Element ID Extension */
2824 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2825 /* Destination MAC address */
2826 os_memcpy(buf, req->dst, ETH_ALEN);
2827 buf += ETH_ALEN;
2828 /* Source MAC address */
2829 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2830 buf += ETH_ALEN;
2831 /* LLC/SNAP Header */
2832 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2833 buf += 6;
2834 /* HLP Packet */
2835 os_memcpy(buf, pos, len - hdr_len);
2836 buf += len - hdr_len;
2837 pos += len - hdr_len;
2838
2839 hlp_len -= len - hdr_len;
2840 ie_len += 2 + len;
2841 rem_len -= 2 + len;
2842
2843 while (hlp_len) {
2844 len = (hlp_len > 255) ? 255 : hlp_len;
2845 if (rem_len < 2 + len)
2846 break;
2847 *buf++ = WLAN_EID_FRAGMENT;
2848 *buf++ = len;
2849 os_memcpy(buf, pos, len);
2850 buf += len;
2851 pos += len;
2852
2853 hlp_len -= len;
2854 ie_len += 2 + len;
2855 rem_len -= 2 + len;
2856 }
2857 }
2858
2859 return ie_len;
2860}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002861
2862
2863int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2864{
2865 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2866 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2867 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2868 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2869}
2870
2871
2872int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2873{
2874#ifdef CONFIG_FILS_SK_PFS
2875 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2876 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2877#else /* CONFIG_FILS_SK_PFS */
2878 return 0;
2879#endif /* CONFIG_FILS_SK_PFS */
2880}
2881
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002882#endif /* CONFIG_FILS */
2883
2884
Hai Shalomc1a21442022-02-04 13:43:00 -08002885static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2886 struct wpa_bss *bss,
2887 u8 *wpa_ie, size_t wpa_ie_len,
2888 size_t max_wpa_ie_len)
2889{
2890 struct wpabuf *wfa_ie = NULL;
2891 u8 wfa_capa[1];
2892 size_t wfa_ie_len, buf_len;
2893
2894 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2895 if (wpa_s->enable_dscp_policy_capa)
2896 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2897
2898 if (!wfa_capa[0])
2899 return wpa_ie_len;
2900
2901 /* Wi-Fi Alliance element */
2902 buf_len = 1 + /* Element ID */
2903 1 + /* Length */
2904 3 + /* OUI */
2905 1 + /* OUI Type */
2906 1 + /* Capabilities Length */
2907 sizeof(wfa_capa); /* Capabilities */
2908 wfa_ie = wpabuf_alloc(buf_len);
2909 if (!wfa_ie)
2910 return wpa_ie_len;
2911
2912 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2913 wpabuf_put_u8(wfa_ie, buf_len - 2);
2914 wpabuf_put_be24(wfa_ie, OUI_WFA);
2915 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2916 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2917 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2918
2919 wfa_ie_len = wpabuf_len(wfa_ie);
2920 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2921 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2922 wfa_ie);
2923 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2924 wfa_ie_len);
2925 wpa_ie_len += wfa_ie_len;
2926 }
2927
2928 wpabuf_free(wfa_ie);
2929 return wpa_ie_len;
2930}
2931
2932
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002933static u8 * wpas_populate_assoc_ies(
2934 struct wpa_supplicant *wpa_s,
2935 struct wpa_bss *bss, struct wpa_ssid *ssid,
2936 struct wpa_driver_associate_params *params,
2937 enum wpa_drv_update_connect_params_mask *mask)
2938{
2939 u8 *wpa_ie;
2940 size_t max_wpa_ie_len = 500;
2941 size_t wpa_ie_len;
2942 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002943#ifdef CONFIG_MBO
2944 const u8 *mbo_ie;
2945#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302946#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2947 int pmksa_cached = 0;
2948#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002949#ifdef CONFIG_FILS
2950 const u8 *realm, *username, *rrk;
2951 size_t realm_len, username_len, rrk_len;
2952 u16 next_seq_num;
2953 struct fils_hlp_req *req;
2954
2955 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2956 list) {
2957 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2958 2 + 2 * wpabuf_len(req->pkt) / 255;
2959 }
2960#endif /* CONFIG_FILS */
2961
2962 wpa_ie = os_malloc(max_wpa_ie_len);
2963 if (!wpa_ie) {
2964 wpa_printf(MSG_ERROR,
2965 "Failed to allocate connect IE buffer for %lu bytes",
2966 (unsigned long) max_wpa_ie_len);
2967 return NULL;
2968 }
2969
2970 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2971 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2972 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2973 int try_opportunistic;
2974 const u8 *cache_id = NULL;
2975
2976 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2977 wpa_s->conf->okc :
2978 ssid->proactive_key_caching) &&
2979 (ssid->proto & WPA_PROTO_RSN);
2980#ifdef CONFIG_FILS
2981 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2982 cache_id = wpa_bss_get_fils_cache_id(bss);
2983#endif /* CONFIG_FILS */
2984 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2985 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002986 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002987 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302988#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2989 pmksa_cached = 1;
2990#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002991 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002992 wpa_ie_len = max_wpa_ie_len;
2993 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2994 wpa_ie, &wpa_ie_len)) {
2995 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2996 "key management and encryption suites");
2997 os_free(wpa_ie);
2998 return NULL;
2999 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003000#ifdef CONFIG_HS20
3001 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3002 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3003 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3004 wpa_ie_len = max_wpa_ie_len;
3005 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3006 wpa_ie, &wpa_ie_len)) {
3007 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3008 "key management and encryption suites");
3009 os_free(wpa_ie);
3010 return NULL;
3011 }
3012#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003013 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3014 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3015 /*
3016 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3017 * use non-WPA since the scan results did not indicate that the
3018 * AP is using WPA or WPA2.
3019 */
3020 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3021 wpa_ie_len = 0;
3022 wpa_s->wpa_proto = 0;
3023 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3024 wpa_ie_len = max_wpa_ie_len;
3025 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3026 wpa_ie, &wpa_ie_len)) {
3027 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3028 "key management and encryption suites (no "
3029 "scan results)");
3030 os_free(wpa_ie);
3031 return NULL;
3032 }
3033#ifdef CONFIG_WPS
3034 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3035 struct wpabuf *wps_ie;
3036 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3037 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3038 wpa_ie_len = wpabuf_len(wps_ie);
3039 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3040 } else
3041 wpa_ie_len = 0;
3042 wpabuf_free(wps_ie);
3043 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3044 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3045 params->wps = WPS_MODE_PRIVACY;
3046 else
3047 params->wps = WPS_MODE_OPEN;
3048 wpa_s->wpa_proto = 0;
3049#endif /* CONFIG_WPS */
3050 } else {
3051 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3052 wpa_ie_len = 0;
3053 wpa_s->wpa_proto = 0;
3054 }
3055
3056#ifdef IEEE8021X_EAPOL
3057 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3058 if (ssid->leap) {
3059 if (ssid->non_leap == 0)
3060 algs = WPA_AUTH_ALG_LEAP;
3061 else
3062 algs |= WPA_AUTH_ALG_LEAP;
3063 }
3064 }
3065
3066#ifdef CONFIG_FILS
3067 /* Clear FILS association */
3068 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3069
3070 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3071 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3072 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3073 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003074 &next_seq_num, &rrk, &rrk_len) == 0 &&
3075 (!wpa_s->last_con_fail_realm ||
3076 wpa_s->last_con_fail_realm_len != realm_len ||
3077 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003078 algs = WPA_AUTH_ALG_FILS;
3079 params->fils_erp_username = username;
3080 params->fils_erp_username_len = username_len;
3081 params->fils_erp_realm = realm;
3082 params->fils_erp_realm_len = realm_len;
3083 params->fils_erp_next_seq_num = next_seq_num;
3084 params->fils_erp_rrk = rrk;
3085 params->fils_erp_rrk_len = rrk_len;
3086
3087 if (mask)
3088 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303089 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3090 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3091 pmksa_cached) {
3092 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003093 }
3094#endif /* CONFIG_FILS */
3095#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003096#ifdef CONFIG_SAE
3097 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3098 algs = WPA_AUTH_ALG_SAE;
3099#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003100
3101 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3102 if (ssid->auth_alg) {
3103 algs = ssid->auth_alg;
3104 wpa_dbg(wpa_s, MSG_DEBUG,
3105 "Overriding auth_alg selection: 0x%x", algs);
3106 }
3107
Hai Shalom5f92bc92019-04-18 11:54:11 -07003108#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303109 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003110 wpa_dbg(wpa_s, MSG_DEBUG,
3111 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3112 algs = WPA_AUTH_ALG_OPEN;
3113 }
3114#endif /* CONFIG_SAE */
3115
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003116#ifdef CONFIG_P2P
3117 if (wpa_s->global->p2p) {
3118 u8 *pos;
3119 size_t len;
3120 int res;
3121 pos = wpa_ie + wpa_ie_len;
3122 len = max_wpa_ie_len - wpa_ie_len;
3123 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3124 ssid->p2p_group);
3125 if (res >= 0)
3126 wpa_ie_len += res;
3127 }
3128
3129 wpa_s->cross_connect_disallowed = 0;
3130 if (bss) {
3131 struct wpabuf *p2p;
3132 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3133 if (p2p) {
3134 wpa_s->cross_connect_disallowed =
3135 p2p_get_cross_connect_disallowed(p2p);
3136 wpabuf_free(p2p);
3137 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3138 "connection",
3139 wpa_s->cross_connect_disallowed ?
3140 "disallows" : "allows");
3141 }
3142 }
3143
3144 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3145#endif /* CONFIG_P2P */
3146
3147 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003148 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003149 wpa_ie + wpa_ie_len,
3150 max_wpa_ie_len -
3151 wpa_ie_len);
3152 }
3153
3154 /*
3155 * Workaround: Add Extended Capabilities element only if the AP
3156 * included this element in Beacon/Probe Response frames. Some older
3157 * APs seem to have interoperability issues if this element is
3158 * included, so while the standard may require us to include the
3159 * element in all cases, it is justifiable to skip it to avoid
3160 * interoperability issues.
3161 */
3162 if (ssid->p2p_group)
3163 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3164 else
3165 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3166
3167 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3168 u8 ext_capab[18];
3169 int ext_capab_len;
3170 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3171 sizeof(ext_capab));
3172 if (ext_capab_len > 0 &&
3173 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3174 u8 *pos = wpa_ie;
3175 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3176 pos += 2 + pos[1];
3177 os_memmove(pos + ext_capab_len, pos,
3178 wpa_ie_len - (pos - wpa_ie));
3179 wpa_ie_len += ext_capab_len;
3180 os_memcpy(pos, ext_capab, ext_capab_len);
3181 }
3182 }
3183
3184#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003185 if (is_hs20_network(wpa_s, ssid, bss)
3186#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3187 && is_hs20_config(wpa_s)
3188#endif /* ANDROID */
3189 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190 struct wpabuf *hs20;
3191
Roshan Pius3a1667e2018-07-03 15:17:14 -07003192 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003193 if (hs20) {
3194 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3195 size_t len;
3196
Hai Shalom74f70d42019-02-11 14:42:39 -08003197 wpas_hs20_add_indication(hs20, pps_mo_id,
3198 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003199 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003200 len = max_wpa_ie_len - wpa_ie_len;
3201 if (wpabuf_len(hs20) <= len) {
3202 os_memcpy(wpa_ie + wpa_ie_len,
3203 wpabuf_head(hs20), wpabuf_len(hs20));
3204 wpa_ie_len += wpabuf_len(hs20);
3205 }
3206 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003207 }
3208 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003209 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003210#endif /* CONFIG_HS20 */
3211
3212 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3213 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3214 size_t len;
3215
3216 len = max_wpa_ie_len - wpa_ie_len;
3217 if (wpabuf_len(buf) <= len) {
3218 os_memcpy(wpa_ie + wpa_ie_len,
3219 wpabuf_head(buf), wpabuf_len(buf));
3220 wpa_ie_len += wpabuf_len(buf);
3221 }
3222 }
3223
3224#ifdef CONFIG_FST
3225 if (wpa_s->fst_ies) {
3226 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3227
3228 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3229 os_memcpy(wpa_ie + wpa_ie_len,
3230 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3231 wpa_ie_len += fst_ies_len;
3232 }
3233 }
3234#endif /* CONFIG_FST */
3235
3236#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003237 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003238 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003239 int len;
3240
3241 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003242 max_wpa_ie_len - wpa_ie_len,
3243 !!mbo_attr_from_mbo_ie(mbo_ie,
3244 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003245 if (len >= 0)
3246 wpa_ie_len += len;
3247 }
3248#endif /* CONFIG_MBO */
3249
3250#ifdef CONFIG_FILS
3251 if (algs == WPA_AUTH_ALG_FILS) {
3252 size_t len;
3253
3254 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3255 max_wpa_ie_len - wpa_ie_len);
3256 wpa_ie_len += len;
3257 }
3258#endif /* CONFIG_FILS */
3259
3260#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003261#ifdef CONFIG_TESTING_OPTIONS
3262 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3263 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3264 } else
3265#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003266 if (algs == WPA_AUTH_ALG_OPEN &&
3267 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3268 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003269 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003270
Roshan Pius3a1667e2018-07-03 15:17:14 -07003271 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003272 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003273 } else if (wpa_s->assoc_status_code ==
3274 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003275 if (wpa_s->last_owe_group == 19)
3276 group = 20;
3277 else if (wpa_s->last_owe_group == 20)
3278 group = 21;
3279 else
3280 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003281 } else {
3282 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003283 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003284
Roshan Pius3a1667e2018-07-03 15:17:14 -07003285 wpa_s->last_owe_group = group;
3286 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3288 if (owe_ie &&
3289 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3290 os_memcpy(wpa_ie + wpa_ie_len,
3291 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3292 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003293 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003294 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003295 }
3296#endif /* CONFIG_OWE */
3297
Hai Shalom021b0b52019-04-10 11:17:58 -07003298#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003299 if (DPP_VERSION > 1 &&
3300 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003301 ssid->dpp_netaccesskey &&
3302 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003303 struct rsn_pmksa_cache_entry *pmksa;
3304
3305 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3306 if (!pmksa || !pmksa->dpp_pfs)
3307 goto pfs_fail;
3308
Hai Shalom021b0b52019-04-10 11:17:58 -07003309 dpp_pfs_free(wpa_s->dpp_pfs);
3310 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3311 ssid->dpp_netaccesskey_len);
3312 if (!wpa_s->dpp_pfs) {
3313 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3314 /* Try to continue without PFS */
3315 goto pfs_fail;
3316 }
3317 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3318 max_wpa_ie_len - wpa_ie_len) {
3319 os_memcpy(wpa_ie + wpa_ie_len,
3320 wpabuf_head(wpa_s->dpp_pfs->ie),
3321 wpabuf_len(wpa_s->dpp_pfs->ie));
3322 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3323 }
3324 }
3325pfs_fail:
3326#endif /* CONFIG_DPP2 */
3327
Roshan Pius3a1667e2018-07-03 15:17:14 -07003328#ifdef CONFIG_IEEE80211R
3329 /*
3330 * Add MDIE under these conditions: the network profile allows FT,
3331 * the AP supports FT, and the mobility domain ID matches.
3332 */
3333 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3334 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3335
3336 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3337 size_t len = 0;
3338 const u8 *md = mdie + 2;
3339 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3340
3341 if (os_memcmp(md, wpa_md,
3342 MOBILITY_DOMAIN_ID_LEN) == 0) {
3343 /* Add mobility domain IE */
3344 len = wpa_ft_add_mdie(
3345 wpa_s->wpa, wpa_ie + wpa_ie_len,
3346 max_wpa_ie_len - wpa_ie_len, mdie);
3347 wpa_ie_len += len;
3348 }
3349#ifdef CONFIG_SME
3350 if (len > 0 && wpa_s->sme.ft_used &&
3351 wpa_sm_has_ptk(wpa_s->wpa)) {
3352 wpa_dbg(wpa_s, MSG_DEBUG,
3353 "SME: Trying to use FT over-the-air");
3354 algs |= WPA_AUTH_ALG_FT;
3355 }
3356#endif /* CONFIG_SME */
3357 }
3358 }
3359#endif /* CONFIG_IEEE80211R */
3360
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003361#ifdef CONFIG_TESTING_OPTIONS
3362 if (wpa_s->rsnxe_override_assoc &&
3363 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3364 max_wpa_ie_len - wpa_ie_len) {
3365 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3366 os_memcpy(wpa_ie + wpa_ie_len,
3367 wpabuf_head(wpa_s->rsnxe_override_assoc),
3368 wpabuf_len(wpa_s->rsnxe_override_assoc));
3369 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3370 } else
3371#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003372 if (wpa_s->rsnxe_len > 0 &&
3373 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3374 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3375 wpa_ie_len += wpa_s->rsnxe_len;
3376 }
3377
Hai Shalomc1a21442022-02-04 13:43:00 -08003378#ifdef CONFIG_TESTING_OPTIONS
3379 if (wpa_s->disable_mscs_support)
3380 goto mscs_end;
3381#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003382 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3383 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003384 struct wpabuf *mscs_ie;
3385 size_t mscs_ie_len, buf_len;
3386
Hai Shalom899fcc72020-10-19 14:38:18 -07003387 buf_len = 3 + /* MSCS descriptor IE header */
3388 1 + /* Request type */
3389 2 + /* User priority control */
3390 4 + /* Stream timeout */
3391 3 + /* TCLAS Mask IE header */
3392 wpa_s->robust_av.frame_classifier_len;
3393 mscs_ie = wpabuf_alloc(buf_len);
3394 if (!mscs_ie) {
3395 wpa_printf(MSG_INFO,
3396 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003397 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003398 }
3399
3400 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3401 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3402 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3403 mscs_ie_len = wpabuf_len(mscs_ie);
3404 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3405 mscs_ie_len);
3406 wpa_ie_len += mscs_ie_len;
3407 }
3408
3409 wpabuf_free(mscs_ie);
3410 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003411mscs_end:
3412
3413 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3414 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003415
Hai Shalom74f70d42019-02-11 14:42:39 -08003416 if (ssid->multi_ap_backhaul_sta) {
3417 size_t multi_ap_ie_len;
3418
3419 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3420 max_wpa_ie_len - wpa_ie_len,
3421 MULTI_AP_BACKHAUL_STA);
3422 if (multi_ap_ie_len == 0) {
3423 wpa_printf(MSG_ERROR,
3424 "Multi-AP: Failed to build Multi-AP IE");
3425 os_free(wpa_ie);
3426 return NULL;
3427 }
3428 wpa_ie_len += multi_ap_ie_len;
3429 }
3430
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003431 params->wpa_ie = wpa_ie;
3432 params->wpa_ie_len = wpa_ie_len;
3433 params->auth_alg = algs;
3434 if (mask)
3435 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3436
3437 return wpa_ie;
3438}
3439
3440
Hai Shalomc3565922019-10-28 11:58:20 -07003441#ifdef CONFIG_OWE
3442static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3443{
3444 struct wpa_driver_associate_params params;
3445 u8 *wpa_ie;
3446
3447 os_memset(&params, 0, sizeof(params));
3448 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3449 wpa_s->current_ssid, &params, NULL);
3450 if (!wpa_ie)
3451 return;
3452
3453 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3454 os_free(wpa_ie);
3455}
3456#endif /* CONFIG_OWE */
3457
3458
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003459#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3460static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3461{
3462 struct wpa_driver_associate_params params;
3463 enum wpa_drv_update_connect_params_mask mask = 0;
3464 u8 *wpa_ie;
3465
3466 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3467 return; /* nothing to do */
3468
3469 os_memset(&params, 0, sizeof(params));
3470 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3471 wpa_s->current_ssid, &params, &mask);
3472 if (!wpa_ie)
3473 return;
3474
Hai Shalomc1a21442022-02-04 13:43:00 -08003475 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3476 wpa_s->auth_alg = params.auth_alg;
3477 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478 }
3479
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003480 os_free(wpa_ie);
3481}
3482#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3483
3484
Hai Shalomc3565922019-10-28 11:58:20 -07003485static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3486{
3487 if (!edmg_ie || edmg_ie[1] < 6)
3488 return 0;
3489 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3490}
3491
3492
3493static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3494{
3495 if (!edmg_ie || edmg_ie[1] < 6)
3496 return 0;
3497 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3498}
3499
3500
3501/* Returns the intersection of two EDMG configurations.
3502 * Note: The current implementation is limited to CB2 only (CB1 included),
3503 * i.e., the implementation supports up to 2 contiguous channels.
3504 * For supporting non-contiguous (aggregated) channels and for supporting
3505 * CB3 and above, this function will need to be extended.
3506 */
3507static struct ieee80211_edmg_config
3508get_edmg_intersection(struct ieee80211_edmg_config a,
3509 struct ieee80211_edmg_config b,
3510 u8 primary_channel)
3511{
3512 struct ieee80211_edmg_config result;
3513 int i, contiguous = 0;
3514 int max_contiguous = 0;
3515
3516 result.channels = b.channels & a.channels;
3517 if (!result.channels) {
3518 wpa_printf(MSG_DEBUG,
3519 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3520 a.channels, b.channels);
3521 goto fail;
3522 }
3523
3524 if (!(result.channels & BIT(primary_channel - 1))) {
3525 wpa_printf(MSG_DEBUG,
3526 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3527 primary_channel, result.channels);
3528 goto fail;
3529 }
3530
3531 /* Find max contiguous channels */
3532 for (i = 0; i < 6; i++) {
3533 if (result.channels & BIT(i))
3534 contiguous++;
3535 else
3536 contiguous = 0;
3537
3538 if (contiguous > max_contiguous)
3539 max_contiguous = contiguous;
3540 }
3541
3542 /* Assuming AP and STA supports ONLY contiguous channels,
3543 * bw configuration can have value between 4-7.
3544 */
3545 if ((b.bw_config < a.bw_config))
3546 result.bw_config = b.bw_config;
3547 else
3548 result.bw_config = a.bw_config;
3549
3550 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3551 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3552 wpa_printf(MSG_DEBUG,
3553 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3554 max_contiguous);
3555 goto fail;
3556 }
3557
3558 return result;
3559
3560fail:
3561 result.channels = 0;
3562 result.bw_config = 0;
3563 return result;
3564}
3565
3566
3567static struct ieee80211_edmg_config
3568get_supported_edmg(struct wpa_supplicant *wpa_s,
3569 struct hostapd_freq_params *freq,
3570 struct ieee80211_edmg_config request_edmg)
3571{
3572 enum hostapd_hw_mode hw_mode;
3573 struct hostapd_hw_modes *mode = NULL;
3574 u8 primary_channel;
3575
3576 if (!wpa_s->hw.modes)
3577 goto fail;
3578
3579 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3580 if (hw_mode == NUM_HOSTAPD_MODES)
3581 goto fail;
3582
Hai Shalom60840252021-02-19 19:02:11 -08003583 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003584 if (!mode)
3585 goto fail;
3586
3587 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3588
3589fail:
3590 request_edmg.channels = 0;
3591 request_edmg.bw_config = 0;
3592 return request_edmg;
3593}
3594
3595
Hai Shalom021b0b52019-04-10 11:17:58 -07003596#ifdef CONFIG_MBO
3597void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3598{
3599 struct wpa_driver_associate_params params;
3600 u8 *wpa_ie;
3601
3602 /*
3603 * Update MBO connect params only in case of change of MBO attributes
3604 * when connected, if the AP support MBO.
3605 */
3606
3607 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3608 !wpa_s->current_bss ||
3609 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3610 return;
3611
3612 os_memset(&params, 0, sizeof(params));
3613 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3614 wpa_s->current_ssid, &params, NULL);
3615 if (!wpa_ie)
3616 return;
3617
3618 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3619 os_free(wpa_ie);
3620}
3621#endif /* CONFIG_MBO */
3622
3623
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003624static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3625{
3626 struct wpa_connect_work *cwork = work->ctx;
3627 struct wpa_bss *bss = cwork->bss;
3628 struct wpa_ssid *ssid = cwork->ssid;
3629 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003630 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003631 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003632 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003633 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003634 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003635#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003636 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003637#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003638 int assoc_failed = 0;
3639 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003640 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003641#ifdef CONFIG_HT_OVERRIDES
3642 struct ieee80211_ht_capabilities htcaps;
3643 struct ieee80211_ht_capabilities htcaps_mask;
3644#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003645#ifdef CONFIG_VHT_OVERRIDES
3646 struct ieee80211_vht_capabilities vhtcaps;
3647 struct ieee80211_vht_capabilities vhtcaps_mask;
3648#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003649
Hai Shalomc1a21442022-02-04 13:43:00 -08003650 wpa_s->roam_in_progress = false;
3651#ifdef CONFIG_WNM
3652 wpa_s->bss_trans_mgmt_in_progress = false;
3653#endif /* CONFIG_WNM */
3654
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003655 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003656 if (work->started) {
3657 wpa_s->connect_work = NULL;
3658
3659 /* cancel possible auth. timeout */
3660 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3661 NULL);
3662 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003663 wpas_connect_work_free(cwork);
3664 return;
3665 }
3666
3667 wpa_s->connect_work = work;
3668
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003669 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3670 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003671 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3672 wpas_connect_work_done(wpa_s);
3673 return;
3674 }
3675
Dmitry Shmidte4663042016-04-04 10:07:49 -07003676 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003677 os_memset(&params, 0, sizeof(params));
3678 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003679 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003680
3681 /* Starting new association, so clear the possibly used WPA IE from the
3682 * previous association. */
3683 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3684 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3685 wpa_s->rsnxe_len = 0;
3686 wpa_s->mscs_setup_done = false;
3687
3688 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3689 if (!wpa_ie) {
3690 wpas_connect_work_done(wpa_s);
3691 return;
3692 }
3693
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003694 if (bss &&
3695 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696#ifdef CONFIG_IEEE80211R
3697 const u8 *ie, *md = NULL;
3698#endif /* CONFIG_IEEE80211R */
3699 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3700 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3701 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3702 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3703 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3704 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3705 if (bssid_changed)
3706 wpas_notify_bssid_changed(wpa_s);
3707#ifdef CONFIG_IEEE80211R
3708 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3709 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3710 md = ie + 2;
3711 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3712 if (md) {
3713 /* Prepare for the next transition */
3714 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3715 }
3716#endif /* CONFIG_IEEE80211R */
3717#ifdef CONFIG_WPS
3718 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3719 wpa_s->conf->ap_scan == 2 &&
3720 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3721 /* Use ap_scan==1 style network selection to find the network
3722 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003723 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003724 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725 wpa_s->reassociate = 1;
3726 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003727 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 return;
3729#endif /* CONFIG_WPS */
3730 } else {
3731 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3732 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003733 if (bss)
3734 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3735 else
3736 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003737 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003738 if (!wpa_s->pno)
3739 wpa_supplicant_cancel_sched_scan(wpa_s);
3740
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003741 wpa_supplicant_cancel_scan(wpa_s);
3742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3744 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003745 cipher_pairwise = wpa_s->pairwise_cipher;
3746 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003747 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003748 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3749 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3750 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3751 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003752#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753 if (wpa_set_wep_keys(wpa_s, ssid)) {
3754 use_crypt = 1;
3755 wep_keys_set = 1;
3756 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003757#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 }
3759 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3760 use_crypt = 0;
3761
3762#ifdef IEEE8021X_EAPOL
3763 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3764 if ((ssid->eapol_flags &
3765 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3766 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3767 !wep_keys_set) {
3768 use_crypt = 0;
3769 } else {
3770 /* Assume that dynamic WEP-104 keys will be used and
3771 * set cipher suites in order for drivers to expect
3772 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003773 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003774 }
3775 }
3776#endif /* IEEE8021X_EAPOL */
3777
3778 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3779 /* Set the key before (and later after) association */
3780 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3781 }
3782
3783 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3784 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003785 params.ssid = bss->ssid;
3786 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003787 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3788 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003789 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3790 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003791 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003792 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003793 ssid->bssid_set,
3794 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003795 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003796 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003797 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003798 params.bssid_hint = bss->bssid;
3799 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003800 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003802 if (ssid->bssid_hint_set)
3803 params.bssid_hint = ssid->bssid_hint;
3804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805 params.ssid = ssid->ssid;
3806 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003807 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003809
3810 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3811 wpa_s->conf->ap_scan == 2) {
3812 params.bssid = ssid->bssid;
3813 params.fixed_bssid = 1;
3814 }
3815
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003816 /* Initial frequency for IBSS/mesh */
3817 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003818 ssid->frequency > 0 && params.freq.freq == 0)
3819 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003820
3821 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003822 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003823 if (ssid->beacon_int)
3824 params.beacon_int = ssid->beacon_int;
3825 else
3826 params.beacon_int = wpa_s->conf->beacon_int;
3827 }
3828
Hai Shalomc3565922019-10-28 11:58:20 -07003829 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003830 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3831 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003832 else
3833 edmg_ie_oper = NULL;
3834
3835 if (edmg_ie_oper) {
3836 params.freq.edmg.channels =
3837 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3838 params.freq.edmg.bw_config =
3839 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3840 wpa_printf(MSG_DEBUG,
3841 "AP supports EDMG channels 0x%x, bw_config %d",
3842 params.freq.edmg.channels,
3843 params.freq.edmg.bw_config);
3844
3845 /* User may ask for specific EDMG channel for EDMG connection
3846 * (must be supported by AP)
3847 */
3848 if (ssid->edmg_channel) {
3849 struct ieee80211_edmg_config configured_edmg;
3850 enum hostapd_hw_mode hw_mode;
3851 u8 primary_channel;
3852
3853 hw_mode = ieee80211_freq_to_chan(bss->freq,
3854 &primary_channel);
3855 if (hw_mode == NUM_HOSTAPD_MODES)
3856 goto edmg_fail;
3857
3858 hostapd_encode_edmg_chan(ssid->enable_edmg,
3859 ssid->edmg_channel,
3860 primary_channel,
3861 &configured_edmg);
3862
3863 if (ieee802_edmg_is_allowed(params.freq.edmg,
3864 configured_edmg)) {
3865 params.freq.edmg = configured_edmg;
3866 wpa_printf(MSG_DEBUG,
3867 "Use EDMG channel %d for connection",
3868 ssid->edmg_channel);
3869 } else {
3870 edmg_fail:
3871 params.freq.edmg.channels = 0;
3872 params.freq.edmg.bw_config = 0;
3873 wpa_printf(MSG_WARNING,
3874 "EDMG channel %d not supported by AP, fallback to DMG",
3875 ssid->edmg_channel);
3876 }
3877 }
3878
3879 if (params.freq.edmg.channels) {
3880 wpa_printf(MSG_DEBUG,
3881 "EDMG before: channels 0x%x, bw_config %d",
3882 params.freq.edmg.channels,
3883 params.freq.edmg.bw_config);
3884 params.freq.edmg = get_supported_edmg(wpa_s,
3885 &params.freq,
3886 params.freq.edmg);
3887 wpa_printf(MSG_DEBUG,
3888 "EDMG after: channels 0x%x, bw_config %d",
3889 params.freq.edmg.channels,
3890 params.freq.edmg.bw_config);
3891 }
3892 }
3893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003894 params.pairwise_suite = cipher_pairwise;
3895 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003896 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003897 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003898 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003899 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003900 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003901 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003902#ifdef CONFIG_WEP
3903 {
3904 int i;
3905
3906 for (i = 0; i < NUM_WEP_KEYS; i++) {
3907 if (ssid->wep_key_len[i])
3908 params.wep_key[i] = ssid->wep_key[i];
3909 params.wep_key_len[i] = ssid->wep_key_len[i];
3910 }
3911 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003912 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003913#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914
Hai Shalom74f70d42019-02-11 14:42:39 -08003915 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303916 (
3917#ifdef CONFIG_DRIVER_NL80211_BRCM
3918 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3919#else
3920 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3921#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003922 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 params.passphrase = ssid->passphrase;
3924 if (ssid->psk_set)
3925 params.psk = ssid->psk;
3926 }
3927
Hai Shalom74f70d42019-02-11 14:42:39 -08003928 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3929 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3930 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3931 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3932 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003933 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003934
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003935 if (wpa_s->conf->key_mgmt_offload) {
3936 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3937 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003938 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3939 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003940 params.req_key_mgmt_offload =
3941 ssid->proactive_key_caching < 0 ?
3942 wpa_s->conf->okc : ssid->proactive_key_caching;
3943 else
3944 params.req_key_mgmt_offload = 1;
3945
Vinayak Yadawad14709082022-03-17 14:25:11 +05303946 if ((
3947#ifdef CONFIG_DRIVER_NL80211_BRCM
3948 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3949#else
3950 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3951#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003952 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3953 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3954 ssid->psk_set)
3955 params.psk = ssid->psk;
3956 }
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 params.drop_unencrypted = use_crypt;
3959
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003960 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003961 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003962 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3963 struct wpa_ie_data ie;
3964 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3965 ie.capabilities &
3966 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3967 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3968 "MFP: require MFP");
3969 params.mgmt_frame_protection =
3970 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003971#ifdef CONFIG_OWE
3972 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3973 !ssid->owe_only) {
3974 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3975#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003976 }
3977 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003979 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003980
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003981 if (wpa_s->p2pdev->set_sta_uapsd)
3982 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 else
3984 params.uapsd = -1;
3985
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003986#ifdef CONFIG_HT_OVERRIDES
3987 os_memset(&htcaps, 0, sizeof(htcaps));
3988 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3989 params.htcaps = (u8 *) &htcaps;
3990 params.htcaps_mask = (u8 *) &htcaps_mask;
3991 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3992#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003993#ifdef CONFIG_VHT_OVERRIDES
3994 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3995 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3996 params.vhtcaps = &vhtcaps;
3997 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003998 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003999#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004000#ifdef CONFIG_HE_OVERRIDES
4001 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4002#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004003
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004004#ifdef CONFIG_P2P
4005 /*
4006 * If multi-channel concurrency is not supported, check for any
4007 * frequency conflict. In case of any frequency conflict, remove the
4008 * least prioritized connection.
4009 */
4010 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004011 int freq, num;
4012 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004013 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004014 wpa_printf(MSG_DEBUG,
4015 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004016 freq, params.freq.freq);
4017 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004018 wpa_s, params.freq.freq, ssid) < 0) {
4019 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004020 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004021 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004022 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004023 }
4024 }
4025#endif /* CONFIG_P2P */
4026
Dmitry Shmidte4663042016-04-04 10:07:49 -07004027 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
4028 wpa_s->current_ssid)
4029 params.prev_bssid = prev_bssid;
4030
Hai Shalom60840252021-02-19 19:02:11 -08004031#ifdef CONFIG_SAE
4032 params.sae_pwe = wpa_s->conf->sae_pwe;
4033#endif /* CONFIG_SAE */
4034
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004035 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004036 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004037 if (ret < 0) {
4038 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4039 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004040 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004041 /*
4042 * The driver is known to mean what is saying, so we
4043 * can stop right here; the association will not
4044 * succeed.
4045 */
4046 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004047 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004048 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004049 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4051 return;
4052 }
4053 /* try to continue anyway; new association will be tried again
4054 * after timeout */
4055 assoc_failed = 1;
4056 }
4057
4058 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4059 /* Set the key after the association just in case association
4060 * cleared the previously configured key. */
4061 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4062 /* No need to timeout authentication since there is no key
4063 * management. */
4064 wpa_supplicant_cancel_auth_timeout(wpa_s);
4065 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4066#ifdef CONFIG_IBSS_RSN
4067 } else if (ssid->mode == WPAS_MODE_IBSS &&
4068 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4069 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4070 /*
4071 * RSN IBSS authentication is per-STA and we can disable the
4072 * per-BSSID authentication.
4073 */
4074 wpa_supplicant_cancel_auth_timeout(wpa_s);
4075#endif /* CONFIG_IBSS_RSN */
4076 } else {
4077 /* Timeout for IEEE 802.11 authentication and association */
4078 int timeout = 60;
4079
4080 if (assoc_failed) {
4081 /* give IBSS a bit more time */
4082 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4083 } else if (wpa_s->conf->ap_scan == 1) {
4084 /* give IBSS a bit more time */
4085 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4086 }
4087 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4088 }
4089
Hai Shalomfdcde762020-04-02 11:19:20 -07004090#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004091 if (wep_keys_set &&
4092 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004093 /* Set static WEP keys again */
4094 wpa_set_wep_keys(wpa_s, ssid);
4095 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004096#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097
4098 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
4099 /*
4100 * Do not allow EAP session resumption between different
4101 * network configurations.
4102 */
4103 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4104 }
4105 old_ssid = wpa_s->current_ssid;
4106 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004107
4108 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004109 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004110#ifdef CONFIG_HS20
4111 hs20_configure_frame_filters(wpa_s);
4112#endif /* CONFIG_HS20 */
4113 }
4114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004115 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4116 wpa_supplicant_initiate_eapol(wpa_s);
4117 if (old_ssid != wpa_s->current_ssid)
4118 wpas_notify_network_changed(wpa_s);
4119}
4120
4121
4122static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4123 const u8 *addr)
4124{
4125 struct wpa_ssid *old_ssid;
4126
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004127 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004130 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 wpa_sm_set_config(wpa_s->wpa, NULL);
4132 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4133 if (old_ssid != wpa_s->current_ssid)
4134 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004135
4136 wpas_scs_deinit(wpa_s);
4137 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4139}
4140
4141
4142/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4144 * @wpa_s: Pointer to wpa_supplicant data
4145 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4146 *
4147 * This function is used to request %wpa_supplicant to deauthenticate from the
4148 * current AP.
4149 */
4150void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004151 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152{
4153 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004154 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004155 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004157 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004158 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004159 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004160 reason_code, reason2str(reason_code),
4161 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004162
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004163 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4164 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4165 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004166 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004167 else if (!is_zero_ether_addr(wpa_s->bssid))
4168 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004169 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4170 /*
4171 * When using driver-based BSS selection, we may not know the
4172 * BSSID with which we are currently trying to associate. We
4173 * need to notify the driver of this disconnection even in such
4174 * a case, so use the all zeros address here.
4175 */
4176 addr = wpa_s->bssid;
4177 zero_addr = 1;
4178 }
4179
Hai Shalom74f70d42019-02-11 14:42:39 -08004180 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4181 wpa_s->enabled_4addr_mode = 0;
4182
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004183#ifdef CONFIG_TDLS
4184 wpa_tdls_teardown_peers(wpa_s->wpa);
4185#endif /* CONFIG_TDLS */
4186
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004187#ifdef CONFIG_MESH
4188 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004189 struct mesh_conf *mconf;
4190
4191 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004192 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4193 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004194 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4195 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004196 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004197 }
4198#endif /* CONFIG_MESH */
4199
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004200 if (addr) {
4201 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004202 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004203 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004204 event.deauth_info.locally_generated = 1;
4205 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004206 if (zero_addr)
4207 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004208 }
4209
4210 wpa_supplicant_clear_connection(wpa_s, addr);
4211}
4212
Hai Shalomfdcde762020-04-02 11:19:20 -07004213
4214void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4215{
4216 wpa_s->own_reconnect_req = 1;
4217 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4218
4219}
4220
4221
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004222static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4223 struct wpa_ssid *ssid)
4224{
4225 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4226 return;
4227
4228 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004229 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004230 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4231 wpas_notify_network_enabled_changed(wpa_s, ssid);
4232
4233 /*
4234 * Try to reassociate since there is no current configuration and a new
4235 * network was made available.
4236 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004237 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004238 wpa_s->reassociate = 1;
4239}
4240
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004241
Roshan Pius950bec92016-07-19 09:49:24 -07004242/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004243 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004244 * @wpa_s: wpa_supplicant structure for a network interface
4245 * Returns: The new network configuration or %NULL if operation failed
4246 *
4247 * This function performs the following operations:
4248 * 1. Adds a new network.
4249 * 2. Send network addition notification.
4250 * 3. Marks the network disabled.
4251 * 4. Set network default parameters.
4252 */
4253struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4254{
4255 struct wpa_ssid *ssid;
4256
4257 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004258 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004259 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004260 wpas_notify_network_added(wpa_s, ssid);
4261 ssid->disabled = 1;
4262 wpa_config_set_network_defaults(ssid);
4263
4264 return ssid;
4265}
4266
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004267
Roshan Pius950bec92016-07-19 09:49:24 -07004268/**
4269 * wpa_supplicant_remove_network - Remove a configured network based on id
4270 * @wpa_s: wpa_supplicant structure for a network interface
4271 * @id: Unique network id to search for
4272 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4273 * could not be removed
4274 *
4275 * This function performs the following operations:
4276 * 1. Removes the network.
4277 * 2. Send network removal notification.
4278 * 3. Update internal state machines.
4279 * 4. Stop any running sched scans.
4280 */
4281int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4282{
4283 struct wpa_ssid *ssid;
4284 int was_disabled;
4285
4286 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004287 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004288 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004289 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004290
4291 if (wpa_s->last_ssid == ssid)
4292 wpa_s->last_ssid = NULL;
4293
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004294 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004295#ifdef CONFIG_SME
4296 wpa_s->sme.prev_bssid_set = 0;
4297#endif /* CONFIG_SME */
4298 /*
4299 * Invalidate the EAP session cache if the current or
4300 * previously used network is removed.
4301 */
4302 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4303 }
4304
4305 if (ssid == wpa_s->current_ssid) {
4306 wpa_sm_set_config(wpa_s->wpa, NULL);
4307 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4308
4309 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4310 wpa_s->own_disconnect_req = 1;
4311 wpa_supplicant_deauthenticate(wpa_s,
4312 WLAN_REASON_DEAUTH_LEAVING);
4313 }
4314
4315 was_disabled = ssid->disabled;
4316
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004317 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004318 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004319
4320 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004321 wpa_printf(MSG_DEBUG,
4322 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004323 wpa_supplicant_cancel_sched_scan(wpa_s);
4324 wpa_supplicant_req_scan(wpa_s, 0, 0);
4325 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004326
Roshan Pius950bec92016-07-19 09:49:24 -07004327 return 0;
4328}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004329
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004331/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004332 * wpa_supplicant_remove_all_networks - Remove all configured networks
4333 * @wpa_s: wpa_supplicant structure for a network interface
4334 * Returns: 0 on success (errors are currently ignored)
4335 *
4336 * This function performs the following operations:
4337 * 1. Remove all networks.
4338 * 2. Send network removal notifications.
4339 * 3. Update internal state machines.
4340 * 4. Stop any running sched scans.
4341 */
4342int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4343{
4344 struct wpa_ssid *ssid;
4345
4346 if (wpa_s->sched_scanning)
4347 wpa_supplicant_cancel_sched_scan(wpa_s);
4348
4349 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4350 if (wpa_s->current_ssid) {
4351#ifdef CONFIG_SME
4352 wpa_s->sme.prev_bssid_set = 0;
4353#endif /* CONFIG_SME */
4354 wpa_sm_set_config(wpa_s->wpa, NULL);
4355 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4356 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4357 wpa_s->own_disconnect_req = 1;
4358 wpa_supplicant_deauthenticate(
4359 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4360 }
4361 ssid = wpa_s->conf->ssid;
4362 while (ssid) {
4363 struct wpa_ssid *remove_ssid = ssid;
4364 int id;
4365
4366 id = ssid->id;
4367 ssid = ssid->next;
4368 if (wpa_s->last_ssid == remove_ssid)
4369 wpa_s->last_ssid = NULL;
4370 wpas_notify_network_removed(wpa_s, remove_ssid);
4371 wpa_config_remove_network(wpa_s->conf, id);
4372 }
4373 return 0;
4374}
4375
4376
4377/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378 * wpa_supplicant_enable_network - Mark a configured network as enabled
4379 * @wpa_s: wpa_supplicant structure for a network interface
4380 * @ssid: wpa_ssid structure for a configured network or %NULL
4381 *
4382 * Enables the specified network or all networks if no network specified.
4383 */
4384void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4385 struct wpa_ssid *ssid)
4386{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004387 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004388 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4389 wpa_supplicant_enable_one_network(wpa_s, ssid);
4390 } else
4391 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004393 if (wpa_s->reassociate && !wpa_s->disconnected &&
4394 (!wpa_s->current_ssid ||
4395 wpa_s->wpa_state == WPA_DISCONNECTED ||
4396 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004397 if (wpa_s->sched_scanning) {
4398 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4399 "new network to scan filters");
4400 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401 }
4402
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004403 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4404 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004405 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004406 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407 }
4408}
4409
4410
4411/**
4412 * wpa_supplicant_disable_network - Mark a configured network as disabled
4413 * @wpa_s: wpa_supplicant structure for a network interface
4414 * @ssid: wpa_ssid structure for a configured network or %NULL
4415 *
4416 * Disables the specified network or all networks if no network specified.
4417 */
4418void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4419 struct wpa_ssid *ssid)
4420{
4421 struct wpa_ssid *other_ssid;
4422 int was_disabled;
4423
4424 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004425 if (wpa_s->sched_scanning)
4426 wpa_supplicant_cancel_sched_scan(wpa_s);
4427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4429 other_ssid = other_ssid->next) {
4430 was_disabled = other_ssid->disabled;
4431 if (was_disabled == 2)
4432 continue; /* do not change persistent P2P group
4433 * data */
4434
4435 other_ssid->disabled = 1;
4436
4437 if (was_disabled != other_ssid->disabled)
4438 wpas_notify_network_enabled_changed(
4439 wpa_s, other_ssid);
4440 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004441 if (wpa_s->current_ssid) {
4442 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4443 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004444 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004445 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004447 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004448 if (ssid == wpa_s->current_ssid) {
4449 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4450 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004451 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004453 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454
4455 was_disabled = ssid->disabled;
4456
4457 ssid->disabled = 1;
4458
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004459 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004461 if (wpa_s->sched_scanning) {
4462 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4463 "to remove network from filters");
4464 wpa_supplicant_cancel_sched_scan(wpa_s);
4465 wpa_supplicant_req_scan(wpa_s, 0, 0);
4466 }
4467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468 }
4469}
4470
4471
4472/**
4473 * wpa_supplicant_select_network - Attempt association with a network
4474 * @wpa_s: wpa_supplicant structure for a network interface
4475 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4476 */
4477void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4478 struct wpa_ssid *ssid)
4479{
4480
4481 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004482 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004484 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004485 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4486 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004487 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004488 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004489 disconnected = 1;
4490 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004492 if (ssid)
4493 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4494
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004495 /*
4496 * Mark all other networks disabled or mark all networks enabled if no
4497 * network specified.
4498 */
4499 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4500 other_ssid = other_ssid->next) {
4501 int was_disabled = other_ssid->disabled;
4502 if (was_disabled == 2)
4503 continue; /* do not change persistent P2P group data */
4504
4505 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004506 if (was_disabled && !other_ssid->disabled)
4507 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508
4509 if (was_disabled != other_ssid->disabled)
4510 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4511 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004512
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004513 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4514 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004515 /* We are already associated with the selected network */
4516 wpa_printf(MSG_DEBUG, "Already associated with the "
4517 "selected network - do nothing");
4518 return;
4519 }
4520
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004521 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004522 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004523 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004524 wpa_s->connect_without_scan =
4525 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004526
4527 /*
4528 * Don't optimize next scan freqs since a new ESS has been
4529 * selected.
4530 */
4531 os_free(wpa_s->next_scan_freqs);
4532 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004533 } else {
4534 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004535 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537 wpa_s->disconnected = 0;
4538 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004539 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004540 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004541 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004542 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004543 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4544 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004545
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004546 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004547 wpa_supplicant_fast_associate(wpa_s) != 1) {
4548 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004549 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004550 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004551 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552
4553 if (ssid)
4554 wpas_notify_network_selected(wpa_s, ssid);
4555}
4556
4557
4558/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004559 * wpas_remove_cred - Remove the specified credential and all the network
4560 * entries created based on the removed credential
4561 * @wpa_s: wpa_supplicant structure for a network interface
4562 * @cred: The credential to remove
4563 * Returns: 0 on success, -1 on failure
4564 */
4565int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4566{
4567 struct wpa_ssid *ssid, *next;
4568 int id;
4569
4570 if (!cred) {
4571 wpa_printf(MSG_DEBUG, "Could not find cred");
4572 return -1;
4573 }
4574
4575 id = cred->id;
4576 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4577 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4578 return -1;
4579 }
4580
4581 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4582
4583 /* Remove any network entry created based on the removed credential */
4584 ssid = wpa_s->conf->ssid;
4585 while (ssid) {
4586 next = ssid->next;
4587
4588 if (ssid->parent_cred == cred) {
4589 wpa_printf(MSG_DEBUG,
4590 "Remove network id %d since it used the removed credential",
4591 ssid->id);
4592 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4593 -1) {
4594 wpa_printf(MSG_DEBUG,
4595 "Could not find network id=%d",
4596 ssid->id);
4597 }
4598 }
4599
4600 ssid = next;
4601 }
4602
4603 return 0;
4604}
4605
4606
4607/**
4608 * wpas_remove_cred - Remove all the Interworking credentials
4609 * @wpa_s: wpa_supplicant structure for a network interface
4610 * Returns: 0 on success, -1 on failure
4611 */
4612int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4613{
4614 int res, ret = 0;
4615 struct wpa_cred *cred, *prev;
4616
4617 cred = wpa_s->conf->cred;
4618 while (cred) {
4619 prev = cred;
4620 cred = cred->next;
4621 res = wpas_remove_cred(wpa_s, prev);
4622 if (res < 0) {
4623 wpa_printf(MSG_DEBUG,
4624 "Removal of all credentials failed - failed to remove credential id=%d",
4625 prev->id);
4626 ret = -1;
4627 }
4628 }
4629
4630 return ret;
4631}
4632
4633
4634/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004635 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4636 * @wpa_s: wpa_supplicant structure for a network interface
4637 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4638 * @pkcs11_module_path: PKCS #11 module path or NULL
4639 * Returns: 0 on success; -1 on failure
4640 *
4641 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4642 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4643 * module path fails the paths will be reset to the default value (NULL).
4644 */
4645int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4646 const char *pkcs11_engine_path,
4647 const char *pkcs11_module_path)
4648{
4649 char *pkcs11_engine_path_copy = NULL;
4650 char *pkcs11_module_path_copy = NULL;
4651
4652 if (pkcs11_engine_path != NULL) {
4653 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4654 if (pkcs11_engine_path_copy == NULL)
4655 return -1;
4656 }
4657 if (pkcs11_module_path != NULL) {
4658 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004659 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004660 os_free(pkcs11_engine_path_copy);
4661 return -1;
4662 }
4663 }
4664
4665 os_free(wpa_s->conf->pkcs11_engine_path);
4666 os_free(wpa_s->conf->pkcs11_module_path);
4667 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4668 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4669
4670 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4671 eapol_sm_deinit(wpa_s->eapol);
4672 wpa_s->eapol = NULL;
4673 if (wpa_supplicant_init_eapol(wpa_s)) {
4674 /* Error -> Reset paths to the default value (NULL) once. */
4675 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4676 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4677 NULL);
4678
4679 return -1;
4680 }
4681 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4682
4683 return 0;
4684}
4685
4686
4687/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4689 * @wpa_s: wpa_supplicant structure for a network interface
4690 * @ap_scan: AP scan mode
4691 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4692 *
4693 */
4694int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4695{
4696
4697 int old_ap_scan;
4698
4699 if (ap_scan < 0 || ap_scan > 2)
4700 return -1;
4701
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004702 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4703 wpa_printf(MSG_INFO,
4704 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4705 }
4706
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004707#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004708 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4709 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4710 wpa_s->wpa_state < WPA_COMPLETED) {
4711 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4712 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004713 return 0;
4714 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004715#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004717 old_ap_scan = wpa_s->conf->ap_scan;
4718 wpa_s->conf->ap_scan = ap_scan;
4719
4720 if (old_ap_scan != wpa_s->conf->ap_scan)
4721 wpas_notify_ap_scan_changed(wpa_s);
4722
4723 return 0;
4724}
4725
4726
4727/**
4728 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4729 * @wpa_s: wpa_supplicant structure for a network interface
4730 * @expire_age: Expiration age in seconds
4731 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4732 *
4733 */
4734int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4735 unsigned int bss_expire_age)
4736{
4737 if (bss_expire_age < 10) {
4738 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4739 bss_expire_age);
4740 return -1;
4741 }
4742 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4743 bss_expire_age);
4744 wpa_s->conf->bss_expiration_age = bss_expire_age;
4745
4746 return 0;
4747}
4748
4749
4750/**
4751 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4752 * @wpa_s: wpa_supplicant structure for a network interface
4753 * @expire_count: number of scans after which an unseen BSS is reclaimed
4754 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4755 *
4756 */
4757int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4758 unsigned int bss_expire_count)
4759{
4760 if (bss_expire_count < 1) {
4761 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4762 bss_expire_count);
4763 return -1;
4764 }
4765 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4766 bss_expire_count);
4767 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4768
4769 return 0;
4770}
4771
4772
4773/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004774 * wpa_supplicant_set_scan_interval - Set scan interval
4775 * @wpa_s: wpa_supplicant structure for a network interface
4776 * @scan_interval: scan interval in seconds
4777 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4778 *
4779 */
4780int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4781 int scan_interval)
4782{
4783 if (scan_interval < 0) {
4784 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4785 scan_interval);
4786 return -1;
4787 }
4788 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4789 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004790 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004791
4792 return 0;
4793}
4794
4795
4796/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797 * wpa_supplicant_set_debug_params - Set global debug params
4798 * @global: wpa_global structure
4799 * @debug_level: debug level
4800 * @debug_timestamp: determines if show timestamp in debug data
4801 * @debug_show_keys: determines if show keys in debug data
4802 * Returns: 0 if succeed or -1 if debug_level has wrong value
4803 */
4804int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4805 int debug_timestamp, int debug_show_keys)
4806{
4807
4808 int old_level, old_timestamp, old_show_keys;
4809
4810 /* check for allowed debuglevels */
4811 if (debug_level != MSG_EXCESSIVE &&
4812 debug_level != MSG_MSGDUMP &&
4813 debug_level != MSG_DEBUG &&
4814 debug_level != MSG_INFO &&
4815 debug_level != MSG_WARNING &&
4816 debug_level != MSG_ERROR)
4817 return -1;
4818
4819 old_level = wpa_debug_level;
4820 old_timestamp = wpa_debug_timestamp;
4821 old_show_keys = wpa_debug_show_keys;
4822
4823 wpa_debug_level = debug_level;
4824 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4825 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4826
4827 if (wpa_debug_level != old_level)
4828 wpas_notify_debug_level_changed(global);
4829 if (wpa_debug_timestamp != old_timestamp)
4830 wpas_notify_debug_timestamp_changed(global);
4831 if (wpa_debug_show_keys != old_show_keys)
4832 wpas_notify_debug_show_keys_changed(global);
4833
4834 return 0;
4835}
4836
4837
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004838#ifdef CONFIG_OWE
4839static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4840 const u8 *entry_ssid, size_t entry_ssid_len)
4841{
4842 const u8 *owe, *pos, *end;
4843 u8 ssid_len;
4844 struct wpa_bss *bss;
4845
4846 /* Check network profile SSID aganst the SSID in the
4847 * OWE Transition Mode element. */
4848
4849 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4850 if (!bss)
4851 return 0;
4852
4853 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4854 if (!owe)
4855 return 0;
4856
4857 pos = owe + 6;
4858 end = owe + 2 + owe[1];
4859
4860 if (end - pos < ETH_ALEN + 1)
4861 return 0;
4862 pos += ETH_ALEN;
4863 ssid_len = *pos++;
4864 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4865 return 0;
4866
4867 return entry_ssid_len == ssid_len &&
4868 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4869}
4870#endif /* CONFIG_OWE */
4871
4872
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873/**
4874 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4875 * @wpa_s: Pointer to wpa_supplicant data
4876 * Returns: A pointer to the current network structure or %NULL on failure
4877 */
4878struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4879{
4880 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004881 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004882 int res;
4883 size_t ssid_len;
4884 u8 bssid[ETH_ALEN];
4885 int wired;
4886
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004887 res = wpa_drv_get_ssid(wpa_s, ssid);
4888 if (res < 0) {
4889 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4890 "driver");
4891 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004892 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004893 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004894
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004895 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004896 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4897 "driver");
4898 return NULL;
4899 }
4900
4901 wired = wpa_s->conf->ap_scan == 0 &&
4902 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4903
4904 entry = wpa_s->conf->ssid;
4905 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004906 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004908 (!entry->ssid ||
4909 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4910 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004911 (!entry->bssid_set ||
4912 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4913 return entry;
4914#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004915 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004916 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4917 (entry->ssid == NULL || entry->ssid_len == 0) &&
4918 (!entry->bssid_set ||
4919 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4920 return entry;
4921#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004922
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004923#ifdef CONFIG_OWE
4924 if (!wpas_network_disabled(wpa_s, entry) &&
4925 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4926 entry->ssid_len) &&
4927 (!entry->bssid_set ||
4928 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4929 return entry;
4930#endif /* CONFIG_OWE */
4931
Dmitry Shmidt04949592012-07-19 12:16:46 -07004932 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004933 entry->ssid_len == 0 &&
4934 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4935 return entry;
4936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004937 entry = entry->next;
4938 }
4939
4940 return NULL;
4941}
4942
4943
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004944static int select_driver(struct wpa_supplicant *wpa_s, int i)
4945{
4946 struct wpa_global *global = wpa_s->global;
4947
4948 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004949 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004950 if (global->drv_priv[i] == NULL) {
4951 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4952 "'%s'", wpa_drivers[i]->name);
4953 return -1;
4954 }
4955 }
4956
4957 wpa_s->driver = wpa_drivers[i];
4958 wpa_s->global_drv_priv = global->drv_priv[i];
4959
4960 return 0;
4961}
4962
4963
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004964static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4965 const char *name)
4966{
4967 int i;
4968 size_t len;
4969 const char *pos, *driver = name;
4970
4971 if (wpa_s == NULL)
4972 return -1;
4973
4974 if (wpa_drivers[0] == NULL) {
4975 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4976 "wpa_supplicant");
4977 return -1;
4978 }
4979
4980 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004981 /* Default to first successful driver in the list */
4982 for (i = 0; wpa_drivers[i]; i++) {
4983 if (select_driver(wpa_s, i) == 0)
4984 return 0;
4985 }
4986 /* Drivers have each reported failure, so no wpa_msg() here. */
4987 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004988 }
4989
4990 do {
4991 pos = os_strchr(driver, ',');
4992 if (pos)
4993 len = pos - driver;
4994 else
4995 len = os_strlen(driver);
4996
4997 for (i = 0; wpa_drivers[i]; i++) {
4998 if (os_strlen(wpa_drivers[i]->name) == len &&
4999 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005000 0) {
5001 /* First driver that succeeds wins */
5002 if (select_driver(wpa_s, i) == 0)
5003 return 0;
5004 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005005 }
5006
5007 driver = pos + 1;
5008 } while (pos);
5009
5010 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5011 return -1;
5012}
5013
5014
5015/**
5016 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5017 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5018 * with struct wpa_driver_ops::init()
5019 * @src_addr: Source address of the EAPOL frame
5020 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5021 * @len: Length of the EAPOL data
5022 *
5023 * This function is called for each received EAPOL frame. Most driver
5024 * interfaces rely on more generic OS mechanism for receiving frames through
5025 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5026 * take care of received EAPOL frames and deliver them to the core supplicant
5027 * code by calling this function.
5028 */
5029void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
5030 const u8 *buf, size_t len)
5031{
5032 struct wpa_supplicant *wpa_s = ctx;
5033
5034 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
5035 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5036
Hai Shalomc1a21442022-02-04 13:43:00 -08005037 if (wpa_s->own_disconnect_req) {
5038 wpa_printf(MSG_DEBUG,
5039 "Drop received EAPOL frame as we are disconnecting");
5040 return;
5041 }
5042
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005043#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005044 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5045 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005046 if (wpa_s->ignore_auth_resp) {
5047 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5048 return;
5049 }
5050#endif /* CONFIG_TESTING_OPTIONS */
5051
Jouni Malinena05074c2012-12-21 21:35:35 +02005052 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5053 (wpa_s->last_eapol_matches_bssid &&
5054#ifdef CONFIG_AP
5055 !wpa_s->ap_iface &&
5056#endif /* CONFIG_AP */
5057 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005058 /*
5059 * There is possible race condition between receiving the
5060 * association event and the EAPOL frame since they are coming
5061 * through different paths from the driver. In order to avoid
5062 * issues in trying to process the EAPOL frame before receiving
5063 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005064 * the association event is received. This may also be needed in
5065 * driver-based roaming case, so also use src_addr != BSSID as a
5066 * trigger if we have previously confirmed that the
5067 * Authenticator uses BSSID as the src_addr (which is not the
5068 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005069 */
5070 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005071 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5072 wpa_supplicant_state_txt(wpa_s->wpa_state),
5073 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005074 wpabuf_free(wpa_s->pending_eapol_rx);
5075 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5076 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005077 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005078 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5079 ETH_ALEN);
5080 }
5081 return;
5082 }
5083
Jouni Malinena05074c2012-12-21 21:35:35 +02005084 wpa_s->last_eapol_matches_bssid =
5085 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087#ifdef CONFIG_AP
5088 if (wpa_s->ap_iface) {
5089 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
5090 return;
5091 }
5092#endif /* CONFIG_AP */
5093
5094 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5095 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5096 "no key management is configured");
5097 return;
5098 }
5099
5100 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005101 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5103 wpa_s->wpa_state != WPA_COMPLETED) &&
5104 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005105 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005107 int timeout = 10;
5108
5109 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5110 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5111 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5112 /* Use longer timeout for IEEE 802.1X/EAP */
5113 timeout = 70;
5114 }
5115
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005116#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005117 if (wpa_s->current_ssid && wpa_s->current_bss &&
5118 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5119 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5120 /*
5121 * Use shorter timeout if going through WPS AP iteration
5122 * for PIN config method with an AP that does not
5123 * advertise Selected Registrar.
5124 */
5125 struct wpabuf *wps_ie;
5126
5127 wps_ie = wpa_bss_get_vendor_ie_multi(
5128 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5129 if (wps_ie &&
5130 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5131 timeout = 10;
5132 wpabuf_free(wps_ie);
5133 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005134#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005135
5136 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005137 }
5138 wpa_s->eapol_received++;
5139
5140 if (wpa_s->countermeasures) {
5141 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5142 "EAPOL packet");
5143 return;
5144 }
5145
5146#ifdef CONFIG_IBSS_RSN
5147 if (wpa_s->current_ssid &&
5148 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
5149 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
5150 return;
5151 }
5152#endif /* CONFIG_IBSS_RSN */
5153
5154 /* Source address of the incoming EAPOL frame could be compared to the
5155 * current BSSID. However, it is possible that a centralized
5156 * Authenticator could be using another MAC address than the BSSID of
5157 * an AP, so just allow any address to be used for now. The replies are
5158 * still sent to the current BSSID (if available), though. */
5159
5160 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5161 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005162 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5163 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005164 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
5165 return;
5166 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005167 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005168 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
5169 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5170 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005171 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005172 * handshake processing which would normally set portValid. We
5173 * need this to allow the EAPOL state machines to be completed
5174 * without going through EAPOL-Key handshake.
5175 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005176 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005177 }
5178}
5179
5180
Hai Shalomb755a2a2020-04-23 21:49:02 -07005181static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5182{
5183 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5184 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5185}
5186
5187
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005188int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005190 if ((!wpa_s->p2p_mgmt ||
5191 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5192 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005193 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5195 wpa_drv_get_mac_addr(wpa_s),
5196 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005197 wpas_eapol_needs_l2_packet(wpa_s) ?
5198 wpa_supplicant_rx_eapol : NULL,
5199 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005200 if (wpa_s->l2 == NULL)
5201 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005202
5203 if (l2_packet_set_packet_filter(wpa_s->l2,
5204 L2_PACKET_FILTER_PKTTYPE))
5205 wpa_dbg(wpa_s, MSG_DEBUG,
5206 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005207
5208 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5209 wpa_msg(wpa_s, MSG_ERROR,
5210 "Failed to get own L2 address");
5211 return -1;
5212 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005213 } else {
5214 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5215 if (addr)
5216 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5217 }
5218
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005219 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005220 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005221
Hai Shalomc3565922019-10-28 11:58:20 -07005222#ifdef CONFIG_FST
5223 if (wpa_s->fst)
5224 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5225#endif /* CONFIG_FST */
5226
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005227 return 0;
5228}
5229
5230
Dmitry Shmidt04949592012-07-19 12:16:46 -07005231static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5232 const u8 *buf, size_t len)
5233{
5234 struct wpa_supplicant *wpa_s = ctx;
5235 const struct l2_ethhdr *eth;
5236
5237 if (len < sizeof(*eth))
5238 return;
5239 eth = (const struct l2_ethhdr *) buf;
5240
5241 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5242 !(eth->h_dest[0] & 0x01)) {
5243 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5244 " (bridge - not for this interface - ignore)",
5245 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5246 return;
5247 }
5248
5249 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5250 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5251 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5252 len - sizeof(*eth));
5253}
5254
5255
Hai Shalom899fcc72020-10-19 14:38:18 -07005256int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5257 const char *bridge_ifname)
5258{
5259 if (wpa_s->wpa_state > WPA_SCANNING)
5260 return -EBUSY;
5261
5262 if (bridge_ifname &&
5263 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5264 return -EINVAL;
5265
5266 if (!bridge_ifname)
5267 bridge_ifname = "";
5268
5269 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5270 return 0;
5271
5272 if (wpa_s->l2_br) {
5273 l2_packet_deinit(wpa_s->l2_br);
5274 wpa_s->l2_br = NULL;
5275 }
5276
5277 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5278 sizeof(wpa_s->bridge_ifname));
5279
5280 if (wpa_s->bridge_ifname[0]) {
5281 wpa_dbg(wpa_s, MSG_DEBUG,
5282 "Receiving packets from bridge interface '%s'",
5283 wpa_s->bridge_ifname);
5284 wpa_s->l2_br = l2_packet_init_bridge(
5285 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5286 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5287 if (!wpa_s->l2_br) {
5288 wpa_msg(wpa_s, MSG_ERROR,
5289 "Failed to open l2_packet connection for the bridge interface '%s'",
5290 wpa_s->bridge_ifname);
5291 goto fail;
5292 }
5293 }
5294
5295#ifdef CONFIG_TDLS
5296 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5297 goto fail;
5298#endif /* CONFIG_TDLS */
5299
5300 return 0;
5301fail:
5302 wpa_s->bridge_ifname[0] = 0;
5303 if (wpa_s->l2_br) {
5304 l2_packet_deinit(wpa_s->l2_br);
5305 wpa_s->l2_br = NULL;
5306 }
5307#ifdef CONFIG_TDLS
5308 if (!wpa_s->p2p_mgmt)
5309 wpa_tdls_init(wpa_s->wpa);
5310#endif /* CONFIG_TDLS */
5311 return -EIO;
5312}
5313
5314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005315/**
5316 * wpa_supplicant_driver_init - Initialize driver interface parameters
5317 * @wpa_s: Pointer to wpa_supplicant data
5318 * Returns: 0 on success, -1 on failure
5319 *
5320 * This function is called to initialize driver interface parameters.
5321 * wpa_drv_init() must have been called before this function to initialize the
5322 * driver interface.
5323 */
5324int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5325{
5326 static int interface_count = 0;
5327
5328 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5329 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005330
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005331 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5332 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005333 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005334 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5335
Hai Shalomb755a2a2020-04-23 21:49:02 -07005336 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005337 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5338 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005339 wpa_s->l2_br = l2_packet_init_bridge(
5340 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5341 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005342 if (wpa_s->l2_br == NULL) {
5343 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5344 "connection for the bridge interface '%s'",
5345 wpa_s->bridge_ifname);
5346 return -1;
5347 }
5348 }
5349
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005350 if (wpa_s->conf->ap_scan == 2 &&
5351 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5352 wpa_printf(MSG_INFO,
5353 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5354 }
5355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005356 wpa_clear_keys(wpa_s, NULL);
5357
5358 /* Make sure that TKIP countermeasures are not left enabled (could
5359 * happen if wpa_supplicant is killed during countermeasures. */
5360 wpa_drv_set_countermeasures(wpa_s, 0);
5361
5362 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5363 wpa_drv_flush_pmkid(wpa_s);
5364
5365 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005366 wpa_s->prev_scan_wildcard = 0;
5367
Dmitry Shmidt04949592012-07-19 12:16:46 -07005368 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005369 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5370 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5371 interface_count = 0;
5372 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005373#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005374 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005375 wpa_supplicant_delayed_sched_scan(wpa_s,
5376 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005377 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005378 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005379 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005380#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005381 interface_count++;
5382 } else
5383 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5384
5385 return 0;
5386}
5387
5388
5389static int wpa_supplicant_daemon(const char *pid_file)
5390{
5391 wpa_printf(MSG_DEBUG, "Daemonize..");
5392 return os_daemonize(pid_file);
5393}
5394
5395
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005396static struct wpa_supplicant *
5397wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005398{
5399 struct wpa_supplicant *wpa_s;
5400
5401 wpa_s = os_zalloc(sizeof(*wpa_s));
5402 if (wpa_s == NULL)
5403 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005404 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005405 wpa_s->scan_interval = 5;
5406 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005407 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005408 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005409 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005410 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005411
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005412 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005413 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005414#ifdef CONFIG_TESTING_OPTIONS
5415 dl_list_init(&wpa_s->drv_signal_override);
5416#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005417 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005418
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005419 return wpa_s;
5420}
5421
5422
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005423#ifdef CONFIG_HT_OVERRIDES
5424
5425static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5426 struct ieee80211_ht_capabilities *htcaps,
5427 struct ieee80211_ht_capabilities *htcaps_mask,
5428 const char *ht_mcs)
5429{
5430 /* parse ht_mcs into hex array */
5431 int i;
5432 const char *tmp = ht_mcs;
5433 char *end = NULL;
5434
5435 /* If ht_mcs is null, do not set anything */
5436 if (!ht_mcs)
5437 return 0;
5438
5439 /* This is what we are setting in the kernel */
5440 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5441
5442 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5443
5444 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005445 long v;
5446
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005447 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005448 v = strtol(tmp, &end, 16);
5449
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005450 if (errno == 0) {
5451 wpa_msg(wpa_s, MSG_DEBUG,
5452 "htcap value[%i]: %ld end: %p tmp: %p",
5453 i, v, end, tmp);
5454 if (end == tmp)
5455 break;
5456
5457 htcaps->supported_mcs_set[i] = v;
5458 tmp = end;
5459 } else {
5460 wpa_msg(wpa_s, MSG_ERROR,
5461 "Failed to parse ht-mcs: %s, error: %s\n",
5462 ht_mcs, strerror(errno));
5463 return -1;
5464 }
5465 }
5466
5467 /*
5468 * If we were able to parse any values, then set mask for the MCS set.
5469 */
5470 if (i) {
5471 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5472 IEEE80211_HT_MCS_MASK_LEN - 1);
5473 /* skip the 3 reserved bits */
5474 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5475 0x1f;
5476 }
5477
5478 return 0;
5479}
5480
5481
5482static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5483 struct ieee80211_ht_capabilities *htcaps,
5484 struct ieee80211_ht_capabilities *htcaps_mask,
5485 int disabled)
5486{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005487 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005488
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005489 if (disabled == -1)
5490 return 0;
5491
Hai Shalom74f70d42019-02-11 14:42:39 -08005492 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5493
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005494 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5495 htcaps_mask->ht_capabilities_info |= msk;
5496 if (disabled)
5497 htcaps->ht_capabilities_info &= msk;
5498 else
5499 htcaps->ht_capabilities_info |= msk;
5500
5501 return 0;
5502}
5503
5504
5505static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5506 struct ieee80211_ht_capabilities *htcaps,
5507 struct ieee80211_ht_capabilities *htcaps_mask,
5508 int factor)
5509{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005510 if (factor == -1)
5511 return 0;
5512
Hai Shalom74f70d42019-02-11 14:42:39 -08005513 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5514
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005515 if (factor < 0 || factor > 3) {
5516 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5517 "Must be 0-3 or -1", factor);
5518 return -EINVAL;
5519 }
5520
5521 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5522 htcaps->a_mpdu_params &= ~0x3;
5523 htcaps->a_mpdu_params |= factor & 0x3;
5524
5525 return 0;
5526}
5527
5528
5529static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5530 struct ieee80211_ht_capabilities *htcaps,
5531 struct ieee80211_ht_capabilities *htcaps_mask,
5532 int density)
5533{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005534 if (density == -1)
5535 return 0;
5536
Hai Shalom74f70d42019-02-11 14:42:39 -08005537 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5538
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005539 if (density < 0 || density > 7) {
5540 wpa_msg(wpa_s, MSG_ERROR,
5541 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5542 density);
5543 return -EINVAL;
5544 }
5545
5546 htcaps_mask->a_mpdu_params |= 0x1C;
5547 htcaps->a_mpdu_params &= ~(0x1C);
5548 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5549
5550 return 0;
5551}
5552
5553
5554static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5555 struct ieee80211_ht_capabilities *htcaps,
5556 struct ieee80211_ht_capabilities *htcaps_mask,
5557 int disabled)
5558{
Hai Shalom74f70d42019-02-11 14:42:39 -08005559 if (disabled)
5560 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005561
Paul Stewart092955c2017-02-06 09:13:09 -08005562 set_disable_ht40(htcaps, disabled);
5563 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005564
5565 return 0;
5566}
5567
5568
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005569static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5570 struct ieee80211_ht_capabilities *htcaps,
5571 struct ieee80211_ht_capabilities *htcaps_mask,
5572 int disabled)
5573{
5574 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005575 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5576 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005577
Hai Shalom74f70d42019-02-11 14:42:39 -08005578 if (disabled)
5579 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005580
5581 if (disabled)
5582 htcaps->ht_capabilities_info &= ~msk;
5583 else
5584 htcaps->ht_capabilities_info |= msk;
5585
5586 htcaps_mask->ht_capabilities_info |= msk;
5587
5588 return 0;
5589}
5590
5591
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005592static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5593 struct ieee80211_ht_capabilities *htcaps,
5594 struct ieee80211_ht_capabilities *htcaps_mask,
5595 int disabled)
5596{
5597 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005598 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005599
Hai Shalom74f70d42019-02-11 14:42:39 -08005600 if (disabled)
5601 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005602
5603 if (disabled)
5604 htcaps->ht_capabilities_info &= ~msk;
5605 else
5606 htcaps->ht_capabilities_info |= msk;
5607
5608 htcaps_mask->ht_capabilities_info |= msk;
5609
5610 return 0;
5611}
5612
5613
Hai Shalom74f70d42019-02-11 14:42:39 -08005614static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5615 struct ieee80211_ht_capabilities *htcaps,
5616 struct ieee80211_ht_capabilities *htcaps_mask,
5617 int tx_stbc)
5618{
5619 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5620
5621 if (tx_stbc == -1)
5622 return 0;
5623
5624 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5625
5626 if (tx_stbc < 0 || tx_stbc > 1) {
5627 wpa_msg(wpa_s, MSG_ERROR,
5628 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5629 return -EINVAL;
5630 }
5631
5632 htcaps_mask->ht_capabilities_info |= msk;
5633 htcaps->ht_capabilities_info &= ~msk;
5634 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5635
5636 return 0;
5637}
5638
5639
5640static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5641 struct ieee80211_ht_capabilities *htcaps,
5642 struct ieee80211_ht_capabilities *htcaps_mask,
5643 int rx_stbc)
5644{
5645 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5646
5647 if (rx_stbc == -1)
5648 return 0;
5649
5650 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5651
5652 if (rx_stbc < 0 || rx_stbc > 3) {
5653 wpa_msg(wpa_s, MSG_ERROR,
5654 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5655 return -EINVAL;
5656 }
5657
5658 htcaps_mask->ht_capabilities_info |= msk;
5659 htcaps->ht_capabilities_info &= ~msk;
5660 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5661
5662 return 0;
5663}
5664
5665
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005666void wpa_supplicant_apply_ht_overrides(
5667 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5668 struct wpa_driver_associate_params *params)
5669{
5670 struct ieee80211_ht_capabilities *htcaps;
5671 struct ieee80211_ht_capabilities *htcaps_mask;
5672
5673 if (!ssid)
5674 return;
5675
5676 params->disable_ht = ssid->disable_ht;
5677 if (!params->htcaps || !params->htcaps_mask)
5678 return;
5679
5680 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5681 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5682 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5683 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5684 ssid->disable_max_amsdu);
5685 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5686 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5687 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005688 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005689 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005690 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5691 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005692
5693 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005694 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005695 htcaps->ht_capabilities_info |= bit;
5696 htcaps_mask->ht_capabilities_info |= bit;
5697 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005698}
5699
5700#endif /* CONFIG_HT_OVERRIDES */
5701
5702
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005703#ifdef CONFIG_VHT_OVERRIDES
5704void wpa_supplicant_apply_vht_overrides(
5705 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5706 struct wpa_driver_associate_params *params)
5707{
5708 struct ieee80211_vht_capabilities *vhtcaps;
5709 struct ieee80211_vht_capabilities *vhtcaps_mask;
5710
5711 if (!ssid)
5712 return;
5713
5714 params->disable_vht = ssid->disable_vht;
5715
5716 vhtcaps = (void *) params->vhtcaps;
5717 vhtcaps_mask = (void *) params->vhtcaps_mask;
5718
5719 if (!vhtcaps || !vhtcaps_mask)
5720 return;
5721
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005722 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5723 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005724
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005725#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005726 if (ssid->disable_sgi) {
5727 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5728 VHT_CAP_SHORT_GI_160);
5729 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5730 VHT_CAP_SHORT_GI_160);
5731 wpa_msg(wpa_s, MSG_DEBUG,
5732 "disable-sgi override specified, vht-caps: 0x%x",
5733 vhtcaps->vht_capabilities_info);
5734 }
5735
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005736 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005737 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5738 int max_ampdu;
5739
5740 max_ampdu = (ssid->vht_capa &
5741 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5742 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005743
5744 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5745 wpa_set_ampdu_factor(wpa_s,
5746 (void *) params->htcaps,
5747 (void *) params->htcaps_mask,
5748 max_ampdu);
5749 }
5750#endif /* CONFIG_HT_OVERRIDES */
5751
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005752#define OVERRIDE_MCS(i) \
5753 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5754 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005755 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005756 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005757 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5758 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005759 } \
5760 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5761 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005762 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005763 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005764 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5765 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005766 }
5767
5768 OVERRIDE_MCS(1);
5769 OVERRIDE_MCS(2);
5770 OVERRIDE_MCS(3);
5771 OVERRIDE_MCS(4);
5772 OVERRIDE_MCS(5);
5773 OVERRIDE_MCS(6);
5774 OVERRIDE_MCS(7);
5775 OVERRIDE_MCS(8);
5776}
5777#endif /* CONFIG_VHT_OVERRIDES */
5778
5779
Hai Shalomfdcde762020-04-02 11:19:20 -07005780#ifdef CONFIG_HE_OVERRIDES
5781void wpa_supplicant_apply_he_overrides(
5782 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5783 struct wpa_driver_associate_params *params)
5784{
5785 if (!ssid)
5786 return;
5787
5788 params->disable_he = ssid->disable_he;
5789}
5790#endif /* CONFIG_HE_OVERRIDES */
5791
5792
Dmitry Shmidt04949592012-07-19 12:16:46 -07005793static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5794{
5795#ifdef PCSC_FUNCS
5796 size_t len;
5797
5798 if (!wpa_s->conf->pcsc_reader)
5799 return 0;
5800
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005801 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005802 if (!wpa_s->scard)
5803 return 1;
5804
5805 if (wpa_s->conf->pcsc_pin &&
5806 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5807 scard_deinit(wpa_s->scard);
5808 wpa_s->scard = NULL;
5809 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5810 return -1;
5811 }
5812
5813 len = sizeof(wpa_s->imsi) - 1;
5814 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5815 scard_deinit(wpa_s->scard);
5816 wpa_s->scard = NULL;
5817 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5818 return -1;
5819 }
5820 wpa_s->imsi[len] = '\0';
5821
5822 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5823
5824 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5825 wpa_s->imsi, wpa_s->mnc_len);
5826
5827 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5828 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5829#endif /* PCSC_FUNCS */
5830
5831 return 0;
5832}
5833
5834
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005835int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5836{
5837 char *val, *pos;
5838
5839 ext_password_deinit(wpa_s->ext_pw);
5840 wpa_s->ext_pw = NULL;
5841 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5842
5843 if (!wpa_s->conf->ext_password_backend)
5844 return 0;
5845
5846 val = os_strdup(wpa_s->conf->ext_password_backend);
5847 if (val == NULL)
5848 return -1;
5849 pos = os_strchr(val, ':');
5850 if (pos)
5851 *pos++ = '\0';
5852
5853 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5854
5855 wpa_s->ext_pw = ext_password_init(val, pos);
5856 os_free(val);
5857 if (wpa_s->ext_pw == NULL) {
5858 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5859 return -1;
5860 }
5861 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5862
5863 return 0;
5864}
5865
5866
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005867#ifdef CONFIG_FST
5868
5869static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5870{
5871 struct wpa_supplicant *wpa_s = ctx;
5872
5873 return (is_zero_ether_addr(wpa_s->bssid) ||
5874 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5875}
5876
5877
5878static void wpas_fst_get_channel_info_cb(void *ctx,
5879 enum hostapd_hw_mode *hw_mode,
5880 u8 *channel)
5881{
5882 struct wpa_supplicant *wpa_s = ctx;
5883
5884 if (wpa_s->current_bss) {
5885 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5886 channel);
5887 } else if (wpa_s->hw.num_modes) {
5888 *hw_mode = wpa_s->hw.modes[0].mode;
5889 } else {
5890 WPA_ASSERT(0);
5891 *hw_mode = 0;
5892 }
5893}
5894
5895
5896static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5897{
5898 struct wpa_supplicant *wpa_s = ctx;
5899
5900 *modes = wpa_s->hw.modes;
5901 return wpa_s->hw.num_modes;
5902}
5903
5904
5905static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5906{
5907 struct wpa_supplicant *wpa_s = ctx;
5908
5909 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5910 wpa_s->fst_ies = fst_ies;
5911}
5912
5913
5914static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5915{
5916 struct wpa_supplicant *wpa_s = ctx;
5917
Paul Stewart092955c2017-02-06 09:13:09 -08005918 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5919 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5920 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5921 return -1;
5922 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005923 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005924 wpa_s->own_addr, wpa_s->bssid,
5925 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005926 0);
5927}
5928
5929
5930static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5931{
5932 struct wpa_supplicant *wpa_s = ctx;
5933
5934 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5935 return wpa_s->received_mb_ies;
5936}
5937
5938
5939static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5940 const u8 *buf, size_t size)
5941{
5942 struct wpa_supplicant *wpa_s = ctx;
5943 struct mb_ies_info info;
5944
5945 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5946
5947 if (!mb_ies_info_by_ies(&info, buf, size)) {
5948 wpabuf_free(wpa_s->received_mb_ies);
5949 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5950 }
5951}
5952
5953
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005954static const u8 * wpas_fst_get_peer_first(void *ctx,
5955 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005956 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005957{
5958 struct wpa_supplicant *wpa_s = ctx;
5959
5960 *get_ctx = NULL;
5961 if (!is_zero_ether_addr(wpa_s->bssid))
5962 return (wpa_s->received_mb_ies || !mb_only) ?
5963 wpa_s->bssid : NULL;
5964 return NULL;
5965}
5966
5967
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005968static const u8 * wpas_fst_get_peer_next(void *ctx,
5969 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005970 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005971{
5972 return NULL;
5973}
5974
5975void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5976 struct fst_wpa_obj *iface_obj)
5977{
5978 iface_obj->ctx = wpa_s;
5979 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5980 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5981 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5982 iface_obj->set_ies = wpas_fst_set_ies_cb;
5983 iface_obj->send_action = wpas_fst_send_action_cb;
5984 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5985 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5986 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5987 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5988}
5989#endif /* CONFIG_FST */
5990
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005991static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005992 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005993{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005994 struct wowlan_triggers *triggers;
5995 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005996
5997 if (!wpa_s->conf->wowlan_triggers)
5998 return 0;
5999
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006000 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6001 if (triggers) {
6002 ret = wpa_drv_wowlan(wpa_s, triggers);
6003 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006004 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006005 return ret;
6006}
6007
6008
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006009enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006010{
6011 if (freq < 3000)
6012 return BAND_2_4_GHZ;
6013 if (freq > 50000)
6014 return BAND_60_GHZ;
6015 return BAND_5_GHZ;
6016}
6017
6018
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006019unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006020{
6021 int i;
6022 unsigned int band = 0;
6023
6024 if (freqs) {
6025 /* freqs are specified for the radio work */
6026 for (i = 0; freqs[i]; i++)
6027 band |= wpas_freq_to_band(freqs[i]);
6028 } else {
6029 /*
6030 * freqs are not specified, implies all
6031 * the supported freqs by HW
6032 */
6033 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6034 if (wpa_s->hw.modes[i].num_channels != 0) {
6035 if (wpa_s->hw.modes[i].mode ==
6036 HOSTAPD_MODE_IEEE80211B ||
6037 wpa_s->hw.modes[i].mode ==
6038 HOSTAPD_MODE_IEEE80211G)
6039 band |= BAND_2_4_GHZ;
6040 else if (wpa_s->hw.modes[i].mode ==
6041 HOSTAPD_MODE_IEEE80211A)
6042 band |= BAND_5_GHZ;
6043 else if (wpa_s->hw.modes[i].mode ==
6044 HOSTAPD_MODE_IEEE80211AD)
6045 band |= BAND_60_GHZ;
6046 else if (wpa_s->hw.modes[i].mode ==
6047 HOSTAPD_MODE_IEEE80211ANY)
6048 band = BAND_2_4_GHZ | BAND_5_GHZ |
6049 BAND_60_GHZ;
6050 }
6051 }
6052 }
6053
6054 return band;
6055}
6056
6057
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006058static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6059 const char *rn)
6060{
6061 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6062 struct wpa_radio *radio;
6063
6064 while (rn && iface) {
6065 radio = iface->radio;
6066 if (radio && os_strcmp(rn, radio->name) == 0) {
6067 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6068 wpa_s->ifname, rn);
6069 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6070 return radio;
6071 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006072
6073 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006074 }
6075
6076 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6077 wpa_s->ifname, rn ? rn : "N/A");
6078 radio = os_zalloc(sizeof(*radio));
6079 if (radio == NULL)
6080 return NULL;
6081
6082 if (rn)
6083 os_strlcpy(radio->name, rn, sizeof(radio->name));
6084 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006085 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006086 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6087
6088 return radio;
6089}
6090
6091
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006092static void radio_work_free(struct wpa_radio_work *work)
6093{
6094 if (work->wpa_s->scan_work == work) {
6095 /* This should not really happen. */
6096 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6097 work->type, work, work->started);
6098 work->wpa_s->scan_work = NULL;
6099 }
6100
6101#ifdef CONFIG_P2P
6102 if (work->wpa_s->p2p_scan_work == work) {
6103 /* This should not really happen. */
6104 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6105 work->type, work, work->started);
6106 work->wpa_s->p2p_scan_work = NULL;
6107 }
6108#endif /* CONFIG_P2P */
6109
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006110 if (work->started) {
6111 work->wpa_s->radio->num_active_works--;
6112 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006113 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006114 work->type, work,
6115 work->wpa_s->radio->num_active_works);
6116 }
6117
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006118 dl_list_del(&work->list);
6119 os_free(work);
6120}
6121
6122
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006123static int radio_work_is_connect(struct wpa_radio_work *work)
6124{
6125 return os_strcmp(work->type, "sme-connect") == 0 ||
6126 os_strcmp(work->type, "connect") == 0;
6127}
6128
6129
6130static int radio_work_is_scan(struct wpa_radio_work *work)
6131{
6132 return os_strcmp(work->type, "scan") == 0 ||
6133 os_strcmp(work->type, "p2p-scan") == 0;
6134}
6135
6136
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006137static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6138{
6139 struct wpa_radio_work *active_work = NULL;
6140 struct wpa_radio_work *tmp;
6141
6142 /* Get the active work to know the type and band. */
6143 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6144 if (tmp->started) {
6145 active_work = tmp;
6146 break;
6147 }
6148 }
6149
6150 if (!active_work) {
6151 /* No active work, start one */
6152 radio->num_active_works = 0;
6153 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6154 list) {
6155 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006156 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006157 (((struct wpa_driver_scan_params *)
6158 tmp->ctx)->only_new_results ||
6159 tmp->wpa_s->clear_driver_scan_cache))
6160 continue;
6161 return tmp;
6162 }
6163 return NULL;
6164 }
6165
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006166 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006167 /*
6168 * If the active work is either connect or sme-connect,
6169 * do not parallelize them with other radio works.
6170 */
6171 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6172 "Do not parallelize radio work with %s",
6173 active_work->type);
6174 return NULL;
6175 }
6176
6177 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6178 if (tmp->started)
6179 continue;
6180
6181 /*
6182 * If connect or sme-connect are enqueued, parallelize only
6183 * those operations ahead of them in the queue.
6184 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006185 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006186 break;
6187
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006188 /* Serialize parallel scan and p2p_scan operations on the same
6189 * interface since the driver_nl80211 mechanism for tracking
6190 * scan cookies does not yet have support for this. */
6191 if (active_work->wpa_s == tmp->wpa_s &&
6192 radio_work_is_scan(active_work) &&
6193 radio_work_is_scan(tmp)) {
6194 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6195 "Do not start work '%s' when another work '%s' is already scheduled",
6196 tmp->type, active_work->type);
6197 continue;
6198 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006199 /*
6200 * Check that the radio works are distinct and
6201 * on different bands.
6202 */
6203 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6204 (active_work->bands != tmp->bands)) {
6205 /*
6206 * If a scan has to be scheduled through nl80211 scan
6207 * interface and if an external scan is already running,
6208 * do not schedule the scan since it is likely to get
6209 * rejected by kernel.
6210 */
6211 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006212 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006213 (((struct wpa_driver_scan_params *)
6214 tmp->ctx)->only_new_results ||
6215 tmp->wpa_s->clear_driver_scan_cache))
6216 continue;
6217
6218 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6219 "active_work:%s new_work:%s",
6220 active_work->type, tmp->type);
6221 return tmp;
6222 }
6223 }
6224
6225 /* Did not find a radio work to schedule in parallel. */
6226 return NULL;
6227}
6228
6229
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006230static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6231{
6232 struct wpa_radio *radio = eloop_ctx;
6233 struct wpa_radio_work *work;
6234 struct os_reltime now, diff;
6235 struct wpa_supplicant *wpa_s;
6236
6237 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006238 if (work == NULL) {
6239 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006240 return;
6241 }
6242
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006243 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6244 radio_list);
6245
6246 if (!(wpa_s &&
6247 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6248 if (work->started)
6249 return; /* already started and still in progress */
6250
Hai Shalom60840252021-02-19 19:02:11 -08006251 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006252 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6253 return;
6254 }
6255 } else {
6256 work = NULL;
6257 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6258 /* get the work to schedule next */
6259 work = radio_work_get_next_work(radio);
6260 }
6261 if (!work)
6262 return;
6263 }
6264
6265 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006266 os_get_reltime(&now);
6267 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006268 wpa_dbg(wpa_s, MSG_DEBUG,
6269 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006270 work->type, work, diff.sec, diff.usec);
6271 work->started = 1;
6272 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006273 radio->num_active_works++;
6274
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006275 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006276
6277 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6278 radio->num_active_works < MAX_ACTIVE_WORKS)
6279 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006280}
6281
6282
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006283/*
6284 * This function removes both started and pending radio works running on
6285 * the provided interface's radio.
6286 * Prior to the removal of the radio work, its callback (cb) is called with
6287 * deinit set to be 1. Each work's callback is responsible for clearing its
6288 * internal data and restoring to a correct state.
6289 * @wpa_s: wpa_supplicant data
6290 * @type: type of works to be removed
6291 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6292 * this interface's works.
6293 */
6294void radio_remove_works(struct wpa_supplicant *wpa_s,
6295 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006296{
6297 struct wpa_radio_work *work, *tmp;
6298 struct wpa_radio *radio = wpa_s->radio;
6299
6300 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6301 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006302 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006303 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006304
6305 /* skip other ifaces' works */
6306 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006307 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006308
6309 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6310 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006311 work->cb(work, 1);
6312 radio_work_free(work);
6313 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006314
6315 /* in case we removed the started work */
6316 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006317}
6318
6319
Roshan Pius3a1667e2018-07-03 15:17:14 -07006320void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6321{
6322 struct wpa_radio_work *work;
6323 struct wpa_radio *radio = wpa_s->radio;
6324
6325 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6326 if (work->ctx != ctx)
6327 continue;
6328 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6329 work->type, work, work->started ? " (started)" : "");
6330 radio_work_free(work);
6331 break;
6332 }
6333}
6334
6335
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006336static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6337{
6338 struct wpa_radio *radio = wpa_s->radio;
6339
6340 if (!radio)
6341 return;
6342
6343 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6344 wpa_s->ifname, radio->name);
6345 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006346 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006347 /* If the interface that triggered the external scan was removed, the
6348 * external scan is no longer running. */
6349 if (wpa_s == radio->external_scan_req_interface)
6350 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006351 wpa_s->radio = NULL;
6352 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006353 return; /* Interfaces remain for this radio */
6354
6355 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006356 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006357 os_free(radio);
6358}
6359
6360
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006361void radio_work_check_next(struct wpa_supplicant *wpa_s)
6362{
6363 struct wpa_radio *radio = wpa_s->radio;
6364
6365 if (dl_list_empty(&radio->work))
6366 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006367 if (wpa_s->ext_work_in_progress) {
6368 wpa_printf(MSG_DEBUG,
6369 "External radio work in progress - delay start of pending item");
6370 return;
6371 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006372 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6373 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6374}
6375
6376
6377/**
6378 * radio_add_work - Add a radio work item
6379 * @wpa_s: Pointer to wpa_supplicant data
6380 * @freq: Frequency of the offchannel operation in MHz or 0
6381 * @type: Unique identifier for each type of work
6382 * @next: Force as the next work to be executed
6383 * @cb: Callback function for indicating when radio is available
6384 * @ctx: Context pointer for the work (work->ctx in cb())
6385 * Returns: 0 on success, -1 on failure
6386 *
6387 * This function is used to request time for an operation that requires
6388 * exclusive radio control. Once the radio is available, the registered callback
6389 * function will be called. radio_work_done() must be called once the exclusive
6390 * radio operation has been completed, so that the radio is freed for other
6391 * operations. The special case of deinit=1 is used to free the context data
6392 * during interface removal. That does not allow the callback function to start
6393 * the radio operation, i.e., it must free any resources allocated for the radio
6394 * work and return.
6395 *
6396 * The @freq parameter can be used to indicate a single channel on which the
6397 * offchannel operation will occur. This may allow multiple radio work
6398 * operations to be performed in parallel if they apply for the same channel.
6399 * Setting this to 0 indicates that the work item may use multiple channels or
6400 * requires exclusive control of the radio.
6401 */
6402int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6403 const char *type, int next,
6404 void (*cb)(struct wpa_radio_work *work, int deinit),
6405 void *ctx)
6406{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006407 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006408 struct wpa_radio_work *work;
6409 int was_empty;
6410
6411 work = os_zalloc(sizeof(*work));
6412 if (work == NULL)
6413 return -1;
6414 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6415 os_get_reltime(&work->time);
6416 work->freq = freq;
6417 work->type = type;
6418 work->wpa_s = wpa_s;
6419 work->cb = cb;
6420 work->ctx = ctx;
6421
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006422 if (freq)
6423 work->bands = wpas_freq_to_band(freq);
6424 else if (os_strcmp(type, "scan") == 0 ||
6425 os_strcmp(type, "p2p-scan") == 0)
6426 work->bands = wpas_get_bands(wpa_s,
6427 ((struct wpa_driver_scan_params *)
6428 ctx)->freqs);
6429 else
6430 work->bands = wpas_get_bands(wpa_s, NULL);
6431
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006432 was_empty = dl_list_empty(&wpa_s->radio->work);
6433 if (next)
6434 dl_list_add(&wpa_s->radio->work, &work->list);
6435 else
6436 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6437 if (was_empty) {
6438 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6439 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006440 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6441 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6442 wpa_dbg(wpa_s, MSG_DEBUG,
6443 "Try to schedule a radio work (num_active_works=%u)",
6444 radio->num_active_works);
6445 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006446 }
6447
6448 return 0;
6449}
6450
6451
6452/**
6453 * radio_work_done - Indicate that a radio work item has been completed
6454 * @work: Completed work
6455 *
6456 * This function is called once the callback function registered with
6457 * radio_add_work() has completed its work.
6458 */
6459void radio_work_done(struct wpa_radio_work *work)
6460{
6461 struct wpa_supplicant *wpa_s = work->wpa_s;
6462 struct os_reltime now, diff;
6463 unsigned int started = work->started;
6464
6465 os_get_reltime(&now);
6466 os_reltime_sub(&now, &work->time, &diff);
6467 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6468 work->type, work, started ? "done" : "canceled",
6469 diff.sec, diff.usec);
6470 radio_work_free(work);
6471 if (started)
6472 radio_work_check_next(wpa_s);
6473}
6474
6475
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006476struct wpa_radio_work *
6477radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006478{
6479 struct wpa_radio_work *work;
6480 struct wpa_radio *radio = wpa_s->radio;
6481
6482 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6483 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006484 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006485 }
6486
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006487 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006488}
6489
6490
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006491static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006492 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006493{
6494 const char *ifname, *driver, *rn;
6495
6496 driver = iface->driver;
6497next_driver:
6498 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6499 return -1;
6500
6501 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6502 if (wpa_s->drv_priv == NULL) {
6503 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006504 int level = MSG_ERROR;
6505
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006506 pos = driver ? os_strchr(driver, ',') : NULL;
6507 if (pos) {
6508 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6509 "driver interface - try next driver wrapper");
6510 driver = pos + 1;
6511 goto next_driver;
6512 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006513
6514#ifdef CONFIG_MATCH_IFACE
6515 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6516 level = MSG_DEBUG;
6517#endif /* CONFIG_MATCH_IFACE */
6518 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006519 return -1;
6520 }
6521 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6522 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6523 "driver_param '%s'", wpa_s->conf->driver_param);
6524 return -1;
6525 }
6526
6527 ifname = wpa_drv_get_ifname(wpa_s);
6528 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6529 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6530 "interface name with '%s'", ifname);
6531 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6532 }
6533
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006534 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006535 if (rn && rn[0] == '\0')
6536 rn = NULL;
6537
6538 wpa_s->radio = radio_add_interface(wpa_s, rn);
6539 if (wpa_s->radio == NULL)
6540 return -1;
6541
6542 return 0;
6543}
6544
6545
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006546#ifdef CONFIG_GAS_SERVER
6547
6548static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6549 unsigned int freq, const u8 *dst,
6550 const u8 *src, const u8 *bssid,
6551 const u8 *data, size_t data_len,
6552 enum offchannel_send_action_result result)
6553{
6554 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6555 " result=%s",
6556 freq, MAC2STR(dst),
6557 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6558 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6559 "FAILED"));
6560 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6561 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6562}
6563
6564
6565static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6566 struct wpabuf *buf, unsigned int wait_time)
6567{
6568 struct wpa_supplicant *wpa_s = ctx;
6569 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6570
6571 if (wait_time > wpa_s->max_remain_on_chan)
6572 wait_time = wpa_s->max_remain_on_chan;
6573
6574 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6575 wpabuf_head(buf), wpabuf_len(buf),
6576 wait_time, wpas_gas_server_tx_status, 0);
6577}
6578
6579#endif /* CONFIG_GAS_SERVER */
6580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006581static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006582 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006583{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006584 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006585 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006586 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006587
6588 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6589 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6590 iface->confname ? iface->confname : "N/A",
6591 iface->driver ? iface->driver : "default",
6592 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6593 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6594
6595 if (iface->confname) {
6596#ifdef CONFIG_BACKEND_FILE
6597 wpa_s->confname = os_rel2abs_path(iface->confname);
6598 if (wpa_s->confname == NULL) {
6599 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6600 "for configuration file '%s'.",
6601 iface->confname);
6602 return -1;
6603 }
6604 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6605 iface->confname, wpa_s->confname);
6606#else /* CONFIG_BACKEND_FILE */
6607 wpa_s->confname = os_strdup(iface->confname);
6608#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006609 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006610 if (wpa_s->conf == NULL) {
6611 wpa_printf(MSG_ERROR, "Failed to read or parse "
6612 "configuration '%s'.", wpa_s->confname);
6613 return -1;
6614 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006615 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006616 if (wpa_s->confanother &&
6617 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6618 wpa_printf(MSG_ERROR,
6619 "Failed to read or parse configuration '%s'.",
6620 wpa_s->confanother);
6621 return -1;
6622 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006623
6624 /*
6625 * Override ctrl_interface and driver_param if set on command
6626 * line.
6627 */
6628 if (iface->ctrl_interface) {
6629 os_free(wpa_s->conf->ctrl_interface);
6630 wpa_s->conf->ctrl_interface =
6631 os_strdup(iface->ctrl_interface);
6632 }
6633
6634 if (iface->driver_param) {
6635 os_free(wpa_s->conf->driver_param);
6636 wpa_s->conf->driver_param =
6637 os_strdup(iface->driver_param);
6638 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006639
6640 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6641 os_free(wpa_s->conf->ctrl_interface);
6642 wpa_s->conf->ctrl_interface = NULL;
6643 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006644 } else
6645 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6646 iface->driver_param);
6647
6648 if (wpa_s->conf == NULL) {
6649 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6650 return -1;
6651 }
6652
6653 if (iface->ifname == NULL) {
6654 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6655 return -1;
6656 }
6657 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6658 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6659 iface->ifname);
6660 return -1;
6661 }
6662 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006663#ifdef CONFIG_MATCH_IFACE
6664 wpa_s->matched = iface->matched;
6665#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006666
6667 if (iface->bridge_ifname) {
6668 if (os_strlen(iface->bridge_ifname) >=
6669 sizeof(wpa_s->bridge_ifname)) {
6670 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6671 "name '%s'.", iface->bridge_ifname);
6672 return -1;
6673 }
6674 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6675 sizeof(wpa_s->bridge_ifname));
6676 }
6677
6678 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006679 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6680 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006681
6682 /* Initialize driver interface and register driver event handler before
6683 * L2 receive handler so that association events are processed before
6684 * EAPOL-Key packets if both become available for the same select()
6685 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006686 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006687 return -1;
6688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006689 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6690 return -1;
6691
6692 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6693 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6694 NULL);
6695 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6696
6697 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6698 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6699 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6700 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6701 "dot11RSNAConfigPMKLifetime");
6702 return -1;
6703 }
6704
6705 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6706 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6707 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6708 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6709 "dot11RSNAConfigPMKReauthThreshold");
6710 return -1;
6711 }
6712
6713 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6714 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6715 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6716 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6717 "dot11RSNAConfigSATimeout");
6718 return -1;
6719 }
6720
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006721 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6722 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006723 &wpa_s->hw.flags,
6724 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006725 if (wpa_s->hw.modes) {
6726 u16 i;
6727
6728 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6729 if (wpa_s->hw.modes[i].vht_capab) {
6730 wpa_s->hw_capab = CAPAB_VHT;
6731 break;
6732 }
6733
6734 if (wpa_s->hw.modes[i].ht_capab &
6735 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6736 wpa_s->hw_capab = CAPAB_HT40;
6737 else if (wpa_s->hw.modes[i].ht_capab &&
6738 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6739 wpa_s->hw_capab = CAPAB_HT;
6740 }
6741 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006742
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006743 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6744 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006745 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006746 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006747 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006748 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006749 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006750 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006751 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006752 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006753 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6754 wpa_s->max_sched_scan_plan_interval =
6755 capa.max_sched_scan_plan_interval;
6756 wpa_s->max_sched_scan_plan_iterations =
6757 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006758 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6759 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006760 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6761 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006762 wpa_s->extended_capa = capa.extended_capa;
6763 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6764 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006765 wpa_s->num_multichan_concurrent =
6766 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006767 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6768
6769 if (capa.mac_addr_rand_scan_supported)
6770 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6771 if (wpa_s->sched_scan_supported &&
6772 capa.mac_addr_rand_sched_scan_supported)
6773 wpa_s->mac_addr_rand_supported |=
6774 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006775
6776 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6777 if (wpa_s->extended_capa &&
6778 wpa_s->extended_capa_len >= 3 &&
6779 wpa_s->extended_capa[2] & 0x40)
6780 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006781 }
6782 if (wpa_s->max_remain_on_chan == 0)
6783 wpa_s->max_remain_on_chan = 1000;
6784
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006785 /*
6786 * Only take p2p_mgmt parameters when P2P Device is supported.
6787 * Doing it here as it determines whether l2_packet_init() will be done
6788 * during wpa_supplicant_driver_init().
6789 */
6790 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6791 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006792
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006793 if (wpa_s->num_multichan_concurrent == 0)
6794 wpa_s->num_multichan_concurrent = 1;
6795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006796 if (wpa_supplicant_driver_init(wpa_s) < 0)
6797 return -1;
6798
6799#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006800 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006801 return -1;
6802#endif /* CONFIG_TDLS */
6803
6804 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6805 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6806 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6807 return -1;
6808 }
6809
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006810#ifdef CONFIG_FST
6811 if (wpa_s->conf->fst_group_id) {
6812 struct fst_iface_cfg cfg;
6813 struct fst_wpa_obj iface_obj;
6814
6815 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6816 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6817 sizeof(cfg.group_id));
6818 cfg.priority = wpa_s->conf->fst_priority;
6819 cfg.llt = wpa_s->conf->fst_llt;
6820
6821 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6822 &iface_obj, &cfg);
6823 if (!wpa_s->fst) {
6824 wpa_msg(wpa_s, MSG_ERROR,
6825 "FST: Cannot attach iface %s to group %s",
6826 wpa_s->ifname, cfg.group_id);
6827 return -1;
6828 }
6829 }
6830#endif /* CONFIG_FST */
6831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006832 if (wpas_wps_init(wpa_s))
6833 return -1;
6834
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006835#ifdef CONFIG_GAS_SERVER
6836 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6837 if (!wpa_s->gas_server) {
6838 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6839 return -1;
6840 }
6841#endif /* CONFIG_GAS_SERVER */
6842
6843#ifdef CONFIG_DPP
6844 if (wpas_dpp_init(wpa_s) < 0)
6845 return -1;
6846#endif /* CONFIG_DPP */
6847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006848 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6849 return -1;
6850 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6851
6852 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6853 if (wpa_s->ctrl_iface == NULL) {
6854 wpa_printf(MSG_ERROR,
6855 "Failed to initialize control interface '%s'.\n"
6856 "You may have another wpa_supplicant process "
6857 "already running or the file was\n"
6858 "left by an unclean termination of wpa_supplicant "
6859 "in which case you will need\n"
6860 "to manually remove this file before starting "
6861 "wpa_supplicant again.\n",
6862 wpa_s->conf->ctrl_interface);
6863 return -1;
6864 }
6865
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006866 wpa_s->gas = gas_query_init(wpa_s);
6867 if (wpa_s->gas == NULL) {
6868 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6869 return -1;
6870 }
6871
Roshan Pius3a1667e2018-07-03 15:17:14 -07006872 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6873 wpa_s->p2p_mgmt) &&
6874 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6876 return -1;
6877 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006878
6879 if (wpa_bss_init(wpa_s) < 0)
6880 return -1;
6881
Paul Stewart092955c2017-02-06 09:13:09 -08006882#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6883#ifdef CONFIG_MESH
6884 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6885#endif /* CONFIG_MESH */
6886#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6887
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006888 /*
6889 * Set Wake-on-WLAN triggers, if configured.
6890 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6891 * have effect anyway when the interface is down).
6892 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006893 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006894 return -1;
6895
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006896#ifdef CONFIG_EAP_PROXY
6897{
6898 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006899 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6900 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006901 if (wpa_s->mnc_len > 0) {
6902 wpa_s->imsi[len] = '\0';
6903 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6904 wpa_s->imsi, wpa_s->mnc_len);
6905 } else {
6906 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6907 }
6908}
6909#endif /* CONFIG_EAP_PROXY */
6910
Dmitry Shmidt04949592012-07-19 12:16:46 -07006911 if (pcsc_reader_init(wpa_s) < 0)
6912 return -1;
6913
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006914 if (wpas_init_ext_pw(wpa_s) < 0)
6915 return -1;
6916
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006917 wpas_rrm_reset(wpa_s);
6918
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006919 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6920
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006921#ifdef CONFIG_HS20
6922 hs20_init(wpa_s);
6923#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006924#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006925 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006926 if ((wpa_s->conf->oce & OCE_STA) &&
6927 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6928 wpa_s->enable_oce = OCE_STA;
6929 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6930 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6931 /* TODO: Need to add STA-CFON support */
6932 wpa_printf(MSG_ERROR,
6933 "OCE STA-CFON feature is not yet supported");
6934 }
6935 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006936 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6937#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006938
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006939 wpa_supplicant_set_default_scan_ies(wpa_s);
6940
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006941 return 0;
6942}
6943
6944
6945static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006946 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006947{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006948 struct wpa_global *global = wpa_s->global;
6949 struct wpa_supplicant *iface, *prev;
6950
Jimmy Chen0e73c002021-08-18 13:21:30 +08006951 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006952 wpas_p2p_group_remove(wpa_s, "*");
6953
6954 iface = global->ifaces;
6955 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006956 if (iface->p2pdev == wpa_s)
6957 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006958 if (iface == wpa_s || iface->parent != wpa_s) {
6959 iface = iface->next;
6960 continue;
6961 }
6962 wpa_printf(MSG_DEBUG,
6963 "Remove remaining child interface %s from parent %s",
6964 iface->ifname, wpa_s->ifname);
6965 prev = iface;
6966 iface = iface->next;
6967 wpa_supplicant_remove_iface(global, prev, terminate);
6968 }
6969
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006970 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006971 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006972 /*
6973 * Don't deauthenticate if WoWLAN is enable and not explicitly
6974 * been configured to disconnect.
6975 */
6976 if (!wpa_drv_get_wowlan(wpa_s) ||
6977 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006978 wpa_supplicant_deauthenticate(
6979 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006980
Hai Shalomfdcde762020-04-02 11:19:20 -07006981 wpa_drv_set_countermeasures(wpa_s, 0);
6982 wpa_clear_keys(wpa_s, NULL);
6983 } else {
6984 wpa_msg(wpa_s, MSG_INFO,
6985 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6986 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006987 }
6988
6989 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006990 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006991
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006992 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006993 radio_remove_interface(wpa_s);
6994
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006995#ifdef CONFIG_FST
6996 if (wpa_s->fst) {
6997 fst_detach(wpa_s->fst);
6998 wpa_s->fst = NULL;
6999 }
7000 if (wpa_s->received_mb_ies) {
7001 wpabuf_free(wpa_s->received_mb_ies);
7002 wpa_s->received_mb_ies = NULL;
7003 }
7004#endif /* CONFIG_FST */
7005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007006 if (wpa_s->drv_priv)
7007 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007008
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007009 if (notify)
7010 wpas_notify_iface_removed(wpa_s);
7011
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007012 if (terminate)
7013 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007014
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007015 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7016 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007017
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007018#ifdef CONFIG_MESH
7019 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007020 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007021 wpa_s->ifmsh = NULL;
7022 }
7023#endif /* CONFIG_MESH */
7024
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007025 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007026 wpa_config_free(wpa_s->conf);
7027 wpa_s->conf = NULL;
7028 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007029
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007030 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007031 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007032
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007033 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007034}
7035
7036
Dmitry Shmidte4663042016-04-04 10:07:49 -07007037#ifdef CONFIG_MATCH_IFACE
7038
7039/**
7040 * wpa_supplicant_match_iface - Match an interface description to a name
7041 * @global: Pointer to global data from wpa_supplicant_init()
7042 * @ifname: Name of the interface to match
7043 * Returns: Pointer to the created interface description or %NULL on failure
7044 */
7045struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7046 const char *ifname)
7047{
7048 int i;
7049 struct wpa_interface *iface, *miface;
7050
7051 for (i = 0; i < global->params.match_iface_count; i++) {
7052 miface = &global->params.match_ifaces[i];
7053 if (!miface->ifname ||
7054 fnmatch(miface->ifname, ifname, 0) == 0) {
7055 iface = os_zalloc(sizeof(*iface));
7056 if (!iface)
7057 return NULL;
7058 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007059 if (!miface->ifname)
7060 iface->matched = WPA_IFACE_MATCHED_NULL;
7061 else
7062 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007063 iface->ifname = ifname;
7064 return iface;
7065 }
7066 }
7067
7068 return NULL;
7069}
7070
7071
7072/**
7073 * wpa_supplicant_match_existing - Match existing interfaces
7074 * @global: Pointer to global data from wpa_supplicant_init()
7075 * Returns: 0 on success, -1 on failure
7076 */
7077static int wpa_supplicant_match_existing(struct wpa_global *global)
7078{
7079 struct if_nameindex *ifi, *ifp;
7080 struct wpa_supplicant *wpa_s;
7081 struct wpa_interface *iface;
7082
7083 ifp = if_nameindex();
7084 if (!ifp) {
7085 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7086 return -1;
7087 }
7088
7089 for (ifi = ifp; ifi->if_name; ifi++) {
7090 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7091 if (wpa_s)
7092 continue;
7093 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7094 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007095 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007096 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007097 }
7098 }
7099
7100 if_freenameindex(ifp);
7101 return 0;
7102}
7103
7104#endif /* CONFIG_MATCH_IFACE */
7105
7106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007107/**
7108 * wpa_supplicant_add_iface - Add a new network interface
7109 * @global: Pointer to global data from wpa_supplicant_init()
7110 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007111 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007112 * Returns: Pointer to the created interface or %NULL on failure
7113 *
7114 * This function is used to add new network interfaces for %wpa_supplicant.
7115 * This can be called before wpa_supplicant_run() to add interfaces before the
7116 * main event loop has been started. In addition, new interfaces can be added
7117 * dynamically while %wpa_supplicant is already running. This could happen,
7118 * e.g., when a hotplug network adapter is inserted.
7119 */
7120struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007121 struct wpa_interface *iface,
7122 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007123{
7124 struct wpa_supplicant *wpa_s;
7125 struct wpa_interface t_iface;
7126 struct wpa_ssid *ssid;
7127
7128 if (global == NULL || iface == NULL)
7129 return NULL;
7130
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007131 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007132 if (wpa_s == NULL)
7133 return NULL;
7134
7135 wpa_s->global = global;
7136
7137 t_iface = *iface;
7138 if (global->params.override_driver) {
7139 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7140 "('%s' -> '%s')",
7141 iface->driver, global->params.override_driver);
7142 t_iface.driver = global->params.override_driver;
7143 }
7144 if (global->params.override_ctrl_interface) {
7145 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7146 "ctrl_interface ('%s' -> '%s')",
7147 iface->ctrl_interface,
7148 global->params.override_ctrl_interface);
7149 t_iface.ctrl_interface =
7150 global->params.override_ctrl_interface;
7151 }
7152 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7153 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7154 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007155 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007156 return NULL;
7157 }
7158
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007159 /* Notify the control interfaces about new iface */
7160 if (wpas_notify_iface_added(wpa_s)) {
7161 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7162 return NULL;
7163 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007164
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007165 /* Notify the control interfaces about new networks for non p2p mgmt
7166 * ifaces. */
7167 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007168 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
7169 wpas_notify_network_added(wpa_s, ssid);
7170 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007171
7172 wpa_s->next = global->ifaces;
7173 global->ifaces = wpa_s;
7174
7175 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007176 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007177
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007178#ifdef CONFIG_P2P
7179 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007180 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007181 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007182 wpas_p2p_add_p2pdev_interface(
7183 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007184 wpa_printf(MSG_INFO,
7185 "P2P: Failed to enable P2P Device interface");
7186 /* Try to continue without. P2P will be disabled. */
7187 }
7188#endif /* CONFIG_P2P */
7189
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007190 return wpa_s;
7191}
7192
7193
7194/**
7195 * wpa_supplicant_remove_iface - Remove a network interface
7196 * @global: Pointer to global data from wpa_supplicant_init()
7197 * @wpa_s: Pointer to the network interface to be removed
7198 * Returns: 0 if interface was removed, -1 if interface was not found
7199 *
7200 * This function can be used to dynamically remove network interfaces from
7201 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7202 * addition, this function is used to remove all remaining interfaces when
7203 * %wpa_supplicant is terminated.
7204 */
7205int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007206 struct wpa_supplicant *wpa_s,
7207 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007208{
7209 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007210#ifdef CONFIG_MESH
7211 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7212 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007213 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007214#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007215
7216 /* Remove interface from the global list of interfaces */
7217 prev = global->ifaces;
7218 if (prev == wpa_s) {
7219 global->ifaces = wpa_s->next;
7220 } else {
7221 while (prev && prev->next != wpa_s)
7222 prev = prev->next;
7223 if (prev == NULL)
7224 return -1;
7225 prev->next = wpa_s->next;
7226 }
7227
7228 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7229
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007230#ifdef CONFIG_MESH
7231 if (mesh_if_created) {
7232 ifname = os_strdup(wpa_s->ifname);
7233 if (ifname == NULL) {
7234 wpa_dbg(wpa_s, MSG_ERROR,
7235 "mesh: Failed to malloc ifname");
7236 return -1;
7237 }
7238 }
7239#endif /* CONFIG_MESH */
7240
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007241 if (global->p2p_group_formation == wpa_s)
7242 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007243 if (global->p2p_invite_group == wpa_s)
7244 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007245 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007246
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007247#ifdef CONFIG_MESH
7248 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007249 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007250 os_free(ifname);
7251 }
7252#endif /* CONFIG_MESH */
7253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007254 return 0;
7255}
7256
7257
7258/**
7259 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7260 * @wpa_s: Pointer to the network interface
7261 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7262 */
7263const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7264{
7265 const char *eapol_method;
7266
7267 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7268 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7269 return "NO-EAP";
7270 }
7271
7272 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7273 if (eapol_method == NULL)
7274 return "UNKNOWN-EAP";
7275
7276 return eapol_method;
7277}
7278
7279
7280/**
7281 * wpa_supplicant_get_iface - Get a new network interface
7282 * @global: Pointer to global data from wpa_supplicant_init()
7283 * @ifname: Interface name
7284 * Returns: Pointer to the interface or %NULL if not found
7285 */
7286struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7287 const char *ifname)
7288{
7289 struct wpa_supplicant *wpa_s;
7290
7291 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7292 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7293 return wpa_s;
7294 }
7295 return NULL;
7296}
7297
7298
7299#ifndef CONFIG_NO_WPA_MSG
7300static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7301{
7302 struct wpa_supplicant *wpa_s = ctx;
7303 if (wpa_s == NULL)
7304 return NULL;
7305 return wpa_s->ifname;
7306}
7307#endif /* CONFIG_NO_WPA_MSG */
7308
7309
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007310#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7311#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7312#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7313
7314/* Periodic cleanup tasks */
7315static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7316{
7317 struct wpa_global *global = eloop_ctx;
7318 struct wpa_supplicant *wpa_s;
7319
7320 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7321 wpas_periodic, global, NULL);
7322
7323#ifdef CONFIG_P2P
7324 if (global->p2p)
7325 p2p_expire_peers(global->p2p);
7326#endif /* CONFIG_P2P */
7327
7328 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7329 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7330#ifdef CONFIG_AP
7331 ap_periodic(wpa_s);
7332#endif /* CONFIG_AP */
7333 }
7334}
7335
7336
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007337/**
7338 * wpa_supplicant_init - Initialize %wpa_supplicant
7339 * @params: Parameters for %wpa_supplicant
7340 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7341 *
7342 * This function is used to initialize %wpa_supplicant. After successful
7343 * initialization, the returned data pointer can be used to add and remove
7344 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7345 */
7346struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7347{
7348 struct wpa_global *global;
7349 int ret, i;
7350
7351 if (params == NULL)
7352 return NULL;
7353
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007354#ifdef CONFIG_DRIVER_NDIS
7355 {
7356 void driver_ndis_init_ops(void);
7357 driver_ndis_init_ops();
7358 }
7359#endif /* CONFIG_DRIVER_NDIS */
7360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007361#ifndef CONFIG_NO_WPA_MSG
7362 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7363#endif /* CONFIG_NO_WPA_MSG */
7364
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007365 if (params->wpa_debug_file_path)
7366 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007367 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007368 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007369 if (params->wpa_debug_syslog)
7370 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007371 if (params->wpa_debug_tracing) {
7372 ret = wpa_debug_open_linux_tracing();
7373 if (ret) {
7374 wpa_printf(MSG_ERROR,
7375 "Failed to enable trace logging");
7376 return NULL;
7377 }
7378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007379
7380 ret = eap_register_methods();
7381 if (ret) {
7382 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7383 if (ret == -2)
7384 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7385 "the same EAP type.");
7386 return NULL;
7387 }
7388
7389 global = os_zalloc(sizeof(*global));
7390 if (global == NULL)
7391 return NULL;
7392 dl_list_init(&global->p2p_srv_bonjour);
7393 dl_list_init(&global->p2p_srv_upnp);
7394 global->params.daemonize = params->daemonize;
7395 global->params.wait_for_monitor = params->wait_for_monitor;
7396 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7397 if (params->pid_file)
7398 global->params.pid_file = os_strdup(params->pid_file);
7399 if (params->ctrl_interface)
7400 global->params.ctrl_interface =
7401 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007402 if (params->ctrl_interface_group)
7403 global->params.ctrl_interface_group =
7404 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007405 if (params->override_driver)
7406 global->params.override_driver =
7407 os_strdup(params->override_driver);
7408 if (params->override_ctrl_interface)
7409 global->params.override_ctrl_interface =
7410 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007411#ifdef CONFIG_MATCH_IFACE
7412 global->params.match_iface_count = params->match_iface_count;
7413 if (params->match_iface_count) {
7414 global->params.match_ifaces =
7415 os_calloc(params->match_iface_count,
7416 sizeof(struct wpa_interface));
7417 os_memcpy(global->params.match_ifaces,
7418 params->match_ifaces,
7419 params->match_iface_count *
7420 sizeof(struct wpa_interface));
7421 }
7422#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007423#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007424 if (params->conf_p2p_dev)
7425 global->params.conf_p2p_dev =
7426 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007427#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428 wpa_debug_level = global->params.wpa_debug_level =
7429 params->wpa_debug_level;
7430 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7431 params->wpa_debug_show_keys;
7432 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7433 params->wpa_debug_timestamp;
7434
Hai Shalomfdcde762020-04-02 11:19:20 -07007435 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007436
7437 if (eloop_init()) {
7438 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7439 wpa_supplicant_deinit(global);
7440 return NULL;
7441 }
7442
Jouni Malinen75ecf522011-06-27 15:19:46 -07007443 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007444
7445 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7446 if (global->ctrl_iface == NULL) {
7447 wpa_supplicant_deinit(global);
7448 return NULL;
7449 }
7450
7451 if (wpas_notify_supplicant_initialized(global)) {
7452 wpa_supplicant_deinit(global);
7453 return NULL;
7454 }
7455
7456 for (i = 0; wpa_drivers[i]; i++)
7457 global->drv_count++;
7458 if (global->drv_count == 0) {
7459 wpa_printf(MSG_ERROR, "No drivers enabled");
7460 wpa_supplicant_deinit(global);
7461 return NULL;
7462 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007463 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007464 if (global->drv_priv == NULL) {
7465 wpa_supplicant_deinit(global);
7466 return NULL;
7467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007468
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007469#ifdef CONFIG_WIFI_DISPLAY
7470 if (wifi_display_init(global) < 0) {
7471 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7472 wpa_supplicant_deinit(global);
7473 return NULL;
7474 }
7475#endif /* CONFIG_WIFI_DISPLAY */
7476
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007477 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7478 wpas_periodic, global, NULL);
7479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007480 return global;
7481}
7482
7483
7484/**
7485 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7486 * @global: Pointer to global data from wpa_supplicant_init()
7487 * Returns: 0 after successful event loop run, -1 on failure
7488 *
7489 * This function starts the main event loop and continues running as long as
7490 * there are any remaining events. In most cases, this function is running as
7491 * long as the %wpa_supplicant process in still in use.
7492 */
7493int wpa_supplicant_run(struct wpa_global *global)
7494{
7495 struct wpa_supplicant *wpa_s;
7496
7497 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007498 (wpa_supplicant_daemon(global->params.pid_file) ||
7499 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007500 return -1;
7501
Dmitry Shmidte4663042016-04-04 10:07:49 -07007502#ifdef CONFIG_MATCH_IFACE
7503 if (wpa_supplicant_match_existing(global))
7504 return -1;
7505#endif
7506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007507 if (global->params.wait_for_monitor) {
7508 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007509 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007510 wpa_supplicant_ctrl_iface_wait(
7511 wpa_s->ctrl_iface);
7512 }
7513
7514 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7515 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7516
7517 eloop_run();
7518
7519 return 0;
7520}
7521
7522
7523/**
7524 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7525 * @global: Pointer to global data from wpa_supplicant_init()
7526 *
7527 * This function is called to deinitialize %wpa_supplicant and to free all
7528 * allocated resources. Remaining network interfaces will also be removed.
7529 */
7530void wpa_supplicant_deinit(struct wpa_global *global)
7531{
7532 int i;
7533
7534 if (global == NULL)
7535 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007536
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007537 eloop_cancel_timeout(wpas_periodic, global, NULL);
7538
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007539#ifdef CONFIG_WIFI_DISPLAY
7540 wifi_display_deinit(global);
7541#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007542
7543 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007544 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007545
7546 if (global->ctrl_iface)
7547 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7548
7549 wpas_notify_supplicant_deinitialized(global);
7550
7551 eap_peer_unregister_methods();
7552#ifdef CONFIG_AP
7553 eap_server_unregister_methods();
7554#endif /* CONFIG_AP */
7555
7556 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7557 if (!global->drv_priv[i])
7558 continue;
7559 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7560 }
7561 os_free(global->drv_priv);
7562
7563 random_deinit();
7564
7565 eloop_destroy();
7566
7567 if (global->params.pid_file) {
7568 os_daemonize_terminate(global->params.pid_file);
7569 os_free(global->params.pid_file);
7570 }
7571 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007572 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007573 os_free(global->params.override_driver);
7574 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007575#ifdef CONFIG_MATCH_IFACE
7576 os_free(global->params.match_ifaces);
7577#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007578#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007579 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007580#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007581
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007582 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007583 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007584 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007585
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007586 os_free(global);
7587 wpa_debug_close_syslog();
7588 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007589 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007590}
7591
7592
7593void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7594{
7595 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7596 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7597 char country[3];
7598 country[0] = wpa_s->conf->country[0];
7599 country[1] = wpa_s->conf->country[1];
7600 country[2] = '\0';
7601 if (wpa_drv_set_country(wpa_s, country) < 0) {
7602 wpa_printf(MSG_ERROR, "Failed to set country code "
7603 "'%s'", country);
7604 }
7605 }
7606
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007607 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7608 wpas_init_ext_pw(wpa_s);
7609
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007610 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7611 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7612
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007613 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7614 struct wpa_driver_capa capa;
7615 int res = wpa_drv_get_capa(wpa_s, &capa);
7616
7617 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7618 wpa_printf(MSG_ERROR,
7619 "Failed to update wowlan_triggers to '%s'",
7620 wpa_s->conf->wowlan_triggers);
7621 }
7622
Hai Shalom81f62d82019-07-22 12:10:00 -07007623 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7624 wpa_supplicant_set_default_scan_ies(wpa_s);
7625
Hai Shalom899fcc72020-10-19 14:38:18 -07007626#ifdef CONFIG_BGSCAN
7627 /*
7628 * We default to global bgscan parameters only when per-network bgscan
7629 * parameters aren't set. Only bother resetting bgscan parameters if
7630 * this is the case.
7631 */
7632 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7633 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7634 wpa_s->wpa_state == WPA_COMPLETED)
7635 wpa_supplicant_reset_bgscan(wpa_s);
7636#endif /* CONFIG_BGSCAN */
7637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007638#ifdef CONFIG_WPS
7639 wpas_wps_update_config(wpa_s);
7640#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007641 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007642 wpa_s->conf->changed_parameters = 0;
7643}
7644
7645
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007646void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007647{
7648 int i;
7649
7650 for (i = 0; i < *num_freqs; i++) {
7651 if (freqs[i] == freq)
7652 return;
7653 }
7654
7655 freqs[*num_freqs] = freq;
7656 (*num_freqs)++;
7657}
7658
7659
7660static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7661{
7662 struct wpa_bss *bss, *cbss;
7663 const int max_freqs = 10;
7664 int *freqs;
7665 int num_freqs = 0;
7666
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007667 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007668 if (freqs == NULL)
7669 return NULL;
7670
7671 cbss = wpa_s->current_bss;
7672
7673 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7674 if (bss == cbss)
7675 continue;
7676 if (bss->ssid_len == cbss->ssid_len &&
7677 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007678 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007679 add_freq(freqs, &num_freqs, bss->freq);
7680 if (num_freqs == max_freqs)
7681 break;
7682 }
7683 }
7684
7685 if (num_freqs == 0) {
7686 os_free(freqs);
7687 freqs = NULL;
7688 }
7689
7690 return freqs;
7691}
7692
7693
7694void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7695{
7696 int timeout;
7697 int count;
7698 int *freqs = NULL;
7699
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007700 wpas_connect_work_done(wpa_s);
7701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007702 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007703 * Remove possible authentication timeout since the connection failed.
7704 */
7705 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7706
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007707 /*
Hai Shalom60840252021-02-19 19:02:11 -08007708 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007709 * generated based on local request to disconnect.
7710 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007711 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007712 wpa_s->own_disconnect_req = 0;
7713 wpa_dbg(wpa_s, MSG_DEBUG,
7714 "Ignore connection failure due to local request to disconnect");
7715 return;
7716 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007717 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007718 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7719 "indication since interface has been put into "
7720 "disconnected state");
7721 return;
7722 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007723 if (wpa_s->auto_reconnect_disabled) {
7724 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7725 "indication since auto connect is disabled");
7726 return;
7727 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007728
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007729 /*
Hai Shalom60840252021-02-19 19:02:11 -08007730 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007731 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007732 */
Hai Shalom60840252021-02-19 19:02:11 -08007733 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007734 if (count == 1 && wpa_s->current_bss) {
7735 /*
Hai Shalom60840252021-02-19 19:02:11 -08007736 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007737 * another BSS available for the same ESS, we should try that
7738 * next. Otherwise, we may as well try this one once more
7739 * before allowing other, likely worse, ESSes to be considered.
7740 */
7741 freqs = get_bss_freqs_in_ess(wpa_s);
7742 if (freqs) {
7743 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7744 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007745 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007746 /*
7747 * On the next scan, go through only the known channels
7748 * used in this ESS based on previous scans to speed up
7749 * common load balancing use case.
7750 */
7751 os_free(wpa_s->next_scan_freqs);
7752 wpa_s->next_scan_freqs = freqs;
7753 }
7754 }
7755
Hai Shalom899fcc72020-10-19 14:38:18 -07007756 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007757
Hai Shalom899fcc72020-10-19 14:38:18 -07007758 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007759 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7760 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007761 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007762 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007763 /*
7764 * Multiple consecutive connection failures mean that other APs are
7765 * either not available or have already been tried, so we can start
7766 * increasing the delay here to avoid constant scanning.
7767 */
7768 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007769 case 1:
7770 timeout = 100;
7771 break;
7772 case 2:
7773 timeout = 500;
7774 break;
7775 case 3:
7776 timeout = 1000;
7777 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007778 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007779 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007780 break;
7781 default:
7782 timeout = 10000;
7783 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007784 }
7785
Hai Shalom899fcc72020-10-19 14:38:18 -07007786 wpa_dbg(wpa_s, MSG_DEBUG,
7787 "Consecutive connection failures: %d --> request scan in %d ms",
7788 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007789
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007790 /*
7791 * TODO: if more than one possible AP is available in scan results,
7792 * could try the other ones before requesting a new scan.
7793 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007794
7795 /* speed up the connection attempt with normal scan */
7796 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007797 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7798 1000 * (timeout % 1000));
7799}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007800
7801
Hai Shalomce48b4a2018-09-05 11:41:35 -07007802#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007803
7804void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7805{
7806 struct wpa_ssid *ssid = wpa_s->current_ssid;
7807 const u8 *realm, *username, *rrk;
7808 size_t realm_len, username_len, rrk_len;
7809 u16 next_seq_num;
7810
7811 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7812 * Check for ERP keys existing to limit when this can be done since
7813 * the rejection response is not protected and such triggers should
7814 * really not allow internal state to be modified unless required to
7815 * avoid significant issues in functionality. In addition, drop
7816 * externally configure PMKSA entries even without ERP keys since it
7817 * is possible for an external component to add PMKSA entries for FILS
7818 * authentication without restoring previously generated ERP keys.
7819 *
7820 * In this case, this is needed to allow recovery from cases where the
7821 * AP or authentication server has dropped PMKSAs and ERP keys. */
7822 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7823 return;
7824
7825 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7826 &username, &username_len,
7827 &realm, &realm_len, &next_seq_num,
7828 &rrk, &rrk_len) != 0 ||
7829 !realm) {
7830 wpa_dbg(wpa_s, MSG_DEBUG,
7831 "FILS: Drop external PMKSA cache entry");
7832 wpa_sm_aborted_external_cached(wpa_s->wpa);
7833 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7834 return;
7835 }
7836
7837 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7838 wpa_sm_aborted_cached(wpa_s->wpa);
7839 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7840}
7841
7842
Hai Shalomce48b4a2018-09-05 11:41:35 -07007843void fils_connection_failure(struct wpa_supplicant *wpa_s)
7844{
7845 struct wpa_ssid *ssid = wpa_s->current_ssid;
7846 const u8 *realm, *username, *rrk;
7847 size_t realm_len, username_len, rrk_len;
7848 u16 next_seq_num;
7849
7850 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7851 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7852 &username, &username_len,
7853 &realm, &realm_len, &next_seq_num,
7854 &rrk, &rrk_len) != 0 ||
7855 !realm)
7856 return;
7857
7858 wpa_hexdump_ascii(MSG_DEBUG,
7859 "FILS: Store last connection failure realm",
7860 realm, realm_len);
7861 os_free(wpa_s->last_con_fail_realm);
7862 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7863 if (wpa_s->last_con_fail_realm) {
7864 wpa_s->last_con_fail_realm_len = realm_len;
7865 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7866 }
7867}
7868#endif /* CONFIG_FILS */
7869
7870
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007871int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7872{
7873 return wpa_s->conf->ap_scan == 2 ||
7874 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7875}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007876
Dmitry Shmidt04949592012-07-19 12:16:46 -07007877
Gabriel Biren57ededa2021-09-03 16:08:50 +00007878#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007879int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7880 struct wpa_ssid *ssid,
7881 const char *field,
7882 const char *value)
7883{
7884#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007885 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007886
7887 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7888 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7889 (const u8 *) value, os_strlen(value));
7890
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007891 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007892 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007893#else /* IEEE8021X_EAPOL */
7894 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7895 return -1;
7896#endif /* IEEE8021X_EAPOL */
7897}
7898
7899int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7900 struct wpa_ssid *ssid,
7901 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007902 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007903{
7904#ifdef IEEE8021X_EAPOL
7905 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007906 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007907
7908 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007909 case WPA_CTRL_REQ_EAP_IDENTITY:
7910 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007911 os_free(eap->imsi_identity);
7912 if (value == NULL)
7913 return -1;
7914 identity = os_strchr(value, ':');
7915 if (identity == NULL) {
7916 /* plain identity */
7917 eap->identity = (u8 *)os_strdup(value);
7918 eap->identity_len = os_strlen(value);
7919 } else {
7920 /* have both plain identity and encrypted identity */
7921 imsi_identity = value;
7922 *identity++ = '\0';
7923 /* plain identity */
7924 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7925 eap->imsi_identity_len = strlen(imsi_identity);
7926 /* encrypted identity */
7927 eap->identity = (u8 *)dup_binstr(identity,
7928 value_len - strlen(imsi_identity) - 1);
7929 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7930 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007931 eap->pending_req_identity = 0;
7932 if (ssid == wpa_s->current_ssid)
7933 wpa_s->reassociate = 1;
7934 break;
7935 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007936 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007937 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007938 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007939 eap->pending_req_password = 0;
7940 if (ssid == wpa_s->current_ssid)
7941 wpa_s->reassociate = 1;
7942 break;
7943 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007944 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007945 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007946 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007947 eap->pending_req_new_password = 0;
7948 if (ssid == wpa_s->current_ssid)
7949 wpa_s->reassociate = 1;
7950 break;
7951 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007952 str_clear_free(eap->cert.pin);
7953 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007954 eap->pending_req_pin = 0;
7955 if (ssid == wpa_s->current_ssid)
7956 wpa_s->reassociate = 1;
7957 break;
7958 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007959 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007960 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007961 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007962 os_free(eap->pending_req_otp);
7963 eap->pending_req_otp = NULL;
7964 eap->pending_req_otp_len = 0;
7965 break;
7966 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007967 str_clear_free(eap->cert.private_key_passwd);
7968 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007969 eap->pending_req_passphrase = 0;
7970 if (ssid == wpa_s->current_ssid)
7971 wpa_s->reassociate = 1;
7972 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007973 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007974 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007975 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007976 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007977 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007978 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7979 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7980 return -1;
7981 ssid->mem_only_psk = 1;
7982 if (ssid->passphrase)
7983 wpa_config_update_psk(ssid);
7984 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7985 wpa_supplicant_req_scan(wpa_s, 0, 0);
7986 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007987 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7988 if (eap->pending_ext_cert_check != PENDING_CHECK)
7989 return -1;
7990 if (os_strcmp(value, "good") == 0)
7991 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7992 else if (os_strcmp(value, "bad") == 0)
7993 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7994 else
7995 return -1;
7996 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007997 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007998 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007999 return -1;
8000 }
8001
8002 return 0;
8003#else /* IEEE8021X_EAPOL */
8004 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8005 return -1;
8006#endif /* IEEE8021X_EAPOL */
8007}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008008#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008009
8010
8011int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8012{
Hai Shalomfdcde762020-04-02 11:19:20 -07008013#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008014 int i;
8015 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008016#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008017
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008018 if (wpa_s->p2p_mgmt)
8019 return 1; /* no normal network profiles on p2p_mgmt interface */
8020
Dmitry Shmidt04949592012-07-19 12:16:46 -07008021 if (ssid == NULL)
8022 return 1;
8023
8024 if (ssid->disabled)
8025 return 1;
8026
Hai Shalomfdcde762020-04-02 11:19:20 -07008027#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008028 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008029 drv_enc = wpa_s->drv_enc;
8030 else
8031 drv_enc = (unsigned int) -1;
8032
8033 for (i = 0; i < NUM_WEP_KEYS; i++) {
8034 size_t len = ssid->wep_key_len[i];
8035 if (len == 0)
8036 continue;
8037 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8038 continue;
8039 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8040 continue;
8041 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8042 continue;
8043 return 1; /* invalid WEP key */
8044 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008045#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008046
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008047 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008048 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008049 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008050 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008051 return 1;
8052
Dmitry Shmidt04949592012-07-19 12:16:46 -07008053 return 0;
8054}
8055
8056
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008057int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8058{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008059 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8060 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8061 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8062 /*
8063 * Driver does not support BIP -- ignore pmf=1 default
8064 * since the connection with PMF would fail and the
8065 * configuration does not require PMF to be enabled.
8066 */
8067 return NO_MGMT_FRAME_PROTECTION;
8068 }
8069
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008070 if (ssid &&
8071 (ssid->key_mgmt &
8072 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8073 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8074 /*
8075 * Do not use the default PMF value for non-RSN networks
8076 * since PMF is available only with RSN and pmf=2
8077 * configuration would otherwise prevent connections to
8078 * all open networks.
8079 */
8080 return NO_MGMT_FRAME_PROTECTION;
8081 }
8082
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008083 return wpa_s->conf->pmf;
8084 }
8085
8086 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008087}
8088
8089
Hai Shalomc1a21442022-02-04 13:43:00 -08008090int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8091{
8092 if (wpa_s->current_ssid == NULL ||
8093 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8094 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8095 return 0;
8096 return wpa_sm_pmf_enabled(wpa_s->wpa);
8097}
8098
8099
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008100int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008101{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008102 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008103 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008104 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008105 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008106 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008107}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008108
8109
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008110void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008111{
8112 struct wpa_ssid *ssid = wpa_s->current_ssid;
8113 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008114 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008115
8116 if (ssid == NULL) {
8117 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8118 "SSID block");
8119 return;
8120 }
8121
8122 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8123 return;
8124
8125 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008126
8127#ifdef CONFIG_P2P
8128 if (ssid->p2p_group &&
8129 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8130 /*
8131 * Skip the wait time since there is a short timeout on the
8132 * connection to a P2P group.
8133 */
8134 return;
8135 }
8136#endif /* CONFIG_P2P */
8137
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008138 if (ssid->auth_failures > 50)
8139 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008140 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008141 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008142 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008143 dur = 90;
8144 else if (ssid->auth_failures > 3)
8145 dur = 60;
8146 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008147 dur = 30;
8148 else if (ssid->auth_failures > 1)
8149 dur = 20;
8150 else
8151 dur = 10;
8152
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008153 if (ssid->auth_failures > 1 &&
8154 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8155 dur += os_random() % (ssid->auth_failures * 10);
8156
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008157 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008158 if (now.sec + dur <= ssid->disabled_until.sec)
8159 return;
8160
8161 ssid->disabled_until.sec = now.sec + dur;
8162
8163 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008164 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008165 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008166 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008167
8168 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8169 int msg_len = snprintf(NULL, 0, format_str,
8170 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8171 ssid->auth_failures, dur, reason) + 1;
8172 char *msg = os_malloc(msg_len);
8173 snprintf(msg, msg_len, format_str,
8174 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8175 ssid->auth_failures, dur, reason);
8176 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8177 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008178}
8179
8180
8181void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8182 struct wpa_ssid *ssid, int clear_failures)
8183{
8184 if (ssid == NULL)
8185 return;
8186
8187 if (ssid->disabled_until.sec) {
8188 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8189 "id=%d ssid=\"%s\"",
8190 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8191 }
8192 ssid->disabled_until.sec = 0;
8193 ssid->disabled_until.usec = 0;
8194 if (clear_failures)
8195 ssid->auth_failures = 0;
8196}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008197
8198
8199int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8200{
8201 size_t i;
8202
8203 if (wpa_s->disallow_aps_bssid == NULL)
8204 return 0;
8205
8206 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8207 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8208 bssid, ETH_ALEN) == 0)
8209 return 1;
8210 }
8211
8212 return 0;
8213}
8214
8215
8216int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8217 size_t ssid_len)
8218{
8219 size_t i;
8220
8221 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8222 return 0;
8223
8224 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8225 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8226 if (ssid_len == s->ssid_len &&
8227 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8228 return 1;
8229 }
8230
8231 return 0;
8232}
8233
8234
8235/**
8236 * wpas_request_connection - Request a new connection
8237 * @wpa_s: Pointer to the network interface
8238 *
8239 * This function is used to request a new connection to be found. It will mark
8240 * the interface to allow reassociation and request a new scan to find a
8241 * suitable network to connect to.
8242 */
8243void wpas_request_connection(struct wpa_supplicant *wpa_s)
8244{
8245 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008246 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008247 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008248 wpa_s->disconnected = 0;
8249 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008250 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008251
8252 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8253 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008254 else
8255 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008256}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008257
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008258
Roshan Pius02242d72016-08-09 15:31:48 -07008259/**
8260 * wpas_request_disconnection - Request disconnection
8261 * @wpa_s: Pointer to the network interface
8262 *
8263 * This function is used to request disconnection from the currently connected
8264 * network. This will stop any ongoing scans and initiate deauthentication.
8265 */
8266void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8267{
8268#ifdef CONFIG_SME
8269 wpa_s->sme.prev_bssid_set = 0;
8270#endif /* CONFIG_SME */
8271 wpa_s->reassociate = 0;
8272 wpa_s->disconnected = 1;
8273 wpa_supplicant_cancel_sched_scan(wpa_s);
8274 wpa_supplicant_cancel_scan(wpa_s);
8275 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8276 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008277 radio_remove_works(wpa_s, "connect", 0);
8278 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008279 wpa_s->roam_in_progress = false;
8280#ifdef CONFIG_WNM
8281 wpa_s->bss_trans_mgmt_in_progress = false;
8282#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008283}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008284
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008285
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008286void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8287 struct wpa_used_freq_data *freqs_data,
8288 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008289{
8290 unsigned int i;
8291
8292 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8293 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008294 for (i = 0; i < len; i++) {
8295 struct wpa_used_freq_data *cur = &freqs_data[i];
8296 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8297 i, cur->freq, cur->flags);
8298 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008299}
8300
8301
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008302/*
8303 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008304 * are using the same radio as the current interface, and in addition, get
8305 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008306 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008307int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8308 struct wpa_used_freq_data *freqs_data,
8309 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008310{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008311 struct wpa_supplicant *ifs;
8312 u8 bssid[ETH_ALEN];
8313 int freq;
8314 unsigned int idx = 0, i;
8315
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008316 wpa_dbg(wpa_s, MSG_DEBUG,
8317 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008318 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008319
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008320 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8321 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008322 if (idx == len)
8323 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008324
8325 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8326 continue;
8327
8328 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008329 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8330 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008331 freq = ifs->current_ssid->frequency;
8332 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8333 freq = ifs->assoc_freq;
8334 else
8335 continue;
8336
8337 /* Hold only distinct freqs */
8338 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008339 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008340 break;
8341
8342 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008343 freqs_data[idx++].freq = freq;
8344
8345 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008346 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008347 WPA_FREQ_USED_BY_P2P_CLIENT :
8348 WPA_FREQ_USED_BY_INFRA_STATION;
8349 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008350 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008351
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008352 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008353 return idx;
8354}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008355
8356
8357/*
8358 * Find the operating frequencies of any of the virtual interfaces that
8359 * are using the same radio as the current interface.
8360 */
8361int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8362 int *freq_array, unsigned int len)
8363{
8364 struct wpa_used_freq_data *freqs_data;
8365 int num, i;
8366
8367 os_memset(freq_array, 0, sizeof(int) * len);
8368
8369 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8370 if (!freqs_data)
8371 return -1;
8372
8373 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8374 for (i = 0; i < num; i++)
8375 freq_array[i] = freqs_data[i].freq;
8376
8377 os_free(freqs_data);
8378
8379 return num;
8380}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008381
8382
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008383struct wpa_supplicant *
8384wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8385{
8386 switch (frame) {
8387#ifdef CONFIG_P2P
8388 case VENDOR_ELEM_PROBE_REQ_P2P:
8389 case VENDOR_ELEM_PROBE_RESP_P2P:
8390 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8391 case VENDOR_ELEM_BEACON_P2P_GO:
8392 case VENDOR_ELEM_P2P_PD_REQ:
8393 case VENDOR_ELEM_P2P_PD_RESP:
8394 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8395 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8396 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8397 case VENDOR_ELEM_P2P_INV_REQ:
8398 case VENDOR_ELEM_P2P_INV_RESP:
8399 case VENDOR_ELEM_P2P_ASSOC_REQ:
8400 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008401 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008402#endif /* CONFIG_P2P */
8403 default:
8404 return wpa_s;
8405 }
8406}
8407
8408
8409void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8410{
8411 unsigned int i;
8412 char buf[30];
8413
8414 wpa_printf(MSG_DEBUG, "Update vendor elements");
8415
8416 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8417 if (wpa_s->vendor_elem[i]) {
8418 int res;
8419
8420 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8421 if (!os_snprintf_error(sizeof(buf), res)) {
8422 wpa_hexdump_buf(MSG_DEBUG, buf,
8423 wpa_s->vendor_elem[i]);
8424 }
8425 }
8426 }
8427
8428#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008429 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008430 wpa_s->global->p2p &&
8431 !wpa_s->global->p2p_disabled)
8432 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8433#endif /* CONFIG_P2P */
8434}
8435
8436
8437int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8438 const u8 *elem, size_t len)
8439{
8440 u8 *ie, *end;
8441
8442 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8443 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8444
8445 for (; ie + 1 < end; ie += 2 + ie[1]) {
8446 if (ie + len > end)
8447 break;
8448 if (os_memcmp(ie, elem, len) != 0)
8449 continue;
8450
8451 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8452 wpabuf_free(wpa_s->vendor_elem[frame]);
8453 wpa_s->vendor_elem[frame] = NULL;
8454 } else {
8455 os_memmove(ie, ie + len, end - (ie + len));
8456 wpa_s->vendor_elem[frame]->used -= len;
8457 }
8458 wpas_vendor_elem_update(wpa_s);
8459 return 0;
8460 }
8461
8462 return -1;
8463}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008464
8465
8466struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008467 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008468 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008469{
8470 u16 i;
8471
Hai Shalomc1a21442022-02-04 13:43:00 -08008472 if (!modes)
8473 return NULL;
8474
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008475 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008476 if (modes[i].mode != mode ||
8477 !modes[i].num_channels || !modes[i].channels)
8478 continue;
8479 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8480 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008481 return &modes[i];
8482 }
8483
8484 return NULL;
8485}
8486
8487
Hai Shalomc1a21442022-02-04 13:43:00 -08008488struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8489 u16 num_modes, int freq)
8490{
8491 int i, j;
8492
8493 for (i = 0; i < num_modes; i++) {
8494 for (j = 0; j < modes[i].num_channels; j++) {
8495 if (freq == modes[i].channels[j].freq)
8496 return &modes[i];
8497 }
8498 }
8499
8500 return NULL;
8501}
8502
8503
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008504static struct
8505wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8506 const u8 *bssid)
8507{
8508 struct wpa_bss_tmp_disallowed *bss;
8509
8510 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8511 struct wpa_bss_tmp_disallowed, list) {
8512 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8513 return bss;
8514 }
8515
8516 return NULL;
8517}
8518
8519
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008520static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8521{
8522 struct wpa_bss_tmp_disallowed *tmp;
8523 unsigned int num_bssid = 0;
8524 u8 *bssids;
8525 int ret;
8526
8527 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8528 if (!bssids)
8529 return -1;
8530 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8531 struct wpa_bss_tmp_disallowed, list) {
8532 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8533 ETH_ALEN);
8534 num_bssid++;
8535 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008536 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008537 os_free(bssids);
8538 return ret;
8539}
8540
8541
8542static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8543{
8544 struct wpa_supplicant *wpa_s = eloop_ctx;
8545 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8546
8547 /* Make sure the bss is not already freed */
8548 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8549 struct wpa_bss_tmp_disallowed, list) {
8550 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008551 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008552 wpa_set_driver_tmp_disallow_list(wpa_s);
8553 break;
8554 }
8555 }
8556}
8557
8558
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008559void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008560 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008561{
8562 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008563
8564 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8565 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008566 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008567 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008568 }
8569
8570 bss = os_malloc(sizeof(*bss));
8571 if (!bss) {
8572 wpa_printf(MSG_DEBUG,
8573 "Failed to allocate memory for temp disallow BSS");
8574 return;
8575 }
8576
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008577 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8578 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008579 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008580
8581finish:
8582 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008583 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8584 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008585}
8586
8587
Hai Shalom74f70d42019-02-11 14:42:39 -08008588int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8589 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008590{
Hai Shalom74f70d42019-02-11 14:42:39 -08008591 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008592
8593 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8594 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008595 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8596 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008597 break;
8598 }
8599 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008600 if (!disallowed)
8601 return 0;
8602
8603 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008604 bss->level > disallowed->rssi_threshold) {
8605 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8606 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008607 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008608 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008609
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008610 return 1;
8611}
Hai Shalom81f62d82019-07-22 12:10:00 -07008612
8613
8614int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8615 unsigned int type, const u8 *addr,
8616 const u8 *mask)
8617{
8618 if ((addr && !mask) || (!addr && mask)) {
8619 wpa_printf(MSG_INFO,
8620 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8621 return -1;
8622 }
8623
8624 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8625 wpa_printf(MSG_INFO,
8626 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8627 return -1;
8628 }
8629
8630 if (type & MAC_ADDR_RAND_SCAN) {
8631 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8632 addr, mask))
8633 return -1;
8634 }
8635
8636 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8637 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8638 addr, mask))
8639 return -1;
8640
8641 if (wpa_s->sched_scanning && !wpa_s->pno)
8642 wpas_scan_restart_sched_scan(wpa_s);
8643 }
8644
8645 if (type & MAC_ADDR_RAND_PNO) {
8646 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8647 addr, mask))
8648 return -1;
8649
8650 if (wpa_s->pno) {
8651 wpas_stop_pno(wpa_s);
8652 wpas_start_pno(wpa_s);
8653 }
8654 }
8655
8656 return 0;
8657}
8658
8659
8660int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8661 unsigned int type)
8662{
8663 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8664 if (wpa_s->pno) {
8665 if (type & MAC_ADDR_RAND_PNO) {
8666 wpas_stop_pno(wpa_s);
8667 wpas_start_pno(wpa_s);
8668 }
8669 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8670 wpas_scan_restart_sched_scan(wpa_s);
8671 }
8672
8673 return 0;
8674}
Hai Shalomfdcde762020-04-02 11:19:20 -07008675
8676
8677int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8678 struct wpa_signal_info *si)
8679{
8680 int res;
8681
8682 if (!wpa_s->driver->signal_poll)
8683 return -1;
8684
8685 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8686
8687#ifdef CONFIG_TESTING_OPTIONS
8688 if (res == 0) {
8689 struct driver_signal_override *dso;
8690
8691 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8692 struct driver_signal_override, list) {
8693 if (os_memcmp(wpa_s->bssid, dso->bssid,
8694 ETH_ALEN) != 0)
8695 continue;
8696 wpa_printf(MSG_DEBUG,
8697 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8698 si->current_signal,
8699 dso->si_current_signal,
8700 si->avg_signal,
8701 dso->si_avg_signal,
8702 si->avg_beacon_signal,
8703 dso->si_avg_beacon_signal,
8704 si->current_noise,
8705 dso->si_current_noise);
8706 si->current_signal = dso->si_current_signal;
8707 si->avg_signal = dso->si_avg_signal;
8708 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8709 si->current_noise = dso->si_current_noise;
8710 break;
8711 }
8712 }
8713#endif /* CONFIG_TESTING_OPTIONS */
8714
8715 return res;
8716}
8717
8718
8719struct wpa_scan_results *
8720wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8721{
8722 struct wpa_scan_results *scan_res;
8723#ifdef CONFIG_TESTING_OPTIONS
8724 size_t idx;
8725#endif /* CONFIG_TESTING_OPTIONS */
8726
8727 if (!wpa_s->driver->get_scan_results2)
8728 return NULL;
8729
8730 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8731
8732#ifdef CONFIG_TESTING_OPTIONS
8733 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8734 struct driver_signal_override *dso;
8735 struct wpa_scan_res *res = scan_res->res[idx];
8736
8737 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8738 struct driver_signal_override, list) {
8739 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8740 continue;
8741 wpa_printf(MSG_DEBUG,
8742 "Override driver scan signal level %d->%d for "
8743 MACSTR,
8744 res->level, dso->scan_level,
8745 MAC2STR(res->bssid));
8746 res->flags |= WPA_SCAN_QUAL_INVALID;
8747 if (dso->scan_level < 0)
8748 res->flags |= WPA_SCAN_LEVEL_DBM;
8749 else
8750 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8751 res->level = dso->scan_level;
8752 break;
8753 }
8754 }
8755#endif /* CONFIG_TESTING_OPTIONS */
8756
8757 return scan_res;
8758}