blob: 139907f1dd1ebf757b0ff32e2342bca40a638278 [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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001894 return 0;
1895}
1896
1897
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001898static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1899{
Hai Shalomc1a21442022-02-04 13:43:00 -08001900 bool scs = true, mscs = true;
1901
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001902 *pos = 0x00;
1903
1904 switch (idx) {
1905 case 0: /* Bits 0-7 */
1906 break;
1907 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001908 if (wpa_s->conf->coloc_intf_reporting) {
1909 /* Bit 13 - Collocated Interference Reporting */
1910 *pos |= 0x20;
1911 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001912 break;
1913 case 2: /* Bits 16-23 */
1914#ifdef CONFIG_WNM
1915 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001916 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001917 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001918#endif /* CONFIG_WNM */
1919 break;
1920 case 3: /* Bits 24-31 */
1921#ifdef CONFIG_WNM
1922 *pos |= 0x02; /* Bit 25 - SSID List */
1923#endif /* CONFIG_WNM */
1924#ifdef CONFIG_INTERWORKING
1925 if (wpa_s->conf->interworking)
1926 *pos |= 0x80; /* Bit 31 - Interworking */
1927#endif /* CONFIG_INTERWORKING */
1928 break;
1929 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001930#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001931 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001932 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001933#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001934 break;
1935 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001936#ifdef CONFIG_HS20
1937 if (wpa_s->conf->hs20)
1938 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1939#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001940#ifdef CONFIG_MBO
1941 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1942#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001943 break;
1944 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001945#ifdef CONFIG_TESTING_OPTIONS
1946 if (wpa_s->disable_scs_support)
1947 scs = false;
1948#endif /* CONFIG_TESTING_OPTIONS */
1949 if (scs)
1950 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001951 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001952 case 7: /* Bits 56-63 */
1953 break;
1954 case 8: /* Bits 64-71 */
1955 if (wpa_s->conf->ftm_responder)
1956 *pos |= 0x40; /* Bit 70 - FTM responder */
1957 if (wpa_s->conf->ftm_initiator)
1958 *pos |= 0x80; /* Bit 71 - FTM initiator */
1959 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001960 case 9: /* Bits 72-79 */
1961#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001962 if (!wpa_s->disable_fils)
1963 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001964#endif /* CONFIG_FILS */
1965 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001966 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001967#ifdef CONFIG_TESTING_OPTIONS
1968 if (wpa_s->disable_mscs_support)
1969 mscs = false;
1970#endif /* CONFIG_TESTING_OPTIONS */
1971 if (mscs)
1972 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001973 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001974 }
1975}
1976
1977
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001978int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001979{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001980 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001981 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001982
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001983 if (len < wpa_s->extended_capa_len)
1984 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001985 if (buflen < (size_t) len + 2) {
1986 wpa_printf(MSG_INFO,
1987 "Not enough room for building extended capabilities element");
1988 return -1;
1989 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001990
1991 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001992 *pos++ = len;
1993 for (i = 0; i < len; i++, pos++) {
1994 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001995
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001996 if (i < wpa_s->extended_capa_len) {
1997 *pos &= ~wpa_s->extended_capa_mask[i];
1998 *pos |= wpa_s->extended_capa[i];
1999 }
2000 }
2001
2002 while (len > 0 && buf[1 + len] == 0) {
2003 len--;
2004 buf[1] = len;
2005 }
2006 if (len == 0)
2007 return 0;
2008
2009 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002010}
2011
2012
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002013static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2014 struct wpa_bss *test_bss)
2015{
2016 struct wpa_bss *bss;
2017
2018 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2019 if (bss == test_bss)
2020 return 1;
2021 }
2022
2023 return 0;
2024}
2025
2026
2027static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2028 struct wpa_ssid *test_ssid)
2029{
2030 struct wpa_ssid *ssid;
2031
2032 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2033 if (ssid == test_ssid)
2034 return 1;
2035 }
2036
2037 return 0;
2038}
2039
2040
2041int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2042 struct wpa_ssid *test_ssid)
2043{
2044 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2045 return 0;
2046
2047 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2048}
2049
2050
2051void wpas_connect_work_free(struct wpa_connect_work *cwork)
2052{
2053 if (cwork == NULL)
2054 return;
2055 os_free(cwork);
2056}
2057
2058
2059void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2060{
2061 struct wpa_connect_work *cwork;
2062 struct wpa_radio_work *work = wpa_s->connect_work;
2063
2064 if (!work)
2065 return;
2066
2067 wpa_s->connect_work = NULL;
2068 cwork = work->ctx;
2069 work->ctx = NULL;
2070 wpas_connect_work_free(cwork);
2071 radio_work_done(work);
2072}
2073
2074
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002075int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2076{
2077 struct os_reltime now;
2078 u8 addr[ETH_ALEN];
2079
2080 os_get_reltime(&now);
2081 if (wpa_s->last_mac_addr_style == style &&
2082 wpa_s->last_mac_addr_change.sec != 0 &&
2083 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2084 wpa_s->conf->rand_addr_lifetime)) {
2085 wpa_msg(wpa_s, MSG_DEBUG,
2086 "Previously selected random MAC address has not yet expired");
2087 return 0;
2088 }
2089
2090 switch (style) {
2091 case 1:
2092 if (random_mac_addr(addr) < 0)
2093 return -1;
2094 break;
2095 case 2:
2096 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2097 if (random_mac_addr_keep_oui(addr) < 0)
2098 return -1;
2099 break;
2100 default:
2101 return -1;
2102 }
2103
2104 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2105 wpa_msg(wpa_s, MSG_INFO,
2106 "Failed to set random MAC address");
2107 return -1;
2108 }
2109
2110 os_get_reltime(&wpa_s->last_mac_addr_change);
2111 wpa_s->mac_addr_changed = 1;
2112 wpa_s->last_mac_addr_style = style;
2113
2114 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2115 wpa_msg(wpa_s, MSG_INFO,
2116 "Could not update MAC address information");
2117 return -1;
2118 }
2119
2120 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2121 MAC2STR(addr));
2122
2123 return 0;
2124}
2125
2126
2127int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2128{
2129 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2130 !wpa_s->conf->preassoc_mac_addr)
2131 return 0;
2132
2133 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2134}
2135
2136
Hai Shalomc3565922019-10-28 11:58:20 -07002137static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2138{
2139#ifdef CONFIG_SAE
2140 int *groups = conf->sae_groups;
2141 int default_groups[] = { 19, 20, 21, 0 };
2142 const char *password;
2143
2144 if (!groups || groups[0] <= 0)
2145 groups = default_groups;
2146
2147 password = ssid->sae_password;
2148 if (!password)
2149 password = ssid->passphrase;
2150
Hai Shalom899fcc72020-10-19 14:38:18 -07002151 if (!password ||
2152 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2153 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002154 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002155 /* PT derivation not needed */
2156 sae_deinit_pt(ssid->pt);
2157 ssid->pt = NULL;
2158 return;
2159 }
2160
2161 if (ssid->pt)
2162 return; /* PT already derived */
2163 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2164 (const u8 *) password, os_strlen(password),
2165 ssid->sae_password_id);
2166#endif /* CONFIG_SAE */
2167}
2168
2169
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002170static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2171{
2172#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2173 os_free(wpa_s->sme.sae_rejected_groups);
2174 wpa_s->sme.sae_rejected_groups = NULL;
2175#ifdef CONFIG_TESTING_OPTIONS
2176 if (wpa_s->extra_sae_rejected_groups) {
2177 int i, *groups = wpa_s->extra_sae_rejected_groups;
2178
2179 for (i = 0; groups[i]; i++) {
2180 wpa_printf(MSG_DEBUG,
2181 "TESTING: Indicate rejection of an extra SAE group %d",
2182 groups[i]);
2183 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2184 groups[i]);
2185 }
2186 }
2187#endif /* CONFIG_TESTING_OPTIONS */
2188#endif /* CONFIG_SAE && CONFIG_SME */
2189}
2190
2191
Hai Shalom60840252021-02-19 19:02:11 -08002192int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2193{
2194 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2195 wpa_msg(wpa_s, MSG_INFO,
2196 "Could not restore permanent MAC address");
2197 return -1;
2198 }
2199 wpa_s->mac_addr_changed = 0;
2200 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2201 wpa_msg(wpa_s, MSG_INFO,
2202 "Could not update MAC address information");
2203 return -1;
2204 }
2205 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2206 return 0;
2207}
2208
2209
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002210static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2211
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212/**
2213 * wpa_supplicant_associate - Request association
2214 * @wpa_s: Pointer to wpa_supplicant data
2215 * @bss: Scan results for the selected BSS, or %NULL if not available
2216 * @ssid: Configuration data for the selected network
2217 *
2218 * This function is used to request %wpa_supplicant to associate with a BSS.
2219 */
2220void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2221 struct wpa_bss *bss, struct wpa_ssid *ssid)
2222{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002223 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002224 int rand_style;
2225
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002226 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002227 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002228
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002229 /*
2230 * If we are starting a new connection, any previously pending EAPOL
2231 * RX cannot be valid anymore.
2232 */
2233 wpabuf_free(wpa_s->pending_eapol_rx);
2234 wpa_s->pending_eapol_rx = NULL;
2235
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002236 if (ssid->mac_addr == -1)
2237 rand_style = wpa_s->conf->mac_addr;
2238 else
2239 rand_style = ssid->mac_addr;
2240
Hai Shalomfdcde762020-04-02 11:19:20 -07002241 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002242 wmm_ac_clear_saved_tspecs(wpa_s);
2243 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002244 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002245#ifdef CONFIG_TESTING_OPTIONS
2246 wpa_s->testing_resend_assoc = 0;
2247#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002248
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002249 if (wpa_s->last_ssid == ssid) {
2250 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002251 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002252 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2253 wmm_ac_save_tspecs(wpa_s);
2254 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002255 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2256 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002257 }
Hai Shalomc3565922019-10-28 11:58:20 -07002258 } else {
2259#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002260 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002261#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002262 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002263#ifdef CONFIG_SAE
2264 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2265#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002266
2267 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002268 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2269 return;
2270 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002271 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002272 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002273 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002274 }
2275 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276
2277#ifdef CONFIG_IBSS_RSN
2278 ibss_rsn_deinit(wpa_s->ibss_rsn);
2279 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002280#else /* CONFIG_IBSS_RSN */
2281 if (ssid->mode == WPAS_MODE_IBSS &&
2282 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2283 wpa_msg(wpa_s, MSG_INFO,
2284 "IBSS RSN not supported in the build");
2285 return;
2286 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002287#endif /* CONFIG_IBSS_RSN */
2288
2289 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2290 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2291#ifdef CONFIG_AP
2292 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2293 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2294 "mode");
2295 return;
2296 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002297 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2298 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002299 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2300 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002301 return;
2302 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303 wpa_s->current_bss = bss;
2304#else /* CONFIG_AP */
2305 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2306 "the build");
2307#endif /* CONFIG_AP */
2308 return;
2309 }
2310
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002311 if (ssid->mode == WPAS_MODE_MESH) {
2312#ifdef CONFIG_MESH
2313 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2314 wpa_msg(wpa_s, MSG_INFO,
2315 "Driver does not support mesh mode");
2316 return;
2317 }
2318 if (bss)
2319 ssid->frequency = bss->freq;
2320 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2321 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2322 return;
2323 }
2324 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002325#else /* CONFIG_MESH */
2326 wpa_msg(wpa_s, MSG_ERROR,
2327 "mesh mode support not included in the build");
2328#endif /* CONFIG_MESH */
2329 return;
2330 }
2331
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002332 /*
2333 * Set WPA state machine configuration to match the selected network now
2334 * so that the information is available before wpas_start_assoc_cb()
2335 * gets called. This is needed at least for RSN pre-authentication where
2336 * candidate APs are added to a list based on scan result processing
2337 * before completion of the first association.
2338 */
2339 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2340
2341#ifdef CONFIG_DPP
2342 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2343 return;
2344#endif /* CONFIG_DPP */
2345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346#ifdef CONFIG_TDLS
2347 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002348 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349#endif /* CONFIG_TDLS */
2350
Hai Shalomc3565922019-10-28 11:58:20 -07002351#ifdef CONFIG_MBO
2352 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2353#endif /* CONFIG_MBO */
2354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002355 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002356 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 sme_authenticate(wpa_s, bss, ssid);
2358 return;
2359 }
2360
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002361 if (wpa_s->connect_work) {
2362 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2363 return;
2364 }
2365
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002366 if (radio_work_pending(wpa_s, "connect")) {
2367 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2368 return;
2369 }
2370
Dmitry Shmidt29333592017-01-09 12:27:11 -08002371#ifdef CONFIG_SME
2372 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2373 /* Clear possibly set auth_alg, if any, from last attempt. */
2374 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2375 }
2376#endif /* CONFIG_SME */
2377
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002378 wpas_abort_ongoing_scan(wpa_s);
2379
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002380 cwork = os_zalloc(sizeof(*cwork));
2381 if (cwork == NULL)
2382 return;
2383
2384 cwork->bss = bss;
2385 cwork->ssid = ssid;
2386
2387 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2388 wpas_start_assoc_cb, cwork) < 0) {
2389 os_free(cwork);
2390 }
2391}
2392
2393
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002394static int bss_is_ibss(struct wpa_bss *bss)
2395{
2396 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2397 IEEE80211_CAP_IBSS;
2398}
2399
2400
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002401static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2402 const struct wpa_ssid *ssid)
2403{
2404 enum hostapd_hw_mode hw_mode;
2405 struct hostapd_hw_modes *mode = NULL;
2406 u8 channel;
2407 int i;
2408
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002409 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2410 if (hw_mode == NUM_HOSTAPD_MODES)
2411 return 0;
2412 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2413 if (wpa_s->hw.modes[i].mode == hw_mode) {
2414 mode = &wpa_s->hw.modes[i];
2415 break;
2416 }
2417 }
2418
2419 if (!mode)
2420 return 0;
2421
2422 return mode->vht_capab != 0;
2423}
2424
2425
Hai Shalomc1a21442022-02-04 13:43:00 -08002426static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2427{
2428 int i;
2429
2430 for (i = channel; i < channel + 16; i += 4) {
2431 struct hostapd_channel_data *chan;
2432
2433 chan = hw_get_channel_chan(mode, i, NULL);
2434 if (!chan ||
2435 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2436 return false;
2437 }
2438
2439 return true;
2440}
2441
2442
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002443void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2444 const struct wpa_ssid *ssid,
2445 struct hostapd_freq_params *freq)
2446{
Hai Shalom81f62d82019-07-22 12:10:00 -07002447 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002448 enum hostapd_hw_mode hw_mode;
2449 struct hostapd_hw_modes *mode = NULL;
2450 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2451 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002452 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2453 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2454 6595, 6675, 6755, 6835, 6915, 6995 };
2455 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002456 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2457 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002458 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002459 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002460 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002461 int chwidth, seg0, seg1;
2462 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002463 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002464
2465 freq->freq = ssid->frequency;
2466
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002467 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2468 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2469
2470 if (ssid->mode != WPAS_MODE_IBSS)
2471 break;
2472
2473 /* Don't adjust control freq in case of fixed_freq */
2474 if (ssid->fixed_freq)
2475 break;
2476
2477 if (!bss_is_ibss(bss))
2478 continue;
2479
2480 if (ssid->ssid_len == bss->ssid_len &&
2481 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2482 wpa_printf(MSG_DEBUG,
2483 "IBSS already found in scan results, adjust control freq: %d",
2484 bss->freq);
2485 freq->freq = bss->freq;
2486 obss_scan = 0;
2487 break;
2488 }
2489 }
2490
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002491 /* For IBSS check HT_IBSS flag */
2492 if (ssid->mode == WPAS_MODE_IBSS &&
2493 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2494 return;
2495
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002496 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2497 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2498 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2499 wpa_printf(MSG_DEBUG,
2500 "IBSS: WEP/TKIP detected, do not try to enable HT");
2501 return;
2502 }
2503
2504 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002505 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2506 if (wpa_s->hw.modes[i].mode == hw_mode) {
2507 mode = &wpa_s->hw.modes[i];
2508 break;
2509 }
2510 }
2511
2512 if (!mode)
2513 return;
2514
Hai Shalom60840252021-02-19 19:02:11 -08002515 freq->channel = channel;
2516
Hai Shalomc3565922019-10-28 11:58:20 -07002517 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2518 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002519
Hai Shalomc1a21442022-02-04 13:43:00 -08002520 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2521 * However, HE is mandatory for 6 GHz.
2522 */
2523 is_6ghz = is_6ghz_freq(freq->freq);
2524 if (is_6ghz)
2525 goto skip_to_6ghz;
2526
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002527#ifdef CONFIG_HT_OVERRIDES
2528 if (ssid->disable_ht) {
2529 freq->ht_enabled = 0;
2530 return;
2531 }
2532#endif /* CONFIG_HT_OVERRIDES */
2533
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002534 freq->ht_enabled = ht_supported(mode);
2535 if (!freq->ht_enabled)
2536 return;
2537
Hai Shalomc3565922019-10-28 11:58:20 -07002538 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2539 if (is_24ghz)
2540 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002541#ifdef CONFIG_HE_OVERRIDES
2542 if (is_24ghz && ssid->disable_he)
2543 freq->he_enabled = 0;
2544#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002545
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002546 /* Setup higher BW only for 5 GHz */
2547 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2548 return;
2549
2550 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2551 pri_chan = &mode->channels[chan_idx];
2552 if (pri_chan->chan == channel)
2553 break;
2554 pri_chan = NULL;
2555 }
2556 if (!pri_chan)
2557 return;
2558
2559 /* Check primary channel flags */
2560 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2561 return;
2562
Hai Shalom74f70d42019-02-11 14:42:39 -08002563 freq->channel = pri_chan->chan;
2564
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002565#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002566 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002567#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002568 if (ssid->disable_vht)
2569 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002570#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002571 goto skip_ht40;
2572 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002573#endif /* CONFIG_HT_OVERRIDES */
2574
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002575 /* Check/setup HT40+/HT40- */
2576 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2577 if (ht40plus[j] == channel) {
2578 ht40 = 1;
2579 break;
2580 }
2581 }
2582
2583 /* Find secondary channel */
2584 for (i = 0; i < mode->num_channels; i++) {
2585 sec_chan = &mode->channels[i];
2586 if (sec_chan->chan == channel + ht40 * 4)
2587 break;
2588 sec_chan = NULL;
2589 }
2590 if (!sec_chan)
2591 return;
2592
2593 /* Check secondary channel flags */
2594 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2595 return;
2596
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002597 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002598 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2599 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002600 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002601 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2602 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002603 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002604 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002605
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002606 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002607 struct wpa_scan_results *scan_res;
2608
2609 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2610 if (scan_res == NULL) {
2611 /* Back to HT20 */
2612 freq->sec_channel_offset = 0;
2613 return;
2614 }
2615
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002616 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002617 switch (res) {
2618 case 0:
2619 /* Back to HT20 */
2620 freq->sec_channel_offset = 0;
2621 break;
2622 case 1:
2623 /* Configuration allowed */
2624 break;
2625 case 2:
2626 /* Switch pri/sec channels */
2627 freq->freq = hw_get_freq(mode, sec_chan->chan);
2628 freq->sec_channel_offset = -freq->sec_channel_offset;
2629 freq->channel = sec_chan->chan;
2630 break;
2631 default:
2632 freq->sec_channel_offset = 0;
2633 break;
2634 }
2635
2636 wpa_scan_results_free(scan_res);
2637 }
2638
Hai Shalom74f70d42019-02-11 14:42:39 -08002639#ifdef CONFIG_HT_OVERRIDES
2640skip_ht40:
2641#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002642 wpa_printf(MSG_DEBUG,
2643 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2644 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002645
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002646 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002647 return;
2648
2649 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002650 if (ssid->mode == WPAS_MODE_IBSS &&
2651 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002652 return;
2653
Paul Stewart092955c2017-02-06 09:13:09 -08002654#ifdef CONFIG_VHT_OVERRIDES
2655 if (ssid->disable_vht) {
2656 freq->vht_enabled = 0;
2657 return;
2658 }
2659#endif /* CONFIG_VHT_OVERRIDES */
2660
Hai Shalomc1a21442022-02-04 13:43:00 -08002661skip_to_6ghz:
2662 vht_freq = *freq;
2663
2664 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002665 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002666 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002667 return;
2668
Hai Shalomfdcde762020-04-02 11:19:20 -07002669 /* Enable HE with VHT for 5 GHz */
2670 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002671
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002673 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2674 if (freq->freq >= bw80[j] &&
2675 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002676 break;
2677 }
2678
Hai Shalomc1a21442022-02-04 13:43:00 -08002679 if (j == ARRAY_SIZE(bw80) ||
2680 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002681 return;
2682
Hai Shalomc1a21442022-02-04 13:43:00 -08002683 /* Back to HT configuration if channel not usable */
2684 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2685 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002686
Hai Shalom81f62d82019-07-22 12:10:00 -07002687 chwidth = CHANWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002688 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002689 seg1 = 0;
2690
Hai Shalomc1a21442022-02-04 13:43:00 -08002691 if ((mode->he_capab[ieee80211_mode].phy_cap[
2692 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2693 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2694 /* In 160 MHz, the initial four 20 MHz channels were validated
2695 * above; check the remaining four 20 MHz channels for the total
2696 * of 160 MHz bandwidth.
2697 */
2698 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2699 return;
2700
2701 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2702 if (freq->freq == bw160[j]) {
2703 chwidth = CHANWIDTH_160MHZ;
2704 seg0 = channel + 14;
2705 break;
2706 }
2707 }
2708 }
2709
Hai Shalom81f62d82019-07-22 12:10:00 -07002710 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002711 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002712 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002713 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002714 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002715 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002716
2717 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2718 NUM_HOSTAPD_MODES)
2719 return;
2720
2721 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002722 struct hostapd_channel_data *chan;
2723
2724 chan = hw_get_channel_chan(mode, i, NULL);
2725 if (!chan)
2726 continue;
2727
2728 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2729 HOSTAPD_CHAN_NO_IR |
2730 HOSTAPD_CHAN_RADAR))
2731 continue;
2732
2733 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002734 chwidth = CHANWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002735 if (!is_6ghz)
2736 vht_caps |=
2737 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2738 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002739 }
2740
Hai Shalom81f62d82019-07-22 12:10:00 -07002741 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002742 break;
2743 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002744 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002745 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002746 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002747 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2748 seg0 = 50;
2749 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002750 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002751 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2752 seg0 = 114;
2753 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002754 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2755 chwidth = CHANWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002756 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002757#ifdef CONFIG_HT_OVERRIDES
2758 if (ssid->disable_ht40)
2759 seg0 = 0;
2760#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002761 }
2762
Hai Shalomfdcde762020-04-02 11:19:20 -07002763#ifdef CONFIG_HE_OVERRIDES
2764 if (ssid->disable_he) {
2765 vht_freq.he_enabled = 0;
2766 freq->he_enabled = 0;
2767 }
2768#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002769 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002770 freq->channel, ssid->enable_edmg,
2771 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002772 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002773 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002774 chwidth, seg0, seg1, vht_caps,
2775 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002776 return;
2777
2778 *freq = vht_freq;
2779
2780 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2781 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002782}
2783
2784
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002785#ifdef CONFIG_FILS
2786static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2787 size_t ie_buf_len)
2788{
2789 struct fils_hlp_req *req;
2790 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2791 const u8 *pos;
2792 u8 *buf = ie_buf;
2793
2794 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2795 list) {
2796 rem_len = ie_buf_len - ie_len;
2797 pos = wpabuf_head(req->pkt);
2798 hdr_len = 1 + 2 * ETH_ALEN + 6;
2799 hlp_len = wpabuf_len(req->pkt);
2800
2801 if (rem_len < 2 + hdr_len + hlp_len) {
2802 wpa_printf(MSG_ERROR,
2803 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2804 (unsigned long) rem_len,
2805 (unsigned long) (2 + hdr_len + hlp_len));
2806 break;
2807 }
2808
2809 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2810 /* Element ID */
2811 *buf++ = WLAN_EID_EXTENSION;
2812 /* Length */
2813 *buf++ = len;
2814 /* Element ID Extension */
2815 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2816 /* Destination MAC address */
2817 os_memcpy(buf, req->dst, ETH_ALEN);
2818 buf += ETH_ALEN;
2819 /* Source MAC address */
2820 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2821 buf += ETH_ALEN;
2822 /* LLC/SNAP Header */
2823 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2824 buf += 6;
2825 /* HLP Packet */
2826 os_memcpy(buf, pos, len - hdr_len);
2827 buf += len - hdr_len;
2828 pos += len - hdr_len;
2829
2830 hlp_len -= len - hdr_len;
2831 ie_len += 2 + len;
2832 rem_len -= 2 + len;
2833
2834 while (hlp_len) {
2835 len = (hlp_len > 255) ? 255 : hlp_len;
2836 if (rem_len < 2 + len)
2837 break;
2838 *buf++ = WLAN_EID_FRAGMENT;
2839 *buf++ = len;
2840 os_memcpy(buf, pos, len);
2841 buf += len;
2842 pos += len;
2843
2844 hlp_len -= len;
2845 ie_len += 2 + len;
2846 rem_len -= 2 + len;
2847 }
2848 }
2849
2850 return ie_len;
2851}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002852
2853
2854int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2855{
2856 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2857 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2858 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2859 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2860}
2861
2862
2863int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2864{
2865#ifdef CONFIG_FILS_SK_PFS
2866 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2867 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2868#else /* CONFIG_FILS_SK_PFS */
2869 return 0;
2870#endif /* CONFIG_FILS_SK_PFS */
2871}
2872
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002873#endif /* CONFIG_FILS */
2874
2875
Hai Shalomc1a21442022-02-04 13:43:00 -08002876static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2877 struct wpa_bss *bss,
2878 u8 *wpa_ie, size_t wpa_ie_len,
2879 size_t max_wpa_ie_len)
2880{
2881 struct wpabuf *wfa_ie = NULL;
2882 u8 wfa_capa[1];
2883 size_t wfa_ie_len, buf_len;
2884
2885 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2886 if (wpa_s->enable_dscp_policy_capa)
2887 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2888
2889 if (!wfa_capa[0])
2890 return wpa_ie_len;
2891
2892 /* Wi-Fi Alliance element */
2893 buf_len = 1 + /* Element ID */
2894 1 + /* Length */
2895 3 + /* OUI */
2896 1 + /* OUI Type */
2897 1 + /* Capabilities Length */
2898 sizeof(wfa_capa); /* Capabilities */
2899 wfa_ie = wpabuf_alloc(buf_len);
2900 if (!wfa_ie)
2901 return wpa_ie_len;
2902
2903 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2904 wpabuf_put_u8(wfa_ie, buf_len - 2);
2905 wpabuf_put_be24(wfa_ie, OUI_WFA);
2906 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2907 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2908 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2909
2910 wfa_ie_len = wpabuf_len(wfa_ie);
2911 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2912 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2913 wfa_ie);
2914 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2915 wfa_ie_len);
2916 wpa_ie_len += wfa_ie_len;
2917 }
2918
2919 wpabuf_free(wfa_ie);
2920 return wpa_ie_len;
2921}
2922
2923
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002924static u8 * wpas_populate_assoc_ies(
2925 struct wpa_supplicant *wpa_s,
2926 struct wpa_bss *bss, struct wpa_ssid *ssid,
2927 struct wpa_driver_associate_params *params,
2928 enum wpa_drv_update_connect_params_mask *mask)
2929{
2930 u8 *wpa_ie;
2931 size_t max_wpa_ie_len = 500;
2932 size_t wpa_ie_len;
2933 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002934#ifdef CONFIG_MBO
2935 const u8 *mbo_ie;
2936#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302937#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2938 int pmksa_cached = 0;
2939#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940#ifdef CONFIG_FILS
2941 const u8 *realm, *username, *rrk;
2942 size_t realm_len, username_len, rrk_len;
2943 u16 next_seq_num;
2944 struct fils_hlp_req *req;
2945
2946 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2947 list) {
2948 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2949 2 + 2 * wpabuf_len(req->pkt) / 255;
2950 }
2951#endif /* CONFIG_FILS */
2952
2953 wpa_ie = os_malloc(max_wpa_ie_len);
2954 if (!wpa_ie) {
2955 wpa_printf(MSG_ERROR,
2956 "Failed to allocate connect IE buffer for %lu bytes",
2957 (unsigned long) max_wpa_ie_len);
2958 return NULL;
2959 }
2960
2961 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2962 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2963 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2964 int try_opportunistic;
2965 const u8 *cache_id = NULL;
2966
2967 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2968 wpa_s->conf->okc :
2969 ssid->proactive_key_caching) &&
2970 (ssid->proto & WPA_PROTO_RSN);
2971#ifdef CONFIG_FILS
2972 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2973 cache_id = wpa_bss_get_fils_cache_id(bss);
2974#endif /* CONFIG_FILS */
2975 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2976 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002977 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002978 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302979#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2980 pmksa_cached = 1;
2981#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002982 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002983 wpa_ie_len = max_wpa_ie_len;
2984 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2985 wpa_ie, &wpa_ie_len)) {
2986 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2987 "key management and encryption suites");
2988 os_free(wpa_ie);
2989 return NULL;
2990 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002991#ifdef CONFIG_HS20
2992 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2993 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2994 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2995 wpa_ie_len = max_wpa_ie_len;
2996 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2997 wpa_ie, &wpa_ie_len)) {
2998 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2999 "key management and encryption suites");
3000 os_free(wpa_ie);
3001 return NULL;
3002 }
3003#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003004 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3005 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3006 /*
3007 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3008 * use non-WPA since the scan results did not indicate that the
3009 * AP is using WPA or WPA2.
3010 */
3011 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3012 wpa_ie_len = 0;
3013 wpa_s->wpa_proto = 0;
3014 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3015 wpa_ie_len = max_wpa_ie_len;
3016 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3017 wpa_ie, &wpa_ie_len)) {
3018 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3019 "key management and encryption suites (no "
3020 "scan results)");
3021 os_free(wpa_ie);
3022 return NULL;
3023 }
3024#ifdef CONFIG_WPS
3025 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3026 struct wpabuf *wps_ie;
3027 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3028 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3029 wpa_ie_len = wpabuf_len(wps_ie);
3030 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3031 } else
3032 wpa_ie_len = 0;
3033 wpabuf_free(wps_ie);
3034 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3035 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3036 params->wps = WPS_MODE_PRIVACY;
3037 else
3038 params->wps = WPS_MODE_OPEN;
3039 wpa_s->wpa_proto = 0;
3040#endif /* CONFIG_WPS */
3041 } else {
3042 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3043 wpa_ie_len = 0;
3044 wpa_s->wpa_proto = 0;
3045 }
3046
3047#ifdef IEEE8021X_EAPOL
3048 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3049 if (ssid->leap) {
3050 if (ssid->non_leap == 0)
3051 algs = WPA_AUTH_ALG_LEAP;
3052 else
3053 algs |= WPA_AUTH_ALG_LEAP;
3054 }
3055 }
3056
3057#ifdef CONFIG_FILS
3058 /* Clear FILS association */
3059 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3060
3061 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3062 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3063 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3064 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003065 &next_seq_num, &rrk, &rrk_len) == 0 &&
3066 (!wpa_s->last_con_fail_realm ||
3067 wpa_s->last_con_fail_realm_len != realm_len ||
3068 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003069 algs = WPA_AUTH_ALG_FILS;
3070 params->fils_erp_username = username;
3071 params->fils_erp_username_len = username_len;
3072 params->fils_erp_realm = realm;
3073 params->fils_erp_realm_len = realm_len;
3074 params->fils_erp_next_seq_num = next_seq_num;
3075 params->fils_erp_rrk = rrk;
3076 params->fils_erp_rrk_len = rrk_len;
3077
3078 if (mask)
3079 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303080 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3081 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3082 pmksa_cached) {
3083 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084 }
3085#endif /* CONFIG_FILS */
3086#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003087#ifdef CONFIG_SAE
3088 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3089 algs = WPA_AUTH_ALG_SAE;
3090#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003091
3092 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3093 if (ssid->auth_alg) {
3094 algs = ssid->auth_alg;
3095 wpa_dbg(wpa_s, MSG_DEBUG,
3096 "Overriding auth_alg selection: 0x%x", algs);
3097 }
3098
Hai Shalom5f92bc92019-04-18 11:54:11 -07003099#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303100 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003101 wpa_dbg(wpa_s, MSG_DEBUG,
3102 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3103 algs = WPA_AUTH_ALG_OPEN;
3104 }
3105#endif /* CONFIG_SAE */
3106
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003107#ifdef CONFIG_P2P
3108 if (wpa_s->global->p2p) {
3109 u8 *pos;
3110 size_t len;
3111 int res;
3112 pos = wpa_ie + wpa_ie_len;
3113 len = max_wpa_ie_len - wpa_ie_len;
3114 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3115 ssid->p2p_group);
3116 if (res >= 0)
3117 wpa_ie_len += res;
3118 }
3119
3120 wpa_s->cross_connect_disallowed = 0;
3121 if (bss) {
3122 struct wpabuf *p2p;
3123 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3124 if (p2p) {
3125 wpa_s->cross_connect_disallowed =
3126 p2p_get_cross_connect_disallowed(p2p);
3127 wpabuf_free(p2p);
3128 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3129 "connection",
3130 wpa_s->cross_connect_disallowed ?
3131 "disallows" : "allows");
3132 }
3133 }
3134
3135 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3136#endif /* CONFIG_P2P */
3137
3138 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003139 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003140 wpa_ie + wpa_ie_len,
3141 max_wpa_ie_len -
3142 wpa_ie_len);
3143 }
3144
3145 /*
3146 * Workaround: Add Extended Capabilities element only if the AP
3147 * included this element in Beacon/Probe Response frames. Some older
3148 * APs seem to have interoperability issues if this element is
3149 * included, so while the standard may require us to include the
3150 * element in all cases, it is justifiable to skip it to avoid
3151 * interoperability issues.
3152 */
3153 if (ssid->p2p_group)
3154 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3155 else
3156 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3157
3158 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3159 u8 ext_capab[18];
3160 int ext_capab_len;
3161 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3162 sizeof(ext_capab));
3163 if (ext_capab_len > 0 &&
3164 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3165 u8 *pos = wpa_ie;
3166 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3167 pos += 2 + pos[1];
3168 os_memmove(pos + ext_capab_len, pos,
3169 wpa_ie_len - (pos - wpa_ie));
3170 wpa_ie_len += ext_capab_len;
3171 os_memcpy(pos, ext_capab, ext_capab_len);
3172 }
3173 }
3174
3175#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003176 if (is_hs20_network(wpa_s, ssid, bss)
3177#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3178 && is_hs20_config(wpa_s)
3179#endif /* ANDROID */
3180 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003181 struct wpabuf *hs20;
3182
Roshan Pius3a1667e2018-07-03 15:17:14 -07003183 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003184 if (hs20) {
3185 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3186 size_t len;
3187
Hai Shalom74f70d42019-02-11 14:42:39 -08003188 wpas_hs20_add_indication(hs20, pps_mo_id,
3189 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003190 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003191 len = max_wpa_ie_len - wpa_ie_len;
3192 if (wpabuf_len(hs20) <= len) {
3193 os_memcpy(wpa_ie + wpa_ie_len,
3194 wpabuf_head(hs20), wpabuf_len(hs20));
3195 wpa_ie_len += wpabuf_len(hs20);
3196 }
3197 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003198 }
3199 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003200 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003201#endif /* CONFIG_HS20 */
3202
3203 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3204 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3205 size_t len;
3206
3207 len = max_wpa_ie_len - wpa_ie_len;
3208 if (wpabuf_len(buf) <= len) {
3209 os_memcpy(wpa_ie + wpa_ie_len,
3210 wpabuf_head(buf), wpabuf_len(buf));
3211 wpa_ie_len += wpabuf_len(buf);
3212 }
3213 }
3214
3215#ifdef CONFIG_FST
3216 if (wpa_s->fst_ies) {
3217 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3218
3219 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3220 os_memcpy(wpa_ie + wpa_ie_len,
3221 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3222 wpa_ie_len += fst_ies_len;
3223 }
3224 }
3225#endif /* CONFIG_FST */
3226
3227#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003228 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003229 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003230 int len;
3231
3232 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003233 max_wpa_ie_len - wpa_ie_len,
3234 !!mbo_attr_from_mbo_ie(mbo_ie,
3235 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003236 if (len >= 0)
3237 wpa_ie_len += len;
3238 }
3239#endif /* CONFIG_MBO */
3240
3241#ifdef CONFIG_FILS
3242 if (algs == WPA_AUTH_ALG_FILS) {
3243 size_t len;
3244
3245 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3246 max_wpa_ie_len - wpa_ie_len);
3247 wpa_ie_len += len;
3248 }
3249#endif /* CONFIG_FILS */
3250
3251#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003252#ifdef CONFIG_TESTING_OPTIONS
3253 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3254 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3255 } else
3256#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003257 if (algs == WPA_AUTH_ALG_OPEN &&
3258 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3259 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003260 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003261
Roshan Pius3a1667e2018-07-03 15:17:14 -07003262 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003263 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003264 } else if (wpa_s->assoc_status_code ==
3265 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003266 if (wpa_s->last_owe_group == 19)
3267 group = 20;
3268 else if (wpa_s->last_owe_group == 20)
3269 group = 21;
3270 else
3271 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003272 } else {
3273 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003274 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003275
Roshan Pius3a1667e2018-07-03 15:17:14 -07003276 wpa_s->last_owe_group = group;
3277 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003278 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3279 if (owe_ie &&
3280 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3281 os_memcpy(wpa_ie + wpa_ie_len,
3282 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3283 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003285 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003286 }
3287#endif /* CONFIG_OWE */
3288
Hai Shalom021b0b52019-04-10 11:17:58 -07003289#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003290 if (DPP_VERSION > 1 &&
3291 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003292 ssid->dpp_netaccesskey &&
3293 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003294 struct rsn_pmksa_cache_entry *pmksa;
3295
3296 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3297 if (!pmksa || !pmksa->dpp_pfs)
3298 goto pfs_fail;
3299
Hai Shalom021b0b52019-04-10 11:17:58 -07003300 dpp_pfs_free(wpa_s->dpp_pfs);
3301 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3302 ssid->dpp_netaccesskey_len);
3303 if (!wpa_s->dpp_pfs) {
3304 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3305 /* Try to continue without PFS */
3306 goto pfs_fail;
3307 }
3308 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3309 max_wpa_ie_len - wpa_ie_len) {
3310 os_memcpy(wpa_ie + wpa_ie_len,
3311 wpabuf_head(wpa_s->dpp_pfs->ie),
3312 wpabuf_len(wpa_s->dpp_pfs->ie));
3313 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3314 }
3315 }
3316pfs_fail:
3317#endif /* CONFIG_DPP2 */
3318
Roshan Pius3a1667e2018-07-03 15:17:14 -07003319#ifdef CONFIG_IEEE80211R
3320 /*
3321 * Add MDIE under these conditions: the network profile allows FT,
3322 * the AP supports FT, and the mobility domain ID matches.
3323 */
3324 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3325 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3326
3327 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3328 size_t len = 0;
3329 const u8 *md = mdie + 2;
3330 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3331
3332 if (os_memcmp(md, wpa_md,
3333 MOBILITY_DOMAIN_ID_LEN) == 0) {
3334 /* Add mobility domain IE */
3335 len = wpa_ft_add_mdie(
3336 wpa_s->wpa, wpa_ie + wpa_ie_len,
3337 max_wpa_ie_len - wpa_ie_len, mdie);
3338 wpa_ie_len += len;
3339 }
3340#ifdef CONFIG_SME
3341 if (len > 0 && wpa_s->sme.ft_used &&
3342 wpa_sm_has_ptk(wpa_s->wpa)) {
3343 wpa_dbg(wpa_s, MSG_DEBUG,
3344 "SME: Trying to use FT over-the-air");
3345 algs |= WPA_AUTH_ALG_FT;
3346 }
3347#endif /* CONFIG_SME */
3348 }
3349 }
3350#endif /* CONFIG_IEEE80211R */
3351
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003352#ifdef CONFIG_TESTING_OPTIONS
3353 if (wpa_s->rsnxe_override_assoc &&
3354 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3355 max_wpa_ie_len - wpa_ie_len) {
3356 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3357 os_memcpy(wpa_ie + wpa_ie_len,
3358 wpabuf_head(wpa_s->rsnxe_override_assoc),
3359 wpabuf_len(wpa_s->rsnxe_override_assoc));
3360 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3361 } else
3362#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003363 if (wpa_s->rsnxe_len > 0 &&
3364 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3365 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3366 wpa_ie_len += wpa_s->rsnxe_len;
3367 }
3368
Hai Shalomc1a21442022-02-04 13:43:00 -08003369#ifdef CONFIG_TESTING_OPTIONS
3370 if (wpa_s->disable_mscs_support)
3371 goto mscs_end;
3372#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003373 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3374 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003375 struct wpabuf *mscs_ie;
3376 size_t mscs_ie_len, buf_len;
3377
Hai Shalom899fcc72020-10-19 14:38:18 -07003378 buf_len = 3 + /* MSCS descriptor IE header */
3379 1 + /* Request type */
3380 2 + /* User priority control */
3381 4 + /* Stream timeout */
3382 3 + /* TCLAS Mask IE header */
3383 wpa_s->robust_av.frame_classifier_len;
3384 mscs_ie = wpabuf_alloc(buf_len);
3385 if (!mscs_ie) {
3386 wpa_printf(MSG_INFO,
3387 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003388 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003389 }
3390
3391 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3392 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3393 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3394 mscs_ie_len = wpabuf_len(mscs_ie);
3395 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3396 mscs_ie_len);
3397 wpa_ie_len += mscs_ie_len;
3398 }
3399
3400 wpabuf_free(mscs_ie);
3401 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003402mscs_end:
3403
3404 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3405 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003406
Hai Shalom74f70d42019-02-11 14:42:39 -08003407 if (ssid->multi_ap_backhaul_sta) {
3408 size_t multi_ap_ie_len;
3409
3410 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3411 max_wpa_ie_len - wpa_ie_len,
3412 MULTI_AP_BACKHAUL_STA);
3413 if (multi_ap_ie_len == 0) {
3414 wpa_printf(MSG_ERROR,
3415 "Multi-AP: Failed to build Multi-AP IE");
3416 os_free(wpa_ie);
3417 return NULL;
3418 }
3419 wpa_ie_len += multi_ap_ie_len;
3420 }
3421
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003422 params->wpa_ie = wpa_ie;
3423 params->wpa_ie_len = wpa_ie_len;
3424 params->auth_alg = algs;
3425 if (mask)
3426 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3427
3428 return wpa_ie;
3429}
3430
3431
Hai Shalomc3565922019-10-28 11:58:20 -07003432#ifdef CONFIG_OWE
3433static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3434{
3435 struct wpa_driver_associate_params params;
3436 u8 *wpa_ie;
3437
3438 os_memset(&params, 0, sizeof(params));
3439 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3440 wpa_s->current_ssid, &params, NULL);
3441 if (!wpa_ie)
3442 return;
3443
3444 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3445 os_free(wpa_ie);
3446}
3447#endif /* CONFIG_OWE */
3448
3449
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3451static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3452{
3453 struct wpa_driver_associate_params params;
3454 enum wpa_drv_update_connect_params_mask mask = 0;
3455 u8 *wpa_ie;
3456
3457 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3458 return; /* nothing to do */
3459
3460 os_memset(&params, 0, sizeof(params));
3461 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3462 wpa_s->current_ssid, &params, &mask);
3463 if (!wpa_ie)
3464 return;
3465
Hai Shalomc1a21442022-02-04 13:43:00 -08003466 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3467 wpa_s->auth_alg = params.auth_alg;
3468 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003469 }
3470
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003471 os_free(wpa_ie);
3472}
3473#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3474
3475
Hai Shalomc3565922019-10-28 11:58:20 -07003476static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3477{
3478 if (!edmg_ie || edmg_ie[1] < 6)
3479 return 0;
3480 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3481}
3482
3483
3484static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3485{
3486 if (!edmg_ie || edmg_ie[1] < 6)
3487 return 0;
3488 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3489}
3490
3491
3492/* Returns the intersection of two EDMG configurations.
3493 * Note: The current implementation is limited to CB2 only (CB1 included),
3494 * i.e., the implementation supports up to 2 contiguous channels.
3495 * For supporting non-contiguous (aggregated) channels and for supporting
3496 * CB3 and above, this function will need to be extended.
3497 */
3498static struct ieee80211_edmg_config
3499get_edmg_intersection(struct ieee80211_edmg_config a,
3500 struct ieee80211_edmg_config b,
3501 u8 primary_channel)
3502{
3503 struct ieee80211_edmg_config result;
3504 int i, contiguous = 0;
3505 int max_contiguous = 0;
3506
3507 result.channels = b.channels & a.channels;
3508 if (!result.channels) {
3509 wpa_printf(MSG_DEBUG,
3510 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3511 a.channels, b.channels);
3512 goto fail;
3513 }
3514
3515 if (!(result.channels & BIT(primary_channel - 1))) {
3516 wpa_printf(MSG_DEBUG,
3517 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3518 primary_channel, result.channels);
3519 goto fail;
3520 }
3521
3522 /* Find max contiguous channels */
3523 for (i = 0; i < 6; i++) {
3524 if (result.channels & BIT(i))
3525 contiguous++;
3526 else
3527 contiguous = 0;
3528
3529 if (contiguous > max_contiguous)
3530 max_contiguous = contiguous;
3531 }
3532
3533 /* Assuming AP and STA supports ONLY contiguous channels,
3534 * bw configuration can have value between 4-7.
3535 */
3536 if ((b.bw_config < a.bw_config))
3537 result.bw_config = b.bw_config;
3538 else
3539 result.bw_config = a.bw_config;
3540
3541 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3542 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3543 wpa_printf(MSG_DEBUG,
3544 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3545 max_contiguous);
3546 goto fail;
3547 }
3548
3549 return result;
3550
3551fail:
3552 result.channels = 0;
3553 result.bw_config = 0;
3554 return result;
3555}
3556
3557
3558static struct ieee80211_edmg_config
3559get_supported_edmg(struct wpa_supplicant *wpa_s,
3560 struct hostapd_freq_params *freq,
3561 struct ieee80211_edmg_config request_edmg)
3562{
3563 enum hostapd_hw_mode hw_mode;
3564 struct hostapd_hw_modes *mode = NULL;
3565 u8 primary_channel;
3566
3567 if (!wpa_s->hw.modes)
3568 goto fail;
3569
3570 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3571 if (hw_mode == NUM_HOSTAPD_MODES)
3572 goto fail;
3573
Hai Shalom60840252021-02-19 19:02:11 -08003574 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003575 if (!mode)
3576 goto fail;
3577
3578 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3579
3580fail:
3581 request_edmg.channels = 0;
3582 request_edmg.bw_config = 0;
3583 return request_edmg;
3584}
3585
3586
Hai Shalom021b0b52019-04-10 11:17:58 -07003587#ifdef CONFIG_MBO
3588void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3589{
3590 struct wpa_driver_associate_params params;
3591 u8 *wpa_ie;
3592
3593 /*
3594 * Update MBO connect params only in case of change of MBO attributes
3595 * when connected, if the AP support MBO.
3596 */
3597
3598 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3599 !wpa_s->current_bss ||
3600 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3601 return;
3602
3603 os_memset(&params, 0, sizeof(params));
3604 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3605 wpa_s->current_ssid, &params, NULL);
3606 if (!wpa_ie)
3607 return;
3608
3609 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3610 os_free(wpa_ie);
3611}
3612#endif /* CONFIG_MBO */
3613
3614
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003615static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3616{
3617 struct wpa_connect_work *cwork = work->ctx;
3618 struct wpa_bss *bss = cwork->bss;
3619 struct wpa_ssid *ssid = cwork->ssid;
3620 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003621 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003622 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003623 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003624 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003625 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003626#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003627 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003628#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003629 int assoc_failed = 0;
3630 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003631 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003632#ifdef CONFIG_HT_OVERRIDES
3633 struct ieee80211_ht_capabilities htcaps;
3634 struct ieee80211_ht_capabilities htcaps_mask;
3635#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003636#ifdef CONFIG_VHT_OVERRIDES
3637 struct ieee80211_vht_capabilities vhtcaps;
3638 struct ieee80211_vht_capabilities vhtcaps_mask;
3639#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003640
Hai Shalomc1a21442022-02-04 13:43:00 -08003641 wpa_s->roam_in_progress = false;
3642#ifdef CONFIG_WNM
3643 wpa_s->bss_trans_mgmt_in_progress = false;
3644#endif /* CONFIG_WNM */
3645
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003646 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003647 if (work->started) {
3648 wpa_s->connect_work = NULL;
3649
3650 /* cancel possible auth. timeout */
3651 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3652 NULL);
3653 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003654 wpas_connect_work_free(cwork);
3655 return;
3656 }
3657
3658 wpa_s->connect_work = work;
3659
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003660 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3661 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003662 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3663 wpas_connect_work_done(wpa_s);
3664 return;
3665 }
3666
Dmitry Shmidte4663042016-04-04 10:07:49 -07003667 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668 os_memset(&params, 0, sizeof(params));
3669 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003670 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003671
3672 /* Starting new association, so clear the possibly used WPA IE from the
3673 * previous association. */
3674 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3675 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3676 wpa_s->rsnxe_len = 0;
3677 wpa_s->mscs_setup_done = false;
3678
3679 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3680 if (!wpa_ie) {
3681 wpas_connect_work_done(wpa_s);
3682 return;
3683 }
3684
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003685 if (bss &&
3686 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003687#ifdef CONFIG_IEEE80211R
3688 const u8 *ie, *md = NULL;
3689#endif /* CONFIG_IEEE80211R */
3690 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3691 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3692 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3693 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3694 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3695 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3696 if (bssid_changed)
3697 wpas_notify_bssid_changed(wpa_s);
3698#ifdef CONFIG_IEEE80211R
3699 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3700 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3701 md = ie + 2;
3702 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3703 if (md) {
3704 /* Prepare for the next transition */
3705 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3706 }
3707#endif /* CONFIG_IEEE80211R */
3708#ifdef CONFIG_WPS
3709 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3710 wpa_s->conf->ap_scan == 2 &&
3711 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3712 /* Use ap_scan==1 style network selection to find the network
3713 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003714 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003715 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716 wpa_s->reassociate = 1;
3717 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003718 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719 return;
3720#endif /* CONFIG_WPS */
3721 } else {
3722 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3723 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003724 if (bss)
3725 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3726 else
3727 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003729 if (!wpa_s->pno)
3730 wpa_supplicant_cancel_sched_scan(wpa_s);
3731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 wpa_supplicant_cancel_scan(wpa_s);
3733
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003734 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3735 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003736 cipher_pairwise = wpa_s->pairwise_cipher;
3737 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003738 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003739 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3740 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3741 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3742 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003743#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744 if (wpa_set_wep_keys(wpa_s, ssid)) {
3745 use_crypt = 1;
3746 wep_keys_set = 1;
3747 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003748#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749 }
3750 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3751 use_crypt = 0;
3752
3753#ifdef IEEE8021X_EAPOL
3754 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3755 if ((ssid->eapol_flags &
3756 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3757 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3758 !wep_keys_set) {
3759 use_crypt = 0;
3760 } else {
3761 /* Assume that dynamic WEP-104 keys will be used and
3762 * set cipher suites in order for drivers to expect
3763 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003764 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 }
3766 }
3767#endif /* IEEE8021X_EAPOL */
3768
3769 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3770 /* Set the key before (and later after) association */
3771 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3772 }
3773
3774 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3775 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 params.ssid = bss->ssid;
3777 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003778 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3779 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003780 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3781 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003782 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003783 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003784 ssid->bssid_set,
3785 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003786 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003787 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003788 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003789 params.bssid_hint = bss->bssid;
3790 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003791 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003792 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003793 if (ssid->bssid_hint_set)
3794 params.bssid_hint = ssid->bssid_hint;
3795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003796 params.ssid = ssid->ssid;
3797 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003798 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003800
3801 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3802 wpa_s->conf->ap_scan == 2) {
3803 params.bssid = ssid->bssid;
3804 params.fixed_bssid = 1;
3805 }
3806
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003807 /* Initial frequency for IBSS/mesh */
3808 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003809 ssid->frequency > 0 && params.freq.freq == 0)
3810 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003811
3812 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003813 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003814 if (ssid->beacon_int)
3815 params.beacon_int = ssid->beacon_int;
3816 else
3817 params.beacon_int = wpa_s->conf->beacon_int;
3818 }
3819
Hai Shalomc3565922019-10-28 11:58:20 -07003820 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003821 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3822 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003823 else
3824 edmg_ie_oper = NULL;
3825
3826 if (edmg_ie_oper) {
3827 params.freq.edmg.channels =
3828 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3829 params.freq.edmg.bw_config =
3830 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3831 wpa_printf(MSG_DEBUG,
3832 "AP supports EDMG channels 0x%x, bw_config %d",
3833 params.freq.edmg.channels,
3834 params.freq.edmg.bw_config);
3835
3836 /* User may ask for specific EDMG channel for EDMG connection
3837 * (must be supported by AP)
3838 */
3839 if (ssid->edmg_channel) {
3840 struct ieee80211_edmg_config configured_edmg;
3841 enum hostapd_hw_mode hw_mode;
3842 u8 primary_channel;
3843
3844 hw_mode = ieee80211_freq_to_chan(bss->freq,
3845 &primary_channel);
3846 if (hw_mode == NUM_HOSTAPD_MODES)
3847 goto edmg_fail;
3848
3849 hostapd_encode_edmg_chan(ssid->enable_edmg,
3850 ssid->edmg_channel,
3851 primary_channel,
3852 &configured_edmg);
3853
3854 if (ieee802_edmg_is_allowed(params.freq.edmg,
3855 configured_edmg)) {
3856 params.freq.edmg = configured_edmg;
3857 wpa_printf(MSG_DEBUG,
3858 "Use EDMG channel %d for connection",
3859 ssid->edmg_channel);
3860 } else {
3861 edmg_fail:
3862 params.freq.edmg.channels = 0;
3863 params.freq.edmg.bw_config = 0;
3864 wpa_printf(MSG_WARNING,
3865 "EDMG channel %d not supported by AP, fallback to DMG",
3866 ssid->edmg_channel);
3867 }
3868 }
3869
3870 if (params.freq.edmg.channels) {
3871 wpa_printf(MSG_DEBUG,
3872 "EDMG before: channels 0x%x, bw_config %d",
3873 params.freq.edmg.channels,
3874 params.freq.edmg.bw_config);
3875 params.freq.edmg = get_supported_edmg(wpa_s,
3876 &params.freq,
3877 params.freq.edmg);
3878 wpa_printf(MSG_DEBUG,
3879 "EDMG after: channels 0x%x, bw_config %d",
3880 params.freq.edmg.channels,
3881 params.freq.edmg.bw_config);
3882 }
3883 }
3884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003885 params.pairwise_suite = cipher_pairwise;
3886 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003887 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003888 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003889 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003890 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003891 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003892 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003893#ifdef CONFIG_WEP
3894 {
3895 int i;
3896
3897 for (i = 0; i < NUM_WEP_KEYS; i++) {
3898 if (ssid->wep_key_len[i])
3899 params.wep_key[i] = ssid->wep_key[i];
3900 params.wep_key_len[i] = ssid->wep_key_len[i];
3901 }
3902 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003903 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003904#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003905
Hai Shalom74f70d42019-02-11 14:42:39 -08003906 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003907 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3908 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003909 params.passphrase = ssid->passphrase;
3910 if (ssid->psk_set)
3911 params.psk = ssid->psk;
3912 }
3913
Hai Shalom74f70d42019-02-11 14:42:39 -08003914 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3915 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3916 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3917 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3918 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003919 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003920
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003921 if (wpa_s->conf->key_mgmt_offload) {
3922 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3923 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003924 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3925 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003926 params.req_key_mgmt_offload =
3927 ssid->proactive_key_caching < 0 ?
3928 wpa_s->conf->okc : ssid->proactive_key_caching;
3929 else
3930 params.req_key_mgmt_offload = 1;
3931
3932 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3933 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3934 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3935 ssid->psk_set)
3936 params.psk = ssid->psk;
3937 }
3938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003939 params.drop_unencrypted = use_crypt;
3940
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003941 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003942 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3944 struct wpa_ie_data ie;
3945 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3946 ie.capabilities &
3947 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3948 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3949 "MFP: require MFP");
3950 params.mgmt_frame_protection =
3951 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003952#ifdef CONFIG_OWE
3953 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3954 !ssid->owe_only) {
3955 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3956#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003957 }
3958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003960 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003962 if (wpa_s->p2pdev->set_sta_uapsd)
3963 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003964 else
3965 params.uapsd = -1;
3966
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003967#ifdef CONFIG_HT_OVERRIDES
3968 os_memset(&htcaps, 0, sizeof(htcaps));
3969 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3970 params.htcaps = (u8 *) &htcaps;
3971 params.htcaps_mask = (u8 *) &htcaps_mask;
3972 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3973#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003974#ifdef CONFIG_VHT_OVERRIDES
3975 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3976 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3977 params.vhtcaps = &vhtcaps;
3978 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003979 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003980#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003981#ifdef CONFIG_HE_OVERRIDES
3982 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3983#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003984
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003985#ifdef CONFIG_P2P
3986 /*
3987 * If multi-channel concurrency is not supported, check for any
3988 * frequency conflict. In case of any frequency conflict, remove the
3989 * least prioritized connection.
3990 */
3991 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003992 int freq, num;
3993 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003994 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003995 wpa_printf(MSG_DEBUG,
3996 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003997 freq, params.freq.freq);
3998 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003999 wpa_s, params.freq.freq, ssid) < 0) {
4000 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004001 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004002 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004003 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004004 }
4005 }
4006#endif /* CONFIG_P2P */
4007
Dmitry Shmidte4663042016-04-04 10:07:49 -07004008 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
4009 wpa_s->current_ssid)
4010 params.prev_bssid = prev_bssid;
4011
Hai Shalom60840252021-02-19 19:02:11 -08004012#ifdef CONFIG_SAE
4013 params.sae_pwe = wpa_s->conf->sae_pwe;
4014#endif /* CONFIG_SAE */
4015
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004016 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004017 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004018 if (ret < 0) {
4019 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4020 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004021 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004022 /*
4023 * The driver is known to mean what is saying, so we
4024 * can stop right here; the association will not
4025 * succeed.
4026 */
4027 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004028 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004029 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004030 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4032 return;
4033 }
4034 /* try to continue anyway; new association will be tried again
4035 * after timeout */
4036 assoc_failed = 1;
4037 }
4038
4039 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4040 /* Set the key after the association just in case association
4041 * cleared the previously configured key. */
4042 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4043 /* No need to timeout authentication since there is no key
4044 * management. */
4045 wpa_supplicant_cancel_auth_timeout(wpa_s);
4046 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4047#ifdef CONFIG_IBSS_RSN
4048 } else if (ssid->mode == WPAS_MODE_IBSS &&
4049 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4050 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4051 /*
4052 * RSN IBSS authentication is per-STA and we can disable the
4053 * per-BSSID authentication.
4054 */
4055 wpa_supplicant_cancel_auth_timeout(wpa_s);
4056#endif /* CONFIG_IBSS_RSN */
4057 } else {
4058 /* Timeout for IEEE 802.11 authentication and association */
4059 int timeout = 60;
4060
4061 if (assoc_failed) {
4062 /* give IBSS a bit more time */
4063 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4064 } else if (wpa_s->conf->ap_scan == 1) {
4065 /* give IBSS a bit more time */
4066 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4067 }
4068 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4069 }
4070
Hai Shalomfdcde762020-04-02 11:19:20 -07004071#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004072 if (wep_keys_set &&
4073 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 /* Set static WEP keys again */
4075 wpa_set_wep_keys(wpa_s, ssid);
4076 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004077#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004078
4079 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
4080 /*
4081 * Do not allow EAP session resumption between different
4082 * network configurations.
4083 */
4084 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4085 }
4086 old_ssid = wpa_s->current_ssid;
4087 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004088
4089 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004090 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004091#ifdef CONFIG_HS20
4092 hs20_configure_frame_filters(wpa_s);
4093#endif /* CONFIG_HS20 */
4094 }
4095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004096 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4097 wpa_supplicant_initiate_eapol(wpa_s);
4098 if (old_ssid != wpa_s->current_ssid)
4099 wpas_notify_network_changed(wpa_s);
4100}
4101
4102
4103static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4104 const u8 *addr)
4105{
4106 struct wpa_ssid *old_ssid;
4107
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004108 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004111 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 wpa_sm_set_config(wpa_s->wpa, NULL);
4113 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4114 if (old_ssid != wpa_s->current_ssid)
4115 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004116
4117 wpas_scs_deinit(wpa_s);
4118 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4120}
4121
4122
4123/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4125 * @wpa_s: Pointer to wpa_supplicant data
4126 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4127 *
4128 * This function is used to request %wpa_supplicant to deauthenticate from the
4129 * current AP.
4130 */
4131void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004132 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133{
4134 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004135 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004136 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004137
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004138 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004139 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004140 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004141 reason_code, reason2str(reason_code),
4142 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004143
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004144 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4145 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4146 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004147 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004148 else if (!is_zero_ether_addr(wpa_s->bssid))
4149 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004150 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4151 /*
4152 * When using driver-based BSS selection, we may not know the
4153 * BSSID with which we are currently trying to associate. We
4154 * need to notify the driver of this disconnection even in such
4155 * a case, so use the all zeros address here.
4156 */
4157 addr = wpa_s->bssid;
4158 zero_addr = 1;
4159 }
4160
Hai Shalom74f70d42019-02-11 14:42:39 -08004161 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4162 wpa_s->enabled_4addr_mode = 0;
4163
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004164#ifdef CONFIG_TDLS
4165 wpa_tdls_teardown_peers(wpa_s->wpa);
4166#endif /* CONFIG_TDLS */
4167
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004168#ifdef CONFIG_MESH
4169 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004170 struct mesh_conf *mconf;
4171
4172 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004173 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4174 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004175 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4176 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004177 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004178 }
4179#endif /* CONFIG_MESH */
4180
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004181 if (addr) {
4182 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004183 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004184 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004185 event.deauth_info.locally_generated = 1;
4186 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004187 if (zero_addr)
4188 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189 }
4190
4191 wpa_supplicant_clear_connection(wpa_s, addr);
4192}
4193
Hai Shalomfdcde762020-04-02 11:19:20 -07004194
4195void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4196{
4197 wpa_s->own_reconnect_req = 1;
4198 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4199
4200}
4201
4202
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004203static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4204 struct wpa_ssid *ssid)
4205{
4206 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4207 return;
4208
4209 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004210 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004211 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4212 wpas_notify_network_enabled_changed(wpa_s, ssid);
4213
4214 /*
4215 * Try to reassociate since there is no current configuration and a new
4216 * network was made available.
4217 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004218 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004219 wpa_s->reassociate = 1;
4220}
4221
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004222
Roshan Pius950bec92016-07-19 09:49:24 -07004223/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004224 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004225 * @wpa_s: wpa_supplicant structure for a network interface
4226 * Returns: The new network configuration or %NULL if operation failed
4227 *
4228 * This function performs the following operations:
4229 * 1. Adds a new network.
4230 * 2. Send network addition notification.
4231 * 3. Marks the network disabled.
4232 * 4. Set network default parameters.
4233 */
4234struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4235{
4236 struct wpa_ssid *ssid;
4237
4238 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004239 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004240 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004241 wpas_notify_network_added(wpa_s, ssid);
4242 ssid->disabled = 1;
4243 wpa_config_set_network_defaults(ssid);
4244
4245 return ssid;
4246}
4247
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004248
Roshan Pius950bec92016-07-19 09:49:24 -07004249/**
4250 * wpa_supplicant_remove_network - Remove a configured network based on id
4251 * @wpa_s: wpa_supplicant structure for a network interface
4252 * @id: Unique network id to search for
4253 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4254 * could not be removed
4255 *
4256 * This function performs the following operations:
4257 * 1. Removes the network.
4258 * 2. Send network removal notification.
4259 * 3. Update internal state machines.
4260 * 4. Stop any running sched scans.
4261 */
4262int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4263{
4264 struct wpa_ssid *ssid;
4265 int was_disabled;
4266
4267 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004268 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004269 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004270 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004271
4272 if (wpa_s->last_ssid == ssid)
4273 wpa_s->last_ssid = NULL;
4274
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004275 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004276#ifdef CONFIG_SME
4277 wpa_s->sme.prev_bssid_set = 0;
4278#endif /* CONFIG_SME */
4279 /*
4280 * Invalidate the EAP session cache if the current or
4281 * previously used network is removed.
4282 */
4283 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4284 }
4285
4286 if (ssid == wpa_s->current_ssid) {
4287 wpa_sm_set_config(wpa_s->wpa, NULL);
4288 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4289
4290 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4291 wpa_s->own_disconnect_req = 1;
4292 wpa_supplicant_deauthenticate(wpa_s,
4293 WLAN_REASON_DEAUTH_LEAVING);
4294 }
4295
4296 was_disabled = ssid->disabled;
4297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004298 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004299 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004300
4301 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004302 wpa_printf(MSG_DEBUG,
4303 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004304 wpa_supplicant_cancel_sched_scan(wpa_s);
4305 wpa_supplicant_req_scan(wpa_s, 0, 0);
4306 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004307
Roshan Pius950bec92016-07-19 09:49:24 -07004308 return 0;
4309}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004310
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004311
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004313 * wpa_supplicant_remove_all_networks - Remove all configured networks
4314 * @wpa_s: wpa_supplicant structure for a network interface
4315 * Returns: 0 on success (errors are currently ignored)
4316 *
4317 * This function performs the following operations:
4318 * 1. Remove all networks.
4319 * 2. Send network removal notifications.
4320 * 3. Update internal state machines.
4321 * 4. Stop any running sched scans.
4322 */
4323int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4324{
4325 struct wpa_ssid *ssid;
4326
4327 if (wpa_s->sched_scanning)
4328 wpa_supplicant_cancel_sched_scan(wpa_s);
4329
4330 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4331 if (wpa_s->current_ssid) {
4332#ifdef CONFIG_SME
4333 wpa_s->sme.prev_bssid_set = 0;
4334#endif /* CONFIG_SME */
4335 wpa_sm_set_config(wpa_s->wpa, NULL);
4336 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4337 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4338 wpa_s->own_disconnect_req = 1;
4339 wpa_supplicant_deauthenticate(
4340 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4341 }
4342 ssid = wpa_s->conf->ssid;
4343 while (ssid) {
4344 struct wpa_ssid *remove_ssid = ssid;
4345 int id;
4346
4347 id = ssid->id;
4348 ssid = ssid->next;
4349 if (wpa_s->last_ssid == remove_ssid)
4350 wpa_s->last_ssid = NULL;
4351 wpas_notify_network_removed(wpa_s, remove_ssid);
4352 wpa_config_remove_network(wpa_s->conf, id);
4353 }
4354 return 0;
4355}
4356
4357
4358/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 * wpa_supplicant_enable_network - Mark a configured network as enabled
4360 * @wpa_s: wpa_supplicant structure for a network interface
4361 * @ssid: wpa_ssid structure for a configured network or %NULL
4362 *
4363 * Enables the specified network or all networks if no network specified.
4364 */
4365void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4366 struct wpa_ssid *ssid)
4367{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004369 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4370 wpa_supplicant_enable_one_network(wpa_s, ssid);
4371 } else
4372 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004373
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004374 if (wpa_s->reassociate && !wpa_s->disconnected &&
4375 (!wpa_s->current_ssid ||
4376 wpa_s->wpa_state == WPA_DISCONNECTED ||
4377 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004378 if (wpa_s->sched_scanning) {
4379 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4380 "new network to scan filters");
4381 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004382 }
4383
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004384 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4385 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004386 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004387 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 }
4389}
4390
4391
4392/**
4393 * wpa_supplicant_disable_network - Mark a configured network as disabled
4394 * @wpa_s: wpa_supplicant structure for a network interface
4395 * @ssid: wpa_ssid structure for a configured network or %NULL
4396 *
4397 * Disables the specified network or all networks if no network specified.
4398 */
4399void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4400 struct wpa_ssid *ssid)
4401{
4402 struct wpa_ssid *other_ssid;
4403 int was_disabled;
4404
4405 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004406 if (wpa_s->sched_scanning)
4407 wpa_supplicant_cancel_sched_scan(wpa_s);
4408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004409 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4410 other_ssid = other_ssid->next) {
4411 was_disabled = other_ssid->disabled;
4412 if (was_disabled == 2)
4413 continue; /* do not change persistent P2P group
4414 * data */
4415
4416 other_ssid->disabled = 1;
4417
4418 if (was_disabled != other_ssid->disabled)
4419 wpas_notify_network_enabled_changed(
4420 wpa_s, other_ssid);
4421 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004422 if (wpa_s->current_ssid) {
4423 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4424 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004425 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004426 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004427 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004429 if (ssid == wpa_s->current_ssid) {
4430 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4431 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004432 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004433 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004434 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004435
4436 was_disabled = ssid->disabled;
4437
4438 ssid->disabled = 1;
4439
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004440 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004441 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004442 if (wpa_s->sched_scanning) {
4443 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4444 "to remove network from filters");
4445 wpa_supplicant_cancel_sched_scan(wpa_s);
4446 wpa_supplicant_req_scan(wpa_s, 0, 0);
4447 }
4448 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004449 }
4450}
4451
4452
4453/**
4454 * wpa_supplicant_select_network - Attempt association with a network
4455 * @wpa_s: wpa_supplicant structure for a network interface
4456 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4457 */
4458void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4459 struct wpa_ssid *ssid)
4460{
4461
4462 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004463 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004465 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004466 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4467 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004468 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004470 disconnected = 1;
4471 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004473 if (ssid)
4474 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004476 /*
4477 * Mark all other networks disabled or mark all networks enabled if no
4478 * network specified.
4479 */
4480 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4481 other_ssid = other_ssid->next) {
4482 int was_disabled = other_ssid->disabled;
4483 if (was_disabled == 2)
4484 continue; /* do not change persistent P2P group data */
4485
4486 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004487 if (was_disabled && !other_ssid->disabled)
4488 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004489
4490 if (was_disabled != other_ssid->disabled)
4491 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4492 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004493
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004494 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4495 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004496 /* We are already associated with the selected network */
4497 wpa_printf(MSG_DEBUG, "Already associated with the "
4498 "selected network - do nothing");
4499 return;
4500 }
4501
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004502 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004503 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004504 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004505 wpa_s->connect_without_scan =
4506 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004507
4508 /*
4509 * Don't optimize next scan freqs since a new ESS has been
4510 * selected.
4511 */
4512 os_free(wpa_s->next_scan_freqs);
4513 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004514 } else {
4515 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004516 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 wpa_s->disconnected = 0;
4519 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004520 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004521 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004522 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004523 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004524 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4525 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004526
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004527 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004528 wpa_supplicant_fast_associate(wpa_s) != 1) {
4529 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004530 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004531 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004532 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004533
4534 if (ssid)
4535 wpas_notify_network_selected(wpa_s, ssid);
4536}
4537
4538
4539/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004540 * wpas_remove_cred - Remove the specified credential and all the network
4541 * entries created based on the removed credential
4542 * @wpa_s: wpa_supplicant structure for a network interface
4543 * @cred: The credential to remove
4544 * Returns: 0 on success, -1 on failure
4545 */
4546int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4547{
4548 struct wpa_ssid *ssid, *next;
4549 int id;
4550
4551 if (!cred) {
4552 wpa_printf(MSG_DEBUG, "Could not find cred");
4553 return -1;
4554 }
4555
4556 id = cred->id;
4557 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4558 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4559 return -1;
4560 }
4561
4562 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4563
4564 /* Remove any network entry created based on the removed credential */
4565 ssid = wpa_s->conf->ssid;
4566 while (ssid) {
4567 next = ssid->next;
4568
4569 if (ssid->parent_cred == cred) {
4570 wpa_printf(MSG_DEBUG,
4571 "Remove network id %d since it used the removed credential",
4572 ssid->id);
4573 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4574 -1) {
4575 wpa_printf(MSG_DEBUG,
4576 "Could not find network id=%d",
4577 ssid->id);
4578 }
4579 }
4580
4581 ssid = next;
4582 }
4583
4584 return 0;
4585}
4586
4587
4588/**
4589 * wpas_remove_cred - Remove all the Interworking credentials
4590 * @wpa_s: wpa_supplicant structure for a network interface
4591 * Returns: 0 on success, -1 on failure
4592 */
4593int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4594{
4595 int res, ret = 0;
4596 struct wpa_cred *cred, *prev;
4597
4598 cred = wpa_s->conf->cred;
4599 while (cred) {
4600 prev = cred;
4601 cred = cred->next;
4602 res = wpas_remove_cred(wpa_s, prev);
4603 if (res < 0) {
4604 wpa_printf(MSG_DEBUG,
4605 "Removal of all credentials failed - failed to remove credential id=%d",
4606 prev->id);
4607 ret = -1;
4608 }
4609 }
4610
4611 return ret;
4612}
4613
4614
4615/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004616 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4617 * @wpa_s: wpa_supplicant structure for a network interface
4618 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4619 * @pkcs11_module_path: PKCS #11 module path or NULL
4620 * Returns: 0 on success; -1 on failure
4621 *
4622 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4623 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4624 * module path fails the paths will be reset to the default value (NULL).
4625 */
4626int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4627 const char *pkcs11_engine_path,
4628 const char *pkcs11_module_path)
4629{
4630 char *pkcs11_engine_path_copy = NULL;
4631 char *pkcs11_module_path_copy = NULL;
4632
4633 if (pkcs11_engine_path != NULL) {
4634 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4635 if (pkcs11_engine_path_copy == NULL)
4636 return -1;
4637 }
4638 if (pkcs11_module_path != NULL) {
4639 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004640 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004641 os_free(pkcs11_engine_path_copy);
4642 return -1;
4643 }
4644 }
4645
4646 os_free(wpa_s->conf->pkcs11_engine_path);
4647 os_free(wpa_s->conf->pkcs11_module_path);
4648 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4649 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4650
4651 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4652 eapol_sm_deinit(wpa_s->eapol);
4653 wpa_s->eapol = NULL;
4654 if (wpa_supplicant_init_eapol(wpa_s)) {
4655 /* Error -> Reset paths to the default value (NULL) once. */
4656 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4657 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4658 NULL);
4659
4660 return -1;
4661 }
4662 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4663
4664 return 0;
4665}
4666
4667
4668/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4670 * @wpa_s: wpa_supplicant structure for a network interface
4671 * @ap_scan: AP scan mode
4672 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4673 *
4674 */
4675int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4676{
4677
4678 int old_ap_scan;
4679
4680 if (ap_scan < 0 || ap_scan > 2)
4681 return -1;
4682
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004683 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4684 wpa_printf(MSG_INFO,
4685 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4686 }
4687
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004688#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004689 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4690 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4691 wpa_s->wpa_state < WPA_COMPLETED) {
4692 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4693 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004694 return 0;
4695 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004696#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698 old_ap_scan = wpa_s->conf->ap_scan;
4699 wpa_s->conf->ap_scan = ap_scan;
4700
4701 if (old_ap_scan != wpa_s->conf->ap_scan)
4702 wpas_notify_ap_scan_changed(wpa_s);
4703
4704 return 0;
4705}
4706
4707
4708/**
4709 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4710 * @wpa_s: wpa_supplicant structure for a network interface
4711 * @expire_age: Expiration age in seconds
4712 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4713 *
4714 */
4715int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4716 unsigned int bss_expire_age)
4717{
4718 if (bss_expire_age < 10) {
4719 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4720 bss_expire_age);
4721 return -1;
4722 }
4723 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4724 bss_expire_age);
4725 wpa_s->conf->bss_expiration_age = bss_expire_age;
4726
4727 return 0;
4728}
4729
4730
4731/**
4732 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4733 * @wpa_s: wpa_supplicant structure for a network interface
4734 * @expire_count: number of scans after which an unseen BSS is reclaimed
4735 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4736 *
4737 */
4738int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4739 unsigned int bss_expire_count)
4740{
4741 if (bss_expire_count < 1) {
4742 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4743 bss_expire_count);
4744 return -1;
4745 }
4746 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4747 bss_expire_count);
4748 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4749
4750 return 0;
4751}
4752
4753
4754/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004755 * wpa_supplicant_set_scan_interval - Set scan interval
4756 * @wpa_s: wpa_supplicant structure for a network interface
4757 * @scan_interval: scan interval in seconds
4758 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4759 *
4760 */
4761int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4762 int scan_interval)
4763{
4764 if (scan_interval < 0) {
4765 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4766 scan_interval);
4767 return -1;
4768 }
4769 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4770 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004771 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004772
4773 return 0;
4774}
4775
4776
4777/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778 * wpa_supplicant_set_debug_params - Set global debug params
4779 * @global: wpa_global structure
4780 * @debug_level: debug level
4781 * @debug_timestamp: determines if show timestamp in debug data
4782 * @debug_show_keys: determines if show keys in debug data
4783 * Returns: 0 if succeed or -1 if debug_level has wrong value
4784 */
4785int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4786 int debug_timestamp, int debug_show_keys)
4787{
4788
4789 int old_level, old_timestamp, old_show_keys;
4790
4791 /* check for allowed debuglevels */
4792 if (debug_level != MSG_EXCESSIVE &&
4793 debug_level != MSG_MSGDUMP &&
4794 debug_level != MSG_DEBUG &&
4795 debug_level != MSG_INFO &&
4796 debug_level != MSG_WARNING &&
4797 debug_level != MSG_ERROR)
4798 return -1;
4799
4800 old_level = wpa_debug_level;
4801 old_timestamp = wpa_debug_timestamp;
4802 old_show_keys = wpa_debug_show_keys;
4803
4804 wpa_debug_level = debug_level;
4805 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4806 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4807
4808 if (wpa_debug_level != old_level)
4809 wpas_notify_debug_level_changed(global);
4810 if (wpa_debug_timestamp != old_timestamp)
4811 wpas_notify_debug_timestamp_changed(global);
4812 if (wpa_debug_show_keys != old_show_keys)
4813 wpas_notify_debug_show_keys_changed(global);
4814
4815 return 0;
4816}
4817
4818
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004819#ifdef CONFIG_OWE
4820static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4821 const u8 *entry_ssid, size_t entry_ssid_len)
4822{
4823 const u8 *owe, *pos, *end;
4824 u8 ssid_len;
4825 struct wpa_bss *bss;
4826
4827 /* Check network profile SSID aganst the SSID in the
4828 * OWE Transition Mode element. */
4829
4830 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4831 if (!bss)
4832 return 0;
4833
4834 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4835 if (!owe)
4836 return 0;
4837
4838 pos = owe + 6;
4839 end = owe + 2 + owe[1];
4840
4841 if (end - pos < ETH_ALEN + 1)
4842 return 0;
4843 pos += ETH_ALEN;
4844 ssid_len = *pos++;
4845 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4846 return 0;
4847
4848 return entry_ssid_len == ssid_len &&
4849 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4850}
4851#endif /* CONFIG_OWE */
4852
4853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004854/**
4855 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4856 * @wpa_s: Pointer to wpa_supplicant data
4857 * Returns: A pointer to the current network structure or %NULL on failure
4858 */
4859struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4860{
4861 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004862 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004863 int res;
4864 size_t ssid_len;
4865 u8 bssid[ETH_ALEN];
4866 int wired;
4867
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004868 res = wpa_drv_get_ssid(wpa_s, ssid);
4869 if (res < 0) {
4870 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4871 "driver");
4872 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004874 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004875
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004876 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004877 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4878 "driver");
4879 return NULL;
4880 }
4881
4882 wired = wpa_s->conf->ap_scan == 0 &&
4883 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4884
4885 entry = wpa_s->conf->ssid;
4886 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004887 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004888 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004889 (!entry->ssid ||
4890 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4891 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004892 (!entry->bssid_set ||
4893 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4894 return entry;
4895#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004896 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4898 (entry->ssid == NULL || entry->ssid_len == 0) &&
4899 (!entry->bssid_set ||
4900 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4901 return entry;
4902#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004904#ifdef CONFIG_OWE
4905 if (!wpas_network_disabled(wpa_s, entry) &&
4906 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4907 entry->ssid_len) &&
4908 (!entry->bssid_set ||
4909 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4910 return entry;
4911#endif /* CONFIG_OWE */
4912
Dmitry Shmidt04949592012-07-19 12:16:46 -07004913 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004914 entry->ssid_len == 0 &&
4915 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4916 return entry;
4917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004918 entry = entry->next;
4919 }
4920
4921 return NULL;
4922}
4923
4924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004925static int select_driver(struct wpa_supplicant *wpa_s, int i)
4926{
4927 struct wpa_global *global = wpa_s->global;
4928
4929 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004930 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004931 if (global->drv_priv[i] == NULL) {
4932 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4933 "'%s'", wpa_drivers[i]->name);
4934 return -1;
4935 }
4936 }
4937
4938 wpa_s->driver = wpa_drivers[i];
4939 wpa_s->global_drv_priv = global->drv_priv[i];
4940
4941 return 0;
4942}
4943
4944
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4946 const char *name)
4947{
4948 int i;
4949 size_t len;
4950 const char *pos, *driver = name;
4951
4952 if (wpa_s == NULL)
4953 return -1;
4954
4955 if (wpa_drivers[0] == NULL) {
4956 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4957 "wpa_supplicant");
4958 return -1;
4959 }
4960
4961 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004962 /* Default to first successful driver in the list */
4963 for (i = 0; wpa_drivers[i]; i++) {
4964 if (select_driver(wpa_s, i) == 0)
4965 return 0;
4966 }
4967 /* Drivers have each reported failure, so no wpa_msg() here. */
4968 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004969 }
4970
4971 do {
4972 pos = os_strchr(driver, ',');
4973 if (pos)
4974 len = pos - driver;
4975 else
4976 len = os_strlen(driver);
4977
4978 for (i = 0; wpa_drivers[i]; i++) {
4979 if (os_strlen(wpa_drivers[i]->name) == len &&
4980 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004981 0) {
4982 /* First driver that succeeds wins */
4983 if (select_driver(wpa_s, i) == 0)
4984 return 0;
4985 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004986 }
4987
4988 driver = pos + 1;
4989 } while (pos);
4990
4991 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4992 return -1;
4993}
4994
4995
4996/**
4997 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4998 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4999 * with struct wpa_driver_ops::init()
5000 * @src_addr: Source address of the EAPOL frame
5001 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5002 * @len: Length of the EAPOL data
5003 *
5004 * This function is called for each received EAPOL frame. Most driver
5005 * interfaces rely on more generic OS mechanism for receiving frames through
5006 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5007 * take care of received EAPOL frames and deliver them to the core supplicant
5008 * code by calling this function.
5009 */
5010void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
5011 const u8 *buf, size_t len)
5012{
5013 struct wpa_supplicant *wpa_s = ctx;
5014
5015 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
5016 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5017
Hai Shalomc1a21442022-02-04 13:43:00 -08005018 if (wpa_s->own_disconnect_req) {
5019 wpa_printf(MSG_DEBUG,
5020 "Drop received EAPOL frame as we are disconnecting");
5021 return;
5022 }
5023
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005024#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005025 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5026 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005027 if (wpa_s->ignore_auth_resp) {
5028 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5029 return;
5030 }
5031#endif /* CONFIG_TESTING_OPTIONS */
5032
Jouni Malinena05074c2012-12-21 21:35:35 +02005033 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5034 (wpa_s->last_eapol_matches_bssid &&
5035#ifdef CONFIG_AP
5036 !wpa_s->ap_iface &&
5037#endif /* CONFIG_AP */
5038 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005039 /*
5040 * There is possible race condition between receiving the
5041 * association event and the EAPOL frame since they are coming
5042 * through different paths from the driver. In order to avoid
5043 * issues in trying to process the EAPOL frame before receiving
5044 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005045 * the association event is received. This may also be needed in
5046 * driver-based roaming case, so also use src_addr != BSSID as a
5047 * trigger if we have previously confirmed that the
5048 * Authenticator uses BSSID as the src_addr (which is not the
5049 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005050 */
5051 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005052 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5053 wpa_supplicant_state_txt(wpa_s->wpa_state),
5054 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005055 wpabuf_free(wpa_s->pending_eapol_rx);
5056 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5057 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005058 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005059 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5060 ETH_ALEN);
5061 }
5062 return;
5063 }
5064
Jouni Malinena05074c2012-12-21 21:35:35 +02005065 wpa_s->last_eapol_matches_bssid =
5066 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005068#ifdef CONFIG_AP
5069 if (wpa_s->ap_iface) {
5070 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
5071 return;
5072 }
5073#endif /* CONFIG_AP */
5074
5075 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5076 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5077 "no key management is configured");
5078 return;
5079 }
5080
5081 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005082 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005083 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5084 wpa_s->wpa_state != WPA_COMPLETED) &&
5085 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005086 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005088 int timeout = 10;
5089
5090 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5091 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5092 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5093 /* Use longer timeout for IEEE 802.1X/EAP */
5094 timeout = 70;
5095 }
5096
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005097#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005098 if (wpa_s->current_ssid && wpa_s->current_bss &&
5099 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5100 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5101 /*
5102 * Use shorter timeout if going through WPS AP iteration
5103 * for PIN config method with an AP that does not
5104 * advertise Selected Registrar.
5105 */
5106 struct wpabuf *wps_ie;
5107
5108 wps_ie = wpa_bss_get_vendor_ie_multi(
5109 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5110 if (wps_ie &&
5111 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5112 timeout = 10;
5113 wpabuf_free(wps_ie);
5114 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005115#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005116
5117 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005118 }
5119 wpa_s->eapol_received++;
5120
5121 if (wpa_s->countermeasures) {
5122 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5123 "EAPOL packet");
5124 return;
5125 }
5126
5127#ifdef CONFIG_IBSS_RSN
5128 if (wpa_s->current_ssid &&
5129 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
5130 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
5131 return;
5132 }
5133#endif /* CONFIG_IBSS_RSN */
5134
5135 /* Source address of the incoming EAPOL frame could be compared to the
5136 * current BSSID. However, it is possible that a centralized
5137 * Authenticator could be using another MAC address than the BSSID of
5138 * an AP, so just allow any address to be used for now. The replies are
5139 * still sent to the current BSSID (if available), though. */
5140
5141 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5142 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005143 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5144 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005145 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
5146 return;
5147 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005148 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005149 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
5150 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5151 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005152 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005153 * handshake processing which would normally set portValid. We
5154 * need this to allow the EAPOL state machines to be completed
5155 * without going through EAPOL-Key handshake.
5156 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005157 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005158 }
5159}
5160
5161
Hai Shalomb755a2a2020-04-23 21:49:02 -07005162static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5163{
5164 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5165 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5166}
5167
5168
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005169int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005170{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005171 if ((!wpa_s->p2p_mgmt ||
5172 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5173 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005174 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005175 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5176 wpa_drv_get_mac_addr(wpa_s),
5177 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005178 wpas_eapol_needs_l2_packet(wpa_s) ?
5179 wpa_supplicant_rx_eapol : NULL,
5180 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005181 if (wpa_s->l2 == NULL)
5182 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005183
5184 if (l2_packet_set_packet_filter(wpa_s->l2,
5185 L2_PACKET_FILTER_PKTTYPE))
5186 wpa_dbg(wpa_s, MSG_DEBUG,
5187 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005188
5189 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5190 wpa_msg(wpa_s, MSG_ERROR,
5191 "Failed to get own L2 address");
5192 return -1;
5193 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194 } else {
5195 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5196 if (addr)
5197 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5198 }
5199
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005200 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005201 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005202
Hai Shalomc3565922019-10-28 11:58:20 -07005203#ifdef CONFIG_FST
5204 if (wpa_s->fst)
5205 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5206#endif /* CONFIG_FST */
5207
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005208 return 0;
5209}
5210
5211
Dmitry Shmidt04949592012-07-19 12:16:46 -07005212static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5213 const u8 *buf, size_t len)
5214{
5215 struct wpa_supplicant *wpa_s = ctx;
5216 const struct l2_ethhdr *eth;
5217
5218 if (len < sizeof(*eth))
5219 return;
5220 eth = (const struct l2_ethhdr *) buf;
5221
5222 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5223 !(eth->h_dest[0] & 0x01)) {
5224 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5225 " (bridge - not for this interface - ignore)",
5226 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5227 return;
5228 }
5229
5230 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5231 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5232 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5233 len - sizeof(*eth));
5234}
5235
5236
Hai Shalom899fcc72020-10-19 14:38:18 -07005237int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5238 const char *bridge_ifname)
5239{
5240 if (wpa_s->wpa_state > WPA_SCANNING)
5241 return -EBUSY;
5242
5243 if (bridge_ifname &&
5244 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5245 return -EINVAL;
5246
5247 if (!bridge_ifname)
5248 bridge_ifname = "";
5249
5250 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5251 return 0;
5252
5253 if (wpa_s->l2_br) {
5254 l2_packet_deinit(wpa_s->l2_br);
5255 wpa_s->l2_br = NULL;
5256 }
5257
5258 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5259 sizeof(wpa_s->bridge_ifname));
5260
5261 if (wpa_s->bridge_ifname[0]) {
5262 wpa_dbg(wpa_s, MSG_DEBUG,
5263 "Receiving packets from bridge interface '%s'",
5264 wpa_s->bridge_ifname);
5265 wpa_s->l2_br = l2_packet_init_bridge(
5266 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5267 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5268 if (!wpa_s->l2_br) {
5269 wpa_msg(wpa_s, MSG_ERROR,
5270 "Failed to open l2_packet connection for the bridge interface '%s'",
5271 wpa_s->bridge_ifname);
5272 goto fail;
5273 }
5274 }
5275
5276#ifdef CONFIG_TDLS
5277 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5278 goto fail;
5279#endif /* CONFIG_TDLS */
5280
5281 return 0;
5282fail:
5283 wpa_s->bridge_ifname[0] = 0;
5284 if (wpa_s->l2_br) {
5285 l2_packet_deinit(wpa_s->l2_br);
5286 wpa_s->l2_br = NULL;
5287 }
5288#ifdef CONFIG_TDLS
5289 if (!wpa_s->p2p_mgmt)
5290 wpa_tdls_init(wpa_s->wpa);
5291#endif /* CONFIG_TDLS */
5292 return -EIO;
5293}
5294
5295
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005296/**
5297 * wpa_supplicant_driver_init - Initialize driver interface parameters
5298 * @wpa_s: Pointer to wpa_supplicant data
5299 * Returns: 0 on success, -1 on failure
5300 *
5301 * This function is called to initialize driver interface parameters.
5302 * wpa_drv_init() must have been called before this function to initialize the
5303 * driver interface.
5304 */
5305int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5306{
5307 static int interface_count = 0;
5308
5309 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5310 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005311
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005312 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5313 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005314 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005315 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5316
Hai Shalomb755a2a2020-04-23 21:49:02 -07005317 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005318 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5319 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005320 wpa_s->l2_br = l2_packet_init_bridge(
5321 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5322 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005323 if (wpa_s->l2_br == NULL) {
5324 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5325 "connection for the bridge interface '%s'",
5326 wpa_s->bridge_ifname);
5327 return -1;
5328 }
5329 }
5330
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005331 if (wpa_s->conf->ap_scan == 2 &&
5332 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5333 wpa_printf(MSG_INFO,
5334 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5335 }
5336
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005337 wpa_clear_keys(wpa_s, NULL);
5338
5339 /* Make sure that TKIP countermeasures are not left enabled (could
5340 * happen if wpa_supplicant is killed during countermeasures. */
5341 wpa_drv_set_countermeasures(wpa_s, 0);
5342
5343 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5344 wpa_drv_flush_pmkid(wpa_s);
5345
5346 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005347 wpa_s->prev_scan_wildcard = 0;
5348
Dmitry Shmidt04949592012-07-19 12:16:46 -07005349 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005350 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5351 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5352 interface_count = 0;
5353 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005354#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005355 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005356 wpa_supplicant_delayed_sched_scan(wpa_s,
5357 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005358 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005359 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005360 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005361#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005362 interface_count++;
5363 } else
5364 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5365
5366 return 0;
5367}
5368
5369
5370static int wpa_supplicant_daemon(const char *pid_file)
5371{
5372 wpa_printf(MSG_DEBUG, "Daemonize..");
5373 return os_daemonize(pid_file);
5374}
5375
5376
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005377static struct wpa_supplicant *
5378wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005379{
5380 struct wpa_supplicant *wpa_s;
5381
5382 wpa_s = os_zalloc(sizeof(*wpa_s));
5383 if (wpa_s == NULL)
5384 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005385 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005386 wpa_s->scan_interval = 5;
5387 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005388 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005389 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005390 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005391 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005393 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005394 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005395#ifdef CONFIG_TESTING_OPTIONS
5396 dl_list_init(&wpa_s->drv_signal_override);
5397#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005398 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005400 return wpa_s;
5401}
5402
5403
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005404#ifdef CONFIG_HT_OVERRIDES
5405
5406static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5407 struct ieee80211_ht_capabilities *htcaps,
5408 struct ieee80211_ht_capabilities *htcaps_mask,
5409 const char *ht_mcs)
5410{
5411 /* parse ht_mcs into hex array */
5412 int i;
5413 const char *tmp = ht_mcs;
5414 char *end = NULL;
5415
5416 /* If ht_mcs is null, do not set anything */
5417 if (!ht_mcs)
5418 return 0;
5419
5420 /* This is what we are setting in the kernel */
5421 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5422
5423 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5424
5425 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005426 long v;
5427
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005428 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005429 v = strtol(tmp, &end, 16);
5430
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005431 if (errno == 0) {
5432 wpa_msg(wpa_s, MSG_DEBUG,
5433 "htcap value[%i]: %ld end: %p tmp: %p",
5434 i, v, end, tmp);
5435 if (end == tmp)
5436 break;
5437
5438 htcaps->supported_mcs_set[i] = v;
5439 tmp = end;
5440 } else {
5441 wpa_msg(wpa_s, MSG_ERROR,
5442 "Failed to parse ht-mcs: %s, error: %s\n",
5443 ht_mcs, strerror(errno));
5444 return -1;
5445 }
5446 }
5447
5448 /*
5449 * If we were able to parse any values, then set mask for the MCS set.
5450 */
5451 if (i) {
5452 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5453 IEEE80211_HT_MCS_MASK_LEN - 1);
5454 /* skip the 3 reserved bits */
5455 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5456 0x1f;
5457 }
5458
5459 return 0;
5460}
5461
5462
5463static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5464 struct ieee80211_ht_capabilities *htcaps,
5465 struct ieee80211_ht_capabilities *htcaps_mask,
5466 int disabled)
5467{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005468 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005469
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005470 if (disabled == -1)
5471 return 0;
5472
Hai Shalom74f70d42019-02-11 14:42:39 -08005473 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5474
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005475 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5476 htcaps_mask->ht_capabilities_info |= msk;
5477 if (disabled)
5478 htcaps->ht_capabilities_info &= msk;
5479 else
5480 htcaps->ht_capabilities_info |= msk;
5481
5482 return 0;
5483}
5484
5485
5486static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5487 struct ieee80211_ht_capabilities *htcaps,
5488 struct ieee80211_ht_capabilities *htcaps_mask,
5489 int factor)
5490{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005491 if (factor == -1)
5492 return 0;
5493
Hai Shalom74f70d42019-02-11 14:42:39 -08005494 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5495
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005496 if (factor < 0 || factor > 3) {
5497 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5498 "Must be 0-3 or -1", factor);
5499 return -EINVAL;
5500 }
5501
5502 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5503 htcaps->a_mpdu_params &= ~0x3;
5504 htcaps->a_mpdu_params |= factor & 0x3;
5505
5506 return 0;
5507}
5508
5509
5510static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5511 struct ieee80211_ht_capabilities *htcaps,
5512 struct ieee80211_ht_capabilities *htcaps_mask,
5513 int density)
5514{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005515 if (density == -1)
5516 return 0;
5517
Hai Shalom74f70d42019-02-11 14:42:39 -08005518 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5519
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005520 if (density < 0 || density > 7) {
5521 wpa_msg(wpa_s, MSG_ERROR,
5522 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5523 density);
5524 return -EINVAL;
5525 }
5526
5527 htcaps_mask->a_mpdu_params |= 0x1C;
5528 htcaps->a_mpdu_params &= ~(0x1C);
5529 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5530
5531 return 0;
5532}
5533
5534
5535static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5536 struct ieee80211_ht_capabilities *htcaps,
5537 struct ieee80211_ht_capabilities *htcaps_mask,
5538 int disabled)
5539{
Hai Shalom74f70d42019-02-11 14:42:39 -08005540 if (disabled)
5541 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005542
Paul Stewart092955c2017-02-06 09:13:09 -08005543 set_disable_ht40(htcaps, disabled);
5544 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005545
5546 return 0;
5547}
5548
5549
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005550static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5551 struct ieee80211_ht_capabilities *htcaps,
5552 struct ieee80211_ht_capabilities *htcaps_mask,
5553 int disabled)
5554{
5555 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005556 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5557 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005558
Hai Shalom74f70d42019-02-11 14:42:39 -08005559 if (disabled)
5560 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005561
5562 if (disabled)
5563 htcaps->ht_capabilities_info &= ~msk;
5564 else
5565 htcaps->ht_capabilities_info |= msk;
5566
5567 htcaps_mask->ht_capabilities_info |= msk;
5568
5569 return 0;
5570}
5571
5572
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005573static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5574 struct ieee80211_ht_capabilities *htcaps,
5575 struct ieee80211_ht_capabilities *htcaps_mask,
5576 int disabled)
5577{
5578 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005579 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005580
Hai Shalom74f70d42019-02-11 14:42:39 -08005581 if (disabled)
5582 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005583
5584 if (disabled)
5585 htcaps->ht_capabilities_info &= ~msk;
5586 else
5587 htcaps->ht_capabilities_info |= msk;
5588
5589 htcaps_mask->ht_capabilities_info |= msk;
5590
5591 return 0;
5592}
5593
5594
Hai Shalom74f70d42019-02-11 14:42:39 -08005595static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5596 struct ieee80211_ht_capabilities *htcaps,
5597 struct ieee80211_ht_capabilities *htcaps_mask,
5598 int tx_stbc)
5599{
5600 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5601
5602 if (tx_stbc == -1)
5603 return 0;
5604
5605 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5606
5607 if (tx_stbc < 0 || tx_stbc > 1) {
5608 wpa_msg(wpa_s, MSG_ERROR,
5609 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5610 return -EINVAL;
5611 }
5612
5613 htcaps_mask->ht_capabilities_info |= msk;
5614 htcaps->ht_capabilities_info &= ~msk;
5615 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5616
5617 return 0;
5618}
5619
5620
5621static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5622 struct ieee80211_ht_capabilities *htcaps,
5623 struct ieee80211_ht_capabilities *htcaps_mask,
5624 int rx_stbc)
5625{
5626 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5627
5628 if (rx_stbc == -1)
5629 return 0;
5630
5631 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5632
5633 if (rx_stbc < 0 || rx_stbc > 3) {
5634 wpa_msg(wpa_s, MSG_ERROR,
5635 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5636 return -EINVAL;
5637 }
5638
5639 htcaps_mask->ht_capabilities_info |= msk;
5640 htcaps->ht_capabilities_info &= ~msk;
5641 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5642
5643 return 0;
5644}
5645
5646
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005647void wpa_supplicant_apply_ht_overrides(
5648 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5649 struct wpa_driver_associate_params *params)
5650{
5651 struct ieee80211_ht_capabilities *htcaps;
5652 struct ieee80211_ht_capabilities *htcaps_mask;
5653
5654 if (!ssid)
5655 return;
5656
5657 params->disable_ht = ssid->disable_ht;
5658 if (!params->htcaps || !params->htcaps_mask)
5659 return;
5660
5661 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5662 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5663 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5664 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5665 ssid->disable_max_amsdu);
5666 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5667 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5668 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005669 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005670 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005671 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5672 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005673
5674 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005675 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005676 htcaps->ht_capabilities_info |= bit;
5677 htcaps_mask->ht_capabilities_info |= bit;
5678 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005679}
5680
5681#endif /* CONFIG_HT_OVERRIDES */
5682
5683
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005684#ifdef CONFIG_VHT_OVERRIDES
5685void wpa_supplicant_apply_vht_overrides(
5686 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5687 struct wpa_driver_associate_params *params)
5688{
5689 struct ieee80211_vht_capabilities *vhtcaps;
5690 struct ieee80211_vht_capabilities *vhtcaps_mask;
5691
5692 if (!ssid)
5693 return;
5694
5695 params->disable_vht = ssid->disable_vht;
5696
5697 vhtcaps = (void *) params->vhtcaps;
5698 vhtcaps_mask = (void *) params->vhtcaps_mask;
5699
5700 if (!vhtcaps || !vhtcaps_mask)
5701 return;
5702
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005703 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5704 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005705
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005706#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005707 if (ssid->disable_sgi) {
5708 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5709 VHT_CAP_SHORT_GI_160);
5710 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5711 VHT_CAP_SHORT_GI_160);
5712 wpa_msg(wpa_s, MSG_DEBUG,
5713 "disable-sgi override specified, vht-caps: 0x%x",
5714 vhtcaps->vht_capabilities_info);
5715 }
5716
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005717 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005718 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5719 int max_ampdu;
5720
5721 max_ampdu = (ssid->vht_capa &
5722 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5723 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005724
5725 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5726 wpa_set_ampdu_factor(wpa_s,
5727 (void *) params->htcaps,
5728 (void *) params->htcaps_mask,
5729 max_ampdu);
5730 }
5731#endif /* CONFIG_HT_OVERRIDES */
5732
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005733#define OVERRIDE_MCS(i) \
5734 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5735 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005736 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005737 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005738 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5739 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005740 } \
5741 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5742 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005743 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005744 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005745 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5746 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005747 }
5748
5749 OVERRIDE_MCS(1);
5750 OVERRIDE_MCS(2);
5751 OVERRIDE_MCS(3);
5752 OVERRIDE_MCS(4);
5753 OVERRIDE_MCS(5);
5754 OVERRIDE_MCS(6);
5755 OVERRIDE_MCS(7);
5756 OVERRIDE_MCS(8);
5757}
5758#endif /* CONFIG_VHT_OVERRIDES */
5759
5760
Hai Shalomfdcde762020-04-02 11:19:20 -07005761#ifdef CONFIG_HE_OVERRIDES
5762void wpa_supplicant_apply_he_overrides(
5763 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5764 struct wpa_driver_associate_params *params)
5765{
5766 if (!ssid)
5767 return;
5768
5769 params->disable_he = ssid->disable_he;
5770}
5771#endif /* CONFIG_HE_OVERRIDES */
5772
5773
Dmitry Shmidt04949592012-07-19 12:16:46 -07005774static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5775{
5776#ifdef PCSC_FUNCS
5777 size_t len;
5778
5779 if (!wpa_s->conf->pcsc_reader)
5780 return 0;
5781
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005782 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005783 if (!wpa_s->scard)
5784 return 1;
5785
5786 if (wpa_s->conf->pcsc_pin &&
5787 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5788 scard_deinit(wpa_s->scard);
5789 wpa_s->scard = NULL;
5790 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5791 return -1;
5792 }
5793
5794 len = sizeof(wpa_s->imsi) - 1;
5795 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5796 scard_deinit(wpa_s->scard);
5797 wpa_s->scard = NULL;
5798 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5799 return -1;
5800 }
5801 wpa_s->imsi[len] = '\0';
5802
5803 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5804
5805 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5806 wpa_s->imsi, wpa_s->mnc_len);
5807
5808 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5809 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5810#endif /* PCSC_FUNCS */
5811
5812 return 0;
5813}
5814
5815
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005816int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5817{
5818 char *val, *pos;
5819
5820 ext_password_deinit(wpa_s->ext_pw);
5821 wpa_s->ext_pw = NULL;
5822 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5823
5824 if (!wpa_s->conf->ext_password_backend)
5825 return 0;
5826
5827 val = os_strdup(wpa_s->conf->ext_password_backend);
5828 if (val == NULL)
5829 return -1;
5830 pos = os_strchr(val, ':');
5831 if (pos)
5832 *pos++ = '\0';
5833
5834 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5835
5836 wpa_s->ext_pw = ext_password_init(val, pos);
5837 os_free(val);
5838 if (wpa_s->ext_pw == NULL) {
5839 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5840 return -1;
5841 }
5842 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5843
5844 return 0;
5845}
5846
5847
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005848#ifdef CONFIG_FST
5849
5850static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5851{
5852 struct wpa_supplicant *wpa_s = ctx;
5853
5854 return (is_zero_ether_addr(wpa_s->bssid) ||
5855 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5856}
5857
5858
5859static void wpas_fst_get_channel_info_cb(void *ctx,
5860 enum hostapd_hw_mode *hw_mode,
5861 u8 *channel)
5862{
5863 struct wpa_supplicant *wpa_s = ctx;
5864
5865 if (wpa_s->current_bss) {
5866 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5867 channel);
5868 } else if (wpa_s->hw.num_modes) {
5869 *hw_mode = wpa_s->hw.modes[0].mode;
5870 } else {
5871 WPA_ASSERT(0);
5872 *hw_mode = 0;
5873 }
5874}
5875
5876
5877static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5878{
5879 struct wpa_supplicant *wpa_s = ctx;
5880
5881 *modes = wpa_s->hw.modes;
5882 return wpa_s->hw.num_modes;
5883}
5884
5885
5886static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5887{
5888 struct wpa_supplicant *wpa_s = ctx;
5889
5890 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5891 wpa_s->fst_ies = fst_ies;
5892}
5893
5894
5895static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5896{
5897 struct wpa_supplicant *wpa_s = ctx;
5898
Paul Stewart092955c2017-02-06 09:13:09 -08005899 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5900 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5901 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5902 return -1;
5903 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005904 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005905 wpa_s->own_addr, wpa_s->bssid,
5906 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005907 0);
5908}
5909
5910
5911static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5912{
5913 struct wpa_supplicant *wpa_s = ctx;
5914
5915 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5916 return wpa_s->received_mb_ies;
5917}
5918
5919
5920static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5921 const u8 *buf, size_t size)
5922{
5923 struct wpa_supplicant *wpa_s = ctx;
5924 struct mb_ies_info info;
5925
5926 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5927
5928 if (!mb_ies_info_by_ies(&info, buf, size)) {
5929 wpabuf_free(wpa_s->received_mb_ies);
5930 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5931 }
5932}
5933
5934
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005935static const u8 * wpas_fst_get_peer_first(void *ctx,
5936 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005937 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005938{
5939 struct wpa_supplicant *wpa_s = ctx;
5940
5941 *get_ctx = NULL;
5942 if (!is_zero_ether_addr(wpa_s->bssid))
5943 return (wpa_s->received_mb_ies || !mb_only) ?
5944 wpa_s->bssid : NULL;
5945 return NULL;
5946}
5947
5948
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005949static const u8 * wpas_fst_get_peer_next(void *ctx,
5950 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005951 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005952{
5953 return NULL;
5954}
5955
5956void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5957 struct fst_wpa_obj *iface_obj)
5958{
5959 iface_obj->ctx = wpa_s;
5960 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5961 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5962 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5963 iface_obj->set_ies = wpas_fst_set_ies_cb;
5964 iface_obj->send_action = wpas_fst_send_action_cb;
5965 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5966 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5967 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5968 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5969}
5970#endif /* CONFIG_FST */
5971
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005972static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005973 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005974{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005975 struct wowlan_triggers *triggers;
5976 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005977
5978 if (!wpa_s->conf->wowlan_triggers)
5979 return 0;
5980
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005981 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5982 if (triggers) {
5983 ret = wpa_drv_wowlan(wpa_s, triggers);
5984 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005985 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005986 return ret;
5987}
5988
5989
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005990enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005991{
5992 if (freq < 3000)
5993 return BAND_2_4_GHZ;
5994 if (freq > 50000)
5995 return BAND_60_GHZ;
5996 return BAND_5_GHZ;
5997}
5998
5999
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006000unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006001{
6002 int i;
6003 unsigned int band = 0;
6004
6005 if (freqs) {
6006 /* freqs are specified for the radio work */
6007 for (i = 0; freqs[i]; i++)
6008 band |= wpas_freq_to_band(freqs[i]);
6009 } else {
6010 /*
6011 * freqs are not specified, implies all
6012 * the supported freqs by HW
6013 */
6014 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6015 if (wpa_s->hw.modes[i].num_channels != 0) {
6016 if (wpa_s->hw.modes[i].mode ==
6017 HOSTAPD_MODE_IEEE80211B ||
6018 wpa_s->hw.modes[i].mode ==
6019 HOSTAPD_MODE_IEEE80211G)
6020 band |= BAND_2_4_GHZ;
6021 else if (wpa_s->hw.modes[i].mode ==
6022 HOSTAPD_MODE_IEEE80211A)
6023 band |= BAND_5_GHZ;
6024 else if (wpa_s->hw.modes[i].mode ==
6025 HOSTAPD_MODE_IEEE80211AD)
6026 band |= BAND_60_GHZ;
6027 else if (wpa_s->hw.modes[i].mode ==
6028 HOSTAPD_MODE_IEEE80211ANY)
6029 band = BAND_2_4_GHZ | BAND_5_GHZ |
6030 BAND_60_GHZ;
6031 }
6032 }
6033 }
6034
6035 return band;
6036}
6037
6038
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006039static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6040 const char *rn)
6041{
6042 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6043 struct wpa_radio *radio;
6044
6045 while (rn && iface) {
6046 radio = iface->radio;
6047 if (radio && os_strcmp(rn, radio->name) == 0) {
6048 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6049 wpa_s->ifname, rn);
6050 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6051 return radio;
6052 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006053
6054 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006055 }
6056
6057 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6058 wpa_s->ifname, rn ? rn : "N/A");
6059 radio = os_zalloc(sizeof(*radio));
6060 if (radio == NULL)
6061 return NULL;
6062
6063 if (rn)
6064 os_strlcpy(radio->name, rn, sizeof(radio->name));
6065 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006066 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006067 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6068
6069 return radio;
6070}
6071
6072
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006073static void radio_work_free(struct wpa_radio_work *work)
6074{
6075 if (work->wpa_s->scan_work == work) {
6076 /* This should not really happen. */
6077 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6078 work->type, work, work->started);
6079 work->wpa_s->scan_work = NULL;
6080 }
6081
6082#ifdef CONFIG_P2P
6083 if (work->wpa_s->p2p_scan_work == work) {
6084 /* This should not really happen. */
6085 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6086 work->type, work, work->started);
6087 work->wpa_s->p2p_scan_work = NULL;
6088 }
6089#endif /* CONFIG_P2P */
6090
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006091 if (work->started) {
6092 work->wpa_s->radio->num_active_works--;
6093 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006094 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006095 work->type, work,
6096 work->wpa_s->radio->num_active_works);
6097 }
6098
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006099 dl_list_del(&work->list);
6100 os_free(work);
6101}
6102
6103
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006104static int radio_work_is_connect(struct wpa_radio_work *work)
6105{
6106 return os_strcmp(work->type, "sme-connect") == 0 ||
6107 os_strcmp(work->type, "connect") == 0;
6108}
6109
6110
6111static int radio_work_is_scan(struct wpa_radio_work *work)
6112{
6113 return os_strcmp(work->type, "scan") == 0 ||
6114 os_strcmp(work->type, "p2p-scan") == 0;
6115}
6116
6117
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006118static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6119{
6120 struct wpa_radio_work *active_work = NULL;
6121 struct wpa_radio_work *tmp;
6122
6123 /* Get the active work to know the type and band. */
6124 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6125 if (tmp->started) {
6126 active_work = tmp;
6127 break;
6128 }
6129 }
6130
6131 if (!active_work) {
6132 /* No active work, start one */
6133 radio->num_active_works = 0;
6134 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6135 list) {
6136 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006137 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006138 (((struct wpa_driver_scan_params *)
6139 tmp->ctx)->only_new_results ||
6140 tmp->wpa_s->clear_driver_scan_cache))
6141 continue;
6142 return tmp;
6143 }
6144 return NULL;
6145 }
6146
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006147 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006148 /*
6149 * If the active work is either connect or sme-connect,
6150 * do not parallelize them with other radio works.
6151 */
6152 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6153 "Do not parallelize radio work with %s",
6154 active_work->type);
6155 return NULL;
6156 }
6157
6158 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6159 if (tmp->started)
6160 continue;
6161
6162 /*
6163 * If connect or sme-connect are enqueued, parallelize only
6164 * those operations ahead of them in the queue.
6165 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006166 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006167 break;
6168
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006169 /* Serialize parallel scan and p2p_scan operations on the same
6170 * interface since the driver_nl80211 mechanism for tracking
6171 * scan cookies does not yet have support for this. */
6172 if (active_work->wpa_s == tmp->wpa_s &&
6173 radio_work_is_scan(active_work) &&
6174 radio_work_is_scan(tmp)) {
6175 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6176 "Do not start work '%s' when another work '%s' is already scheduled",
6177 tmp->type, active_work->type);
6178 continue;
6179 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006180 /*
6181 * Check that the radio works are distinct and
6182 * on different bands.
6183 */
6184 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6185 (active_work->bands != tmp->bands)) {
6186 /*
6187 * If a scan has to be scheduled through nl80211 scan
6188 * interface and if an external scan is already running,
6189 * do not schedule the scan since it is likely to get
6190 * rejected by kernel.
6191 */
6192 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006193 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006194 (((struct wpa_driver_scan_params *)
6195 tmp->ctx)->only_new_results ||
6196 tmp->wpa_s->clear_driver_scan_cache))
6197 continue;
6198
6199 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6200 "active_work:%s new_work:%s",
6201 active_work->type, tmp->type);
6202 return tmp;
6203 }
6204 }
6205
6206 /* Did not find a radio work to schedule in parallel. */
6207 return NULL;
6208}
6209
6210
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006211static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6212{
6213 struct wpa_radio *radio = eloop_ctx;
6214 struct wpa_radio_work *work;
6215 struct os_reltime now, diff;
6216 struct wpa_supplicant *wpa_s;
6217
6218 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006219 if (work == NULL) {
6220 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006221 return;
6222 }
6223
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006224 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6225 radio_list);
6226
6227 if (!(wpa_s &&
6228 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6229 if (work->started)
6230 return; /* already started and still in progress */
6231
Hai Shalom60840252021-02-19 19:02:11 -08006232 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006233 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6234 return;
6235 }
6236 } else {
6237 work = NULL;
6238 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6239 /* get the work to schedule next */
6240 work = radio_work_get_next_work(radio);
6241 }
6242 if (!work)
6243 return;
6244 }
6245
6246 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006247 os_get_reltime(&now);
6248 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006249 wpa_dbg(wpa_s, MSG_DEBUG,
6250 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006251 work->type, work, diff.sec, diff.usec);
6252 work->started = 1;
6253 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006254 radio->num_active_works++;
6255
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006256 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006257
6258 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6259 radio->num_active_works < MAX_ACTIVE_WORKS)
6260 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006261}
6262
6263
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006264/*
6265 * This function removes both started and pending radio works running on
6266 * the provided interface's radio.
6267 * Prior to the removal of the radio work, its callback (cb) is called with
6268 * deinit set to be 1. Each work's callback is responsible for clearing its
6269 * internal data and restoring to a correct state.
6270 * @wpa_s: wpa_supplicant data
6271 * @type: type of works to be removed
6272 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6273 * this interface's works.
6274 */
6275void radio_remove_works(struct wpa_supplicant *wpa_s,
6276 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006277{
6278 struct wpa_radio_work *work, *tmp;
6279 struct wpa_radio *radio = wpa_s->radio;
6280
6281 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6282 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006283 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006284 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006285
6286 /* skip other ifaces' works */
6287 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006288 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006289
6290 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6291 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006292 work->cb(work, 1);
6293 radio_work_free(work);
6294 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006295
6296 /* in case we removed the started work */
6297 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006298}
6299
6300
Roshan Pius3a1667e2018-07-03 15:17:14 -07006301void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6302{
6303 struct wpa_radio_work *work;
6304 struct wpa_radio *radio = wpa_s->radio;
6305
6306 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6307 if (work->ctx != ctx)
6308 continue;
6309 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6310 work->type, work, work->started ? " (started)" : "");
6311 radio_work_free(work);
6312 break;
6313 }
6314}
6315
6316
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006317static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6318{
6319 struct wpa_radio *radio = wpa_s->radio;
6320
6321 if (!radio)
6322 return;
6323
6324 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6325 wpa_s->ifname, radio->name);
6326 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006327 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006328 /* If the interface that triggered the external scan was removed, the
6329 * external scan is no longer running. */
6330 if (wpa_s == radio->external_scan_req_interface)
6331 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006332 wpa_s->radio = NULL;
6333 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006334 return; /* Interfaces remain for this radio */
6335
6336 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006337 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006338 os_free(radio);
6339}
6340
6341
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006342void radio_work_check_next(struct wpa_supplicant *wpa_s)
6343{
6344 struct wpa_radio *radio = wpa_s->radio;
6345
6346 if (dl_list_empty(&radio->work))
6347 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006348 if (wpa_s->ext_work_in_progress) {
6349 wpa_printf(MSG_DEBUG,
6350 "External radio work in progress - delay start of pending item");
6351 return;
6352 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006353 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6354 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6355}
6356
6357
6358/**
6359 * radio_add_work - Add a radio work item
6360 * @wpa_s: Pointer to wpa_supplicant data
6361 * @freq: Frequency of the offchannel operation in MHz or 0
6362 * @type: Unique identifier for each type of work
6363 * @next: Force as the next work to be executed
6364 * @cb: Callback function for indicating when radio is available
6365 * @ctx: Context pointer for the work (work->ctx in cb())
6366 * Returns: 0 on success, -1 on failure
6367 *
6368 * This function is used to request time for an operation that requires
6369 * exclusive radio control. Once the radio is available, the registered callback
6370 * function will be called. radio_work_done() must be called once the exclusive
6371 * radio operation has been completed, so that the radio is freed for other
6372 * operations. The special case of deinit=1 is used to free the context data
6373 * during interface removal. That does not allow the callback function to start
6374 * the radio operation, i.e., it must free any resources allocated for the radio
6375 * work and return.
6376 *
6377 * The @freq parameter can be used to indicate a single channel on which the
6378 * offchannel operation will occur. This may allow multiple radio work
6379 * operations to be performed in parallel if they apply for the same channel.
6380 * Setting this to 0 indicates that the work item may use multiple channels or
6381 * requires exclusive control of the radio.
6382 */
6383int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6384 const char *type, int next,
6385 void (*cb)(struct wpa_radio_work *work, int deinit),
6386 void *ctx)
6387{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006388 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006389 struct wpa_radio_work *work;
6390 int was_empty;
6391
6392 work = os_zalloc(sizeof(*work));
6393 if (work == NULL)
6394 return -1;
6395 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6396 os_get_reltime(&work->time);
6397 work->freq = freq;
6398 work->type = type;
6399 work->wpa_s = wpa_s;
6400 work->cb = cb;
6401 work->ctx = ctx;
6402
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006403 if (freq)
6404 work->bands = wpas_freq_to_band(freq);
6405 else if (os_strcmp(type, "scan") == 0 ||
6406 os_strcmp(type, "p2p-scan") == 0)
6407 work->bands = wpas_get_bands(wpa_s,
6408 ((struct wpa_driver_scan_params *)
6409 ctx)->freqs);
6410 else
6411 work->bands = wpas_get_bands(wpa_s, NULL);
6412
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006413 was_empty = dl_list_empty(&wpa_s->radio->work);
6414 if (next)
6415 dl_list_add(&wpa_s->radio->work, &work->list);
6416 else
6417 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6418 if (was_empty) {
6419 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6420 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006421 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6422 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6423 wpa_dbg(wpa_s, MSG_DEBUG,
6424 "Try to schedule a radio work (num_active_works=%u)",
6425 radio->num_active_works);
6426 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006427 }
6428
6429 return 0;
6430}
6431
6432
6433/**
6434 * radio_work_done - Indicate that a radio work item has been completed
6435 * @work: Completed work
6436 *
6437 * This function is called once the callback function registered with
6438 * radio_add_work() has completed its work.
6439 */
6440void radio_work_done(struct wpa_radio_work *work)
6441{
6442 struct wpa_supplicant *wpa_s = work->wpa_s;
6443 struct os_reltime now, diff;
6444 unsigned int started = work->started;
6445
6446 os_get_reltime(&now);
6447 os_reltime_sub(&now, &work->time, &diff);
6448 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6449 work->type, work, started ? "done" : "canceled",
6450 diff.sec, diff.usec);
6451 radio_work_free(work);
6452 if (started)
6453 radio_work_check_next(wpa_s);
6454}
6455
6456
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006457struct wpa_radio_work *
6458radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006459{
6460 struct wpa_radio_work *work;
6461 struct wpa_radio *radio = wpa_s->radio;
6462
6463 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6464 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006465 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006466 }
6467
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006468 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006469}
6470
6471
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006472static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006473 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006474{
6475 const char *ifname, *driver, *rn;
6476
6477 driver = iface->driver;
6478next_driver:
6479 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6480 return -1;
6481
6482 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6483 if (wpa_s->drv_priv == NULL) {
6484 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006485 int level = MSG_ERROR;
6486
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006487 pos = driver ? os_strchr(driver, ',') : NULL;
6488 if (pos) {
6489 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6490 "driver interface - try next driver wrapper");
6491 driver = pos + 1;
6492 goto next_driver;
6493 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006494
6495#ifdef CONFIG_MATCH_IFACE
6496 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6497 level = MSG_DEBUG;
6498#endif /* CONFIG_MATCH_IFACE */
6499 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006500 return -1;
6501 }
6502 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6503 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6504 "driver_param '%s'", wpa_s->conf->driver_param);
6505 return -1;
6506 }
6507
6508 ifname = wpa_drv_get_ifname(wpa_s);
6509 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6510 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6511 "interface name with '%s'", ifname);
6512 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6513 }
6514
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006515 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006516 if (rn && rn[0] == '\0')
6517 rn = NULL;
6518
6519 wpa_s->radio = radio_add_interface(wpa_s, rn);
6520 if (wpa_s->radio == NULL)
6521 return -1;
6522
6523 return 0;
6524}
6525
6526
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006527#ifdef CONFIG_GAS_SERVER
6528
6529static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6530 unsigned int freq, const u8 *dst,
6531 const u8 *src, const u8 *bssid,
6532 const u8 *data, size_t data_len,
6533 enum offchannel_send_action_result result)
6534{
6535 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6536 " result=%s",
6537 freq, MAC2STR(dst),
6538 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6539 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6540 "FAILED"));
6541 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6542 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6543}
6544
6545
6546static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6547 struct wpabuf *buf, unsigned int wait_time)
6548{
6549 struct wpa_supplicant *wpa_s = ctx;
6550 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6551
6552 if (wait_time > wpa_s->max_remain_on_chan)
6553 wait_time = wpa_s->max_remain_on_chan;
6554
6555 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6556 wpabuf_head(buf), wpabuf_len(buf),
6557 wait_time, wpas_gas_server_tx_status, 0);
6558}
6559
6560#endif /* CONFIG_GAS_SERVER */
6561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006562static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006563 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006564{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006565 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006566 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006567 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006568
6569 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6570 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6571 iface->confname ? iface->confname : "N/A",
6572 iface->driver ? iface->driver : "default",
6573 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6574 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6575
6576 if (iface->confname) {
6577#ifdef CONFIG_BACKEND_FILE
6578 wpa_s->confname = os_rel2abs_path(iface->confname);
6579 if (wpa_s->confname == NULL) {
6580 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6581 "for configuration file '%s'.",
6582 iface->confname);
6583 return -1;
6584 }
6585 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6586 iface->confname, wpa_s->confname);
6587#else /* CONFIG_BACKEND_FILE */
6588 wpa_s->confname = os_strdup(iface->confname);
6589#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006590 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006591 if (wpa_s->conf == NULL) {
6592 wpa_printf(MSG_ERROR, "Failed to read or parse "
6593 "configuration '%s'.", wpa_s->confname);
6594 return -1;
6595 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006596 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006597 if (wpa_s->confanother &&
6598 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6599 wpa_printf(MSG_ERROR,
6600 "Failed to read or parse configuration '%s'.",
6601 wpa_s->confanother);
6602 return -1;
6603 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006604
6605 /*
6606 * Override ctrl_interface and driver_param if set on command
6607 * line.
6608 */
6609 if (iface->ctrl_interface) {
6610 os_free(wpa_s->conf->ctrl_interface);
6611 wpa_s->conf->ctrl_interface =
6612 os_strdup(iface->ctrl_interface);
6613 }
6614
6615 if (iface->driver_param) {
6616 os_free(wpa_s->conf->driver_param);
6617 wpa_s->conf->driver_param =
6618 os_strdup(iface->driver_param);
6619 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006620
6621 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6622 os_free(wpa_s->conf->ctrl_interface);
6623 wpa_s->conf->ctrl_interface = NULL;
6624 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006625 } else
6626 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6627 iface->driver_param);
6628
6629 if (wpa_s->conf == NULL) {
6630 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6631 return -1;
6632 }
6633
6634 if (iface->ifname == NULL) {
6635 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6636 return -1;
6637 }
6638 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6639 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6640 iface->ifname);
6641 return -1;
6642 }
6643 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006644#ifdef CONFIG_MATCH_IFACE
6645 wpa_s->matched = iface->matched;
6646#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006647
6648 if (iface->bridge_ifname) {
6649 if (os_strlen(iface->bridge_ifname) >=
6650 sizeof(wpa_s->bridge_ifname)) {
6651 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6652 "name '%s'.", iface->bridge_ifname);
6653 return -1;
6654 }
6655 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6656 sizeof(wpa_s->bridge_ifname));
6657 }
6658
6659 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006660 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6661 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006662
6663 /* Initialize driver interface and register driver event handler before
6664 * L2 receive handler so that association events are processed before
6665 * EAPOL-Key packets if both become available for the same select()
6666 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006667 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006668 return -1;
6669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006670 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6671 return -1;
6672
6673 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6674 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6675 NULL);
6676 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6677
6678 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6679 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6680 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6681 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6682 "dot11RSNAConfigPMKLifetime");
6683 return -1;
6684 }
6685
6686 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6687 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6688 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6689 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6690 "dot11RSNAConfigPMKReauthThreshold");
6691 return -1;
6692 }
6693
6694 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6695 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6696 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6697 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6698 "dot11RSNAConfigSATimeout");
6699 return -1;
6700 }
6701
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006702 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6703 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006704 &wpa_s->hw.flags,
6705 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006706 if (wpa_s->hw.modes) {
6707 u16 i;
6708
6709 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6710 if (wpa_s->hw.modes[i].vht_capab) {
6711 wpa_s->hw_capab = CAPAB_VHT;
6712 break;
6713 }
6714
6715 if (wpa_s->hw.modes[i].ht_capab &
6716 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6717 wpa_s->hw_capab = CAPAB_HT40;
6718 else if (wpa_s->hw.modes[i].ht_capab &&
6719 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6720 wpa_s->hw_capab = CAPAB_HT;
6721 }
6722 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006723
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006724 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6725 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006726 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006727 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006728 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006729 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006730 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006731 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006732 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006733 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006734 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6735 wpa_s->max_sched_scan_plan_interval =
6736 capa.max_sched_scan_plan_interval;
6737 wpa_s->max_sched_scan_plan_iterations =
6738 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006739 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6740 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006741 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6742 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006743 wpa_s->extended_capa = capa.extended_capa;
6744 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6745 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006746 wpa_s->num_multichan_concurrent =
6747 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006748 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6749
6750 if (capa.mac_addr_rand_scan_supported)
6751 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6752 if (wpa_s->sched_scan_supported &&
6753 capa.mac_addr_rand_sched_scan_supported)
6754 wpa_s->mac_addr_rand_supported |=
6755 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006756
6757 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6758 if (wpa_s->extended_capa &&
6759 wpa_s->extended_capa_len >= 3 &&
6760 wpa_s->extended_capa[2] & 0x40)
6761 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006762 }
6763 if (wpa_s->max_remain_on_chan == 0)
6764 wpa_s->max_remain_on_chan = 1000;
6765
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006766 /*
6767 * Only take p2p_mgmt parameters when P2P Device is supported.
6768 * Doing it here as it determines whether l2_packet_init() will be done
6769 * during wpa_supplicant_driver_init().
6770 */
6771 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6772 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006773
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006774 if (wpa_s->num_multichan_concurrent == 0)
6775 wpa_s->num_multichan_concurrent = 1;
6776
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006777 if (wpa_supplicant_driver_init(wpa_s) < 0)
6778 return -1;
6779
6780#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006781 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006782 return -1;
6783#endif /* CONFIG_TDLS */
6784
6785 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6786 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6787 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6788 return -1;
6789 }
6790
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006791#ifdef CONFIG_FST
6792 if (wpa_s->conf->fst_group_id) {
6793 struct fst_iface_cfg cfg;
6794 struct fst_wpa_obj iface_obj;
6795
6796 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6797 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6798 sizeof(cfg.group_id));
6799 cfg.priority = wpa_s->conf->fst_priority;
6800 cfg.llt = wpa_s->conf->fst_llt;
6801
6802 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6803 &iface_obj, &cfg);
6804 if (!wpa_s->fst) {
6805 wpa_msg(wpa_s, MSG_ERROR,
6806 "FST: Cannot attach iface %s to group %s",
6807 wpa_s->ifname, cfg.group_id);
6808 return -1;
6809 }
6810 }
6811#endif /* CONFIG_FST */
6812
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006813 if (wpas_wps_init(wpa_s))
6814 return -1;
6815
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006816#ifdef CONFIG_GAS_SERVER
6817 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6818 if (!wpa_s->gas_server) {
6819 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6820 return -1;
6821 }
6822#endif /* CONFIG_GAS_SERVER */
6823
6824#ifdef CONFIG_DPP
6825 if (wpas_dpp_init(wpa_s) < 0)
6826 return -1;
6827#endif /* CONFIG_DPP */
6828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006829 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6830 return -1;
6831 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6832
6833 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6834 if (wpa_s->ctrl_iface == NULL) {
6835 wpa_printf(MSG_ERROR,
6836 "Failed to initialize control interface '%s'.\n"
6837 "You may have another wpa_supplicant process "
6838 "already running or the file was\n"
6839 "left by an unclean termination of wpa_supplicant "
6840 "in which case you will need\n"
6841 "to manually remove this file before starting "
6842 "wpa_supplicant again.\n",
6843 wpa_s->conf->ctrl_interface);
6844 return -1;
6845 }
6846
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006847 wpa_s->gas = gas_query_init(wpa_s);
6848 if (wpa_s->gas == NULL) {
6849 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6850 return -1;
6851 }
6852
Roshan Pius3a1667e2018-07-03 15:17:14 -07006853 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6854 wpa_s->p2p_mgmt) &&
6855 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006856 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6857 return -1;
6858 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006859
6860 if (wpa_bss_init(wpa_s) < 0)
6861 return -1;
6862
Paul Stewart092955c2017-02-06 09:13:09 -08006863#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6864#ifdef CONFIG_MESH
6865 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6866#endif /* CONFIG_MESH */
6867#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6868
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006869 /*
6870 * Set Wake-on-WLAN triggers, if configured.
6871 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6872 * have effect anyway when the interface is down).
6873 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006874 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006875 return -1;
6876
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006877#ifdef CONFIG_EAP_PROXY
6878{
6879 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006880 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6881 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006882 if (wpa_s->mnc_len > 0) {
6883 wpa_s->imsi[len] = '\0';
6884 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6885 wpa_s->imsi, wpa_s->mnc_len);
6886 } else {
6887 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6888 }
6889}
6890#endif /* CONFIG_EAP_PROXY */
6891
Dmitry Shmidt04949592012-07-19 12:16:46 -07006892 if (pcsc_reader_init(wpa_s) < 0)
6893 return -1;
6894
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006895 if (wpas_init_ext_pw(wpa_s) < 0)
6896 return -1;
6897
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006898 wpas_rrm_reset(wpa_s);
6899
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006900 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6901
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006902#ifdef CONFIG_HS20
6903 hs20_init(wpa_s);
6904#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006905#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006906 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006907 if ((wpa_s->conf->oce & OCE_STA) &&
6908 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6909 wpa_s->enable_oce = OCE_STA;
6910 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6911 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6912 /* TODO: Need to add STA-CFON support */
6913 wpa_printf(MSG_ERROR,
6914 "OCE STA-CFON feature is not yet supported");
6915 }
6916 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006917 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6918#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006919
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006920 wpa_supplicant_set_default_scan_ies(wpa_s);
6921
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006922 return 0;
6923}
6924
6925
6926static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006927 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006928{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006929 struct wpa_global *global = wpa_s->global;
6930 struct wpa_supplicant *iface, *prev;
6931
Jimmy Chen0e73c002021-08-18 13:21:30 +08006932 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006933 wpas_p2p_group_remove(wpa_s, "*");
6934
6935 iface = global->ifaces;
6936 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006937 if (iface->p2pdev == wpa_s)
6938 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006939 if (iface == wpa_s || iface->parent != wpa_s) {
6940 iface = iface->next;
6941 continue;
6942 }
6943 wpa_printf(MSG_DEBUG,
6944 "Remove remaining child interface %s from parent %s",
6945 iface->ifname, wpa_s->ifname);
6946 prev = iface;
6947 iface = iface->next;
6948 wpa_supplicant_remove_iface(global, prev, terminate);
6949 }
6950
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006951 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006952 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006953 /*
6954 * Don't deauthenticate if WoWLAN is enable and not explicitly
6955 * been configured to disconnect.
6956 */
6957 if (!wpa_drv_get_wowlan(wpa_s) ||
6958 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006959 wpa_supplicant_deauthenticate(
6960 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006961
Hai Shalomfdcde762020-04-02 11:19:20 -07006962 wpa_drv_set_countermeasures(wpa_s, 0);
6963 wpa_clear_keys(wpa_s, NULL);
6964 } else {
6965 wpa_msg(wpa_s, MSG_INFO,
6966 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6967 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006968 }
6969
6970 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006971 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006972
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006973 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006974 radio_remove_interface(wpa_s);
6975
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006976#ifdef CONFIG_FST
6977 if (wpa_s->fst) {
6978 fst_detach(wpa_s->fst);
6979 wpa_s->fst = NULL;
6980 }
6981 if (wpa_s->received_mb_ies) {
6982 wpabuf_free(wpa_s->received_mb_ies);
6983 wpa_s->received_mb_ies = NULL;
6984 }
6985#endif /* CONFIG_FST */
6986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006987 if (wpa_s->drv_priv)
6988 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006989
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006990 if (notify)
6991 wpas_notify_iface_removed(wpa_s);
6992
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006993 if (terminate)
6994 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006995
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02006996 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
6997 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006998
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006999#ifdef CONFIG_MESH
7000 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007001 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007002 wpa_s->ifmsh = NULL;
7003 }
7004#endif /* CONFIG_MESH */
7005
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007006 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007007 wpa_config_free(wpa_s->conf);
7008 wpa_s->conf = NULL;
7009 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007010
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007011 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007012 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007013
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007014 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007015}
7016
7017
Dmitry Shmidte4663042016-04-04 10:07:49 -07007018#ifdef CONFIG_MATCH_IFACE
7019
7020/**
7021 * wpa_supplicant_match_iface - Match an interface description to a name
7022 * @global: Pointer to global data from wpa_supplicant_init()
7023 * @ifname: Name of the interface to match
7024 * Returns: Pointer to the created interface description or %NULL on failure
7025 */
7026struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7027 const char *ifname)
7028{
7029 int i;
7030 struct wpa_interface *iface, *miface;
7031
7032 for (i = 0; i < global->params.match_iface_count; i++) {
7033 miface = &global->params.match_ifaces[i];
7034 if (!miface->ifname ||
7035 fnmatch(miface->ifname, ifname, 0) == 0) {
7036 iface = os_zalloc(sizeof(*iface));
7037 if (!iface)
7038 return NULL;
7039 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007040 if (!miface->ifname)
7041 iface->matched = WPA_IFACE_MATCHED_NULL;
7042 else
7043 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007044 iface->ifname = ifname;
7045 return iface;
7046 }
7047 }
7048
7049 return NULL;
7050}
7051
7052
7053/**
7054 * wpa_supplicant_match_existing - Match existing interfaces
7055 * @global: Pointer to global data from wpa_supplicant_init()
7056 * Returns: 0 on success, -1 on failure
7057 */
7058static int wpa_supplicant_match_existing(struct wpa_global *global)
7059{
7060 struct if_nameindex *ifi, *ifp;
7061 struct wpa_supplicant *wpa_s;
7062 struct wpa_interface *iface;
7063
7064 ifp = if_nameindex();
7065 if (!ifp) {
7066 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7067 return -1;
7068 }
7069
7070 for (ifi = ifp; ifi->if_name; ifi++) {
7071 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7072 if (wpa_s)
7073 continue;
7074 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7075 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007076 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007077 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007078 }
7079 }
7080
7081 if_freenameindex(ifp);
7082 return 0;
7083}
7084
7085#endif /* CONFIG_MATCH_IFACE */
7086
7087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007088/**
7089 * wpa_supplicant_add_iface - Add a new network interface
7090 * @global: Pointer to global data from wpa_supplicant_init()
7091 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007092 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007093 * Returns: Pointer to the created interface or %NULL on failure
7094 *
7095 * This function is used to add new network interfaces for %wpa_supplicant.
7096 * This can be called before wpa_supplicant_run() to add interfaces before the
7097 * main event loop has been started. In addition, new interfaces can be added
7098 * dynamically while %wpa_supplicant is already running. This could happen,
7099 * e.g., when a hotplug network adapter is inserted.
7100 */
7101struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007102 struct wpa_interface *iface,
7103 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007104{
7105 struct wpa_supplicant *wpa_s;
7106 struct wpa_interface t_iface;
7107 struct wpa_ssid *ssid;
7108
7109 if (global == NULL || iface == NULL)
7110 return NULL;
7111
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007112 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007113 if (wpa_s == NULL)
7114 return NULL;
7115
7116 wpa_s->global = global;
7117
7118 t_iface = *iface;
7119 if (global->params.override_driver) {
7120 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7121 "('%s' -> '%s')",
7122 iface->driver, global->params.override_driver);
7123 t_iface.driver = global->params.override_driver;
7124 }
7125 if (global->params.override_ctrl_interface) {
7126 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7127 "ctrl_interface ('%s' -> '%s')",
7128 iface->ctrl_interface,
7129 global->params.override_ctrl_interface);
7130 t_iface.ctrl_interface =
7131 global->params.override_ctrl_interface;
7132 }
7133 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7134 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7135 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007136 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007137 return NULL;
7138 }
7139
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007140 /* Notify the control interfaces about new iface */
7141 if (wpas_notify_iface_added(wpa_s)) {
7142 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7143 return NULL;
7144 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007146 /* Notify the control interfaces about new networks for non p2p mgmt
7147 * ifaces. */
7148 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007149 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
7150 wpas_notify_network_added(wpa_s, ssid);
7151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007152
7153 wpa_s->next = global->ifaces;
7154 global->ifaces = wpa_s;
7155
7156 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007157 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007158
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007159#ifdef CONFIG_P2P
7160 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007161 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007162 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007163 wpas_p2p_add_p2pdev_interface(
7164 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007165 wpa_printf(MSG_INFO,
7166 "P2P: Failed to enable P2P Device interface");
7167 /* Try to continue without. P2P will be disabled. */
7168 }
7169#endif /* CONFIG_P2P */
7170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007171 return wpa_s;
7172}
7173
7174
7175/**
7176 * wpa_supplicant_remove_iface - Remove a network interface
7177 * @global: Pointer to global data from wpa_supplicant_init()
7178 * @wpa_s: Pointer to the network interface to be removed
7179 * Returns: 0 if interface was removed, -1 if interface was not found
7180 *
7181 * This function can be used to dynamically remove network interfaces from
7182 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7183 * addition, this function is used to remove all remaining interfaces when
7184 * %wpa_supplicant is terminated.
7185 */
7186int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007187 struct wpa_supplicant *wpa_s,
7188 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007189{
7190 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007191#ifdef CONFIG_MESH
7192 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7193 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007194 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007195#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007196
7197 /* Remove interface from the global list of interfaces */
7198 prev = global->ifaces;
7199 if (prev == wpa_s) {
7200 global->ifaces = wpa_s->next;
7201 } else {
7202 while (prev && prev->next != wpa_s)
7203 prev = prev->next;
7204 if (prev == NULL)
7205 return -1;
7206 prev->next = wpa_s->next;
7207 }
7208
7209 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7210
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007211#ifdef CONFIG_MESH
7212 if (mesh_if_created) {
7213 ifname = os_strdup(wpa_s->ifname);
7214 if (ifname == NULL) {
7215 wpa_dbg(wpa_s, MSG_ERROR,
7216 "mesh: Failed to malloc ifname");
7217 return -1;
7218 }
7219 }
7220#endif /* CONFIG_MESH */
7221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007222 if (global->p2p_group_formation == wpa_s)
7223 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007224 if (global->p2p_invite_group == wpa_s)
7225 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007226 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007227
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007228#ifdef CONFIG_MESH
7229 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007230 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007231 os_free(ifname);
7232 }
7233#endif /* CONFIG_MESH */
7234
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007235 return 0;
7236}
7237
7238
7239/**
7240 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7241 * @wpa_s: Pointer to the network interface
7242 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7243 */
7244const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7245{
7246 const char *eapol_method;
7247
7248 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7249 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7250 return "NO-EAP";
7251 }
7252
7253 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7254 if (eapol_method == NULL)
7255 return "UNKNOWN-EAP";
7256
7257 return eapol_method;
7258}
7259
7260
7261/**
7262 * wpa_supplicant_get_iface - Get a new network interface
7263 * @global: Pointer to global data from wpa_supplicant_init()
7264 * @ifname: Interface name
7265 * Returns: Pointer to the interface or %NULL if not found
7266 */
7267struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7268 const char *ifname)
7269{
7270 struct wpa_supplicant *wpa_s;
7271
7272 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7273 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7274 return wpa_s;
7275 }
7276 return NULL;
7277}
7278
7279
7280#ifndef CONFIG_NO_WPA_MSG
7281static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7282{
7283 struct wpa_supplicant *wpa_s = ctx;
7284 if (wpa_s == NULL)
7285 return NULL;
7286 return wpa_s->ifname;
7287}
7288#endif /* CONFIG_NO_WPA_MSG */
7289
7290
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007291#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7292#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7293#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7294
7295/* Periodic cleanup tasks */
7296static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7297{
7298 struct wpa_global *global = eloop_ctx;
7299 struct wpa_supplicant *wpa_s;
7300
7301 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7302 wpas_periodic, global, NULL);
7303
7304#ifdef CONFIG_P2P
7305 if (global->p2p)
7306 p2p_expire_peers(global->p2p);
7307#endif /* CONFIG_P2P */
7308
7309 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7310 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7311#ifdef CONFIG_AP
7312 ap_periodic(wpa_s);
7313#endif /* CONFIG_AP */
7314 }
7315}
7316
7317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007318/**
7319 * wpa_supplicant_init - Initialize %wpa_supplicant
7320 * @params: Parameters for %wpa_supplicant
7321 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7322 *
7323 * This function is used to initialize %wpa_supplicant. After successful
7324 * initialization, the returned data pointer can be used to add and remove
7325 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7326 */
7327struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7328{
7329 struct wpa_global *global;
7330 int ret, i;
7331
7332 if (params == NULL)
7333 return NULL;
7334
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007335#ifdef CONFIG_DRIVER_NDIS
7336 {
7337 void driver_ndis_init_ops(void);
7338 driver_ndis_init_ops();
7339 }
7340#endif /* CONFIG_DRIVER_NDIS */
7341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007342#ifndef CONFIG_NO_WPA_MSG
7343 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7344#endif /* CONFIG_NO_WPA_MSG */
7345
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007346 if (params->wpa_debug_file_path)
7347 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007348 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007349 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007350 if (params->wpa_debug_syslog)
7351 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007352 if (params->wpa_debug_tracing) {
7353 ret = wpa_debug_open_linux_tracing();
7354 if (ret) {
7355 wpa_printf(MSG_ERROR,
7356 "Failed to enable trace logging");
7357 return NULL;
7358 }
7359 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007360
7361 ret = eap_register_methods();
7362 if (ret) {
7363 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7364 if (ret == -2)
7365 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7366 "the same EAP type.");
7367 return NULL;
7368 }
7369
7370 global = os_zalloc(sizeof(*global));
7371 if (global == NULL)
7372 return NULL;
7373 dl_list_init(&global->p2p_srv_bonjour);
7374 dl_list_init(&global->p2p_srv_upnp);
7375 global->params.daemonize = params->daemonize;
7376 global->params.wait_for_monitor = params->wait_for_monitor;
7377 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7378 if (params->pid_file)
7379 global->params.pid_file = os_strdup(params->pid_file);
7380 if (params->ctrl_interface)
7381 global->params.ctrl_interface =
7382 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007383 if (params->ctrl_interface_group)
7384 global->params.ctrl_interface_group =
7385 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007386 if (params->override_driver)
7387 global->params.override_driver =
7388 os_strdup(params->override_driver);
7389 if (params->override_ctrl_interface)
7390 global->params.override_ctrl_interface =
7391 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007392#ifdef CONFIG_MATCH_IFACE
7393 global->params.match_iface_count = params->match_iface_count;
7394 if (params->match_iface_count) {
7395 global->params.match_ifaces =
7396 os_calloc(params->match_iface_count,
7397 sizeof(struct wpa_interface));
7398 os_memcpy(global->params.match_ifaces,
7399 params->match_ifaces,
7400 params->match_iface_count *
7401 sizeof(struct wpa_interface));
7402 }
7403#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007404#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007405 if (params->conf_p2p_dev)
7406 global->params.conf_p2p_dev =
7407 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007408#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007409 wpa_debug_level = global->params.wpa_debug_level =
7410 params->wpa_debug_level;
7411 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7412 params->wpa_debug_show_keys;
7413 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7414 params->wpa_debug_timestamp;
7415
Hai Shalomfdcde762020-04-02 11:19:20 -07007416 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007417
7418 if (eloop_init()) {
7419 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7420 wpa_supplicant_deinit(global);
7421 return NULL;
7422 }
7423
Jouni Malinen75ecf522011-06-27 15:19:46 -07007424 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007425
7426 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7427 if (global->ctrl_iface == NULL) {
7428 wpa_supplicant_deinit(global);
7429 return NULL;
7430 }
7431
7432 if (wpas_notify_supplicant_initialized(global)) {
7433 wpa_supplicant_deinit(global);
7434 return NULL;
7435 }
7436
7437 for (i = 0; wpa_drivers[i]; i++)
7438 global->drv_count++;
7439 if (global->drv_count == 0) {
7440 wpa_printf(MSG_ERROR, "No drivers enabled");
7441 wpa_supplicant_deinit(global);
7442 return NULL;
7443 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007444 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007445 if (global->drv_priv == NULL) {
7446 wpa_supplicant_deinit(global);
7447 return NULL;
7448 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007449
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007450#ifdef CONFIG_WIFI_DISPLAY
7451 if (wifi_display_init(global) < 0) {
7452 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7453 wpa_supplicant_deinit(global);
7454 return NULL;
7455 }
7456#endif /* CONFIG_WIFI_DISPLAY */
7457
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007458 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7459 wpas_periodic, global, NULL);
7460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007461 return global;
7462}
7463
7464
7465/**
7466 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7467 * @global: Pointer to global data from wpa_supplicant_init()
7468 * Returns: 0 after successful event loop run, -1 on failure
7469 *
7470 * This function starts the main event loop and continues running as long as
7471 * there are any remaining events. In most cases, this function is running as
7472 * long as the %wpa_supplicant process in still in use.
7473 */
7474int wpa_supplicant_run(struct wpa_global *global)
7475{
7476 struct wpa_supplicant *wpa_s;
7477
7478 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007479 (wpa_supplicant_daemon(global->params.pid_file) ||
7480 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481 return -1;
7482
Dmitry Shmidte4663042016-04-04 10:07:49 -07007483#ifdef CONFIG_MATCH_IFACE
7484 if (wpa_supplicant_match_existing(global))
7485 return -1;
7486#endif
7487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007488 if (global->params.wait_for_monitor) {
7489 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007490 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007491 wpa_supplicant_ctrl_iface_wait(
7492 wpa_s->ctrl_iface);
7493 }
7494
7495 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7496 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7497
7498 eloop_run();
7499
7500 return 0;
7501}
7502
7503
7504/**
7505 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7506 * @global: Pointer to global data from wpa_supplicant_init()
7507 *
7508 * This function is called to deinitialize %wpa_supplicant and to free all
7509 * allocated resources. Remaining network interfaces will also be removed.
7510 */
7511void wpa_supplicant_deinit(struct wpa_global *global)
7512{
7513 int i;
7514
7515 if (global == NULL)
7516 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007517
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007518 eloop_cancel_timeout(wpas_periodic, global, NULL);
7519
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007520#ifdef CONFIG_WIFI_DISPLAY
7521 wifi_display_deinit(global);
7522#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007523
7524 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007525 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007526
7527 if (global->ctrl_iface)
7528 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7529
7530 wpas_notify_supplicant_deinitialized(global);
7531
7532 eap_peer_unregister_methods();
7533#ifdef CONFIG_AP
7534 eap_server_unregister_methods();
7535#endif /* CONFIG_AP */
7536
7537 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7538 if (!global->drv_priv[i])
7539 continue;
7540 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7541 }
7542 os_free(global->drv_priv);
7543
7544 random_deinit();
7545
7546 eloop_destroy();
7547
7548 if (global->params.pid_file) {
7549 os_daemonize_terminate(global->params.pid_file);
7550 os_free(global->params.pid_file);
7551 }
7552 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007553 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007554 os_free(global->params.override_driver);
7555 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007556#ifdef CONFIG_MATCH_IFACE
7557 os_free(global->params.match_ifaces);
7558#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007559#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007560 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007561#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007562
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007563 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007564 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007565 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007567 os_free(global);
7568 wpa_debug_close_syslog();
7569 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007570 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007571}
7572
7573
7574void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7575{
7576 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7577 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7578 char country[3];
7579 country[0] = wpa_s->conf->country[0];
7580 country[1] = wpa_s->conf->country[1];
7581 country[2] = '\0';
7582 if (wpa_drv_set_country(wpa_s, country) < 0) {
7583 wpa_printf(MSG_ERROR, "Failed to set country code "
7584 "'%s'", country);
7585 }
7586 }
7587
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007588 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7589 wpas_init_ext_pw(wpa_s);
7590
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007591 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7592 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7593
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007594 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7595 struct wpa_driver_capa capa;
7596 int res = wpa_drv_get_capa(wpa_s, &capa);
7597
7598 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7599 wpa_printf(MSG_ERROR,
7600 "Failed to update wowlan_triggers to '%s'",
7601 wpa_s->conf->wowlan_triggers);
7602 }
7603
Hai Shalom81f62d82019-07-22 12:10:00 -07007604 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7605 wpa_supplicant_set_default_scan_ies(wpa_s);
7606
Hai Shalom899fcc72020-10-19 14:38:18 -07007607#ifdef CONFIG_BGSCAN
7608 /*
7609 * We default to global bgscan parameters only when per-network bgscan
7610 * parameters aren't set. Only bother resetting bgscan parameters if
7611 * this is the case.
7612 */
7613 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7614 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7615 wpa_s->wpa_state == WPA_COMPLETED)
7616 wpa_supplicant_reset_bgscan(wpa_s);
7617#endif /* CONFIG_BGSCAN */
7618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007619#ifdef CONFIG_WPS
7620 wpas_wps_update_config(wpa_s);
7621#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007622 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007623 wpa_s->conf->changed_parameters = 0;
7624}
7625
7626
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007627void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007628{
7629 int i;
7630
7631 for (i = 0; i < *num_freqs; i++) {
7632 if (freqs[i] == freq)
7633 return;
7634 }
7635
7636 freqs[*num_freqs] = freq;
7637 (*num_freqs)++;
7638}
7639
7640
7641static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7642{
7643 struct wpa_bss *bss, *cbss;
7644 const int max_freqs = 10;
7645 int *freqs;
7646 int num_freqs = 0;
7647
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007648 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007649 if (freqs == NULL)
7650 return NULL;
7651
7652 cbss = wpa_s->current_bss;
7653
7654 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7655 if (bss == cbss)
7656 continue;
7657 if (bss->ssid_len == cbss->ssid_len &&
7658 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007659 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007660 add_freq(freqs, &num_freqs, bss->freq);
7661 if (num_freqs == max_freqs)
7662 break;
7663 }
7664 }
7665
7666 if (num_freqs == 0) {
7667 os_free(freqs);
7668 freqs = NULL;
7669 }
7670
7671 return freqs;
7672}
7673
7674
7675void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7676{
7677 int timeout;
7678 int count;
7679 int *freqs = NULL;
7680
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007681 wpas_connect_work_done(wpa_s);
7682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007683 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007684 * Remove possible authentication timeout since the connection failed.
7685 */
7686 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7687
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007688 /*
Hai Shalom60840252021-02-19 19:02:11 -08007689 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007690 * generated based on local request to disconnect.
7691 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007692 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007693 wpa_s->own_disconnect_req = 0;
7694 wpa_dbg(wpa_s, MSG_DEBUG,
7695 "Ignore connection failure due to local request to disconnect");
7696 return;
7697 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007698 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007699 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7700 "indication since interface has been put into "
7701 "disconnected state");
7702 return;
7703 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007704 if (wpa_s->auto_reconnect_disabled) {
7705 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7706 "indication since auto connect is disabled");
7707 return;
7708 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007709
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007710 /*
Hai Shalom60840252021-02-19 19:02:11 -08007711 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007712 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007713 */
Hai Shalom60840252021-02-19 19:02:11 -08007714 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007715 if (count == 1 && wpa_s->current_bss) {
7716 /*
Hai Shalom60840252021-02-19 19:02:11 -08007717 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007718 * another BSS available for the same ESS, we should try that
7719 * next. Otherwise, we may as well try this one once more
7720 * before allowing other, likely worse, ESSes to be considered.
7721 */
7722 freqs = get_bss_freqs_in_ess(wpa_s);
7723 if (freqs) {
7724 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7725 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007726 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007727 /*
7728 * On the next scan, go through only the known channels
7729 * used in this ESS based on previous scans to speed up
7730 * common load balancing use case.
7731 */
7732 os_free(wpa_s->next_scan_freqs);
7733 wpa_s->next_scan_freqs = freqs;
7734 }
7735 }
7736
Hai Shalom899fcc72020-10-19 14:38:18 -07007737 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007738
Hai Shalom899fcc72020-10-19 14:38:18 -07007739 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007740 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7741 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007742 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007743 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007744 /*
7745 * Multiple consecutive connection failures mean that other APs are
7746 * either not available or have already been tried, so we can start
7747 * increasing the delay here to avoid constant scanning.
7748 */
7749 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007750 case 1:
7751 timeout = 100;
7752 break;
7753 case 2:
7754 timeout = 500;
7755 break;
7756 case 3:
7757 timeout = 1000;
7758 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007759 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007760 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007761 break;
7762 default:
7763 timeout = 10000;
7764 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007765 }
7766
Hai Shalom899fcc72020-10-19 14:38:18 -07007767 wpa_dbg(wpa_s, MSG_DEBUG,
7768 "Consecutive connection failures: %d --> request scan in %d ms",
7769 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771 /*
7772 * TODO: if more than one possible AP is available in scan results,
7773 * could try the other ones before requesting a new scan.
7774 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007775
7776 /* speed up the connection attempt with normal scan */
7777 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007778 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7779 1000 * (timeout % 1000));
7780}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007781
7782
Hai Shalomce48b4a2018-09-05 11:41:35 -07007783#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007784
7785void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7786{
7787 struct wpa_ssid *ssid = wpa_s->current_ssid;
7788 const u8 *realm, *username, *rrk;
7789 size_t realm_len, username_len, rrk_len;
7790 u16 next_seq_num;
7791
7792 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7793 * Check for ERP keys existing to limit when this can be done since
7794 * the rejection response is not protected and such triggers should
7795 * really not allow internal state to be modified unless required to
7796 * avoid significant issues in functionality. In addition, drop
7797 * externally configure PMKSA entries even without ERP keys since it
7798 * is possible for an external component to add PMKSA entries for FILS
7799 * authentication without restoring previously generated ERP keys.
7800 *
7801 * In this case, this is needed to allow recovery from cases where the
7802 * AP or authentication server has dropped PMKSAs and ERP keys. */
7803 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7804 return;
7805
7806 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7807 &username, &username_len,
7808 &realm, &realm_len, &next_seq_num,
7809 &rrk, &rrk_len) != 0 ||
7810 !realm) {
7811 wpa_dbg(wpa_s, MSG_DEBUG,
7812 "FILS: Drop external PMKSA cache entry");
7813 wpa_sm_aborted_external_cached(wpa_s->wpa);
7814 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7815 return;
7816 }
7817
7818 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7819 wpa_sm_aborted_cached(wpa_s->wpa);
7820 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7821}
7822
7823
Hai Shalomce48b4a2018-09-05 11:41:35 -07007824void fils_connection_failure(struct wpa_supplicant *wpa_s)
7825{
7826 struct wpa_ssid *ssid = wpa_s->current_ssid;
7827 const u8 *realm, *username, *rrk;
7828 size_t realm_len, username_len, rrk_len;
7829 u16 next_seq_num;
7830
7831 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7832 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7833 &username, &username_len,
7834 &realm, &realm_len, &next_seq_num,
7835 &rrk, &rrk_len) != 0 ||
7836 !realm)
7837 return;
7838
7839 wpa_hexdump_ascii(MSG_DEBUG,
7840 "FILS: Store last connection failure realm",
7841 realm, realm_len);
7842 os_free(wpa_s->last_con_fail_realm);
7843 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7844 if (wpa_s->last_con_fail_realm) {
7845 wpa_s->last_con_fail_realm_len = realm_len;
7846 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7847 }
7848}
7849#endif /* CONFIG_FILS */
7850
7851
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007852int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7853{
7854 return wpa_s->conf->ap_scan == 2 ||
7855 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7856}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007857
Dmitry Shmidt04949592012-07-19 12:16:46 -07007858
Gabriel Biren57ededa2021-09-03 16:08:50 +00007859#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007860int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7861 struct wpa_ssid *ssid,
7862 const char *field,
7863 const char *value)
7864{
7865#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007866 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007867
7868 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7869 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7870 (const u8 *) value, os_strlen(value));
7871
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007872 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007873 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007874#else /* IEEE8021X_EAPOL */
7875 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7876 return -1;
7877#endif /* IEEE8021X_EAPOL */
7878}
7879
7880int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7881 struct wpa_ssid *ssid,
7882 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007883 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007884{
7885#ifdef IEEE8021X_EAPOL
7886 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007887 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007888
7889 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007890 case WPA_CTRL_REQ_EAP_IDENTITY:
7891 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007892 os_free(eap->imsi_identity);
7893 if (value == NULL)
7894 return -1;
7895 identity = os_strchr(value, ':');
7896 if (identity == NULL) {
7897 /* plain identity */
7898 eap->identity = (u8 *)os_strdup(value);
7899 eap->identity_len = os_strlen(value);
7900 } else {
7901 /* have both plain identity and encrypted identity */
7902 imsi_identity = value;
7903 *identity++ = '\0';
7904 /* plain identity */
7905 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7906 eap->imsi_identity_len = strlen(imsi_identity);
7907 /* encrypted identity */
7908 eap->identity = (u8 *)dup_binstr(identity,
7909 value_len - strlen(imsi_identity) - 1);
7910 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7911 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007912 eap->pending_req_identity = 0;
7913 if (ssid == wpa_s->current_ssid)
7914 wpa_s->reassociate = 1;
7915 break;
7916 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007917 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007918 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007919 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007920 eap->pending_req_password = 0;
7921 if (ssid == wpa_s->current_ssid)
7922 wpa_s->reassociate = 1;
7923 break;
7924 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007925 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007926 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007927 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007928 eap->pending_req_new_password = 0;
7929 if (ssid == wpa_s->current_ssid)
7930 wpa_s->reassociate = 1;
7931 break;
7932 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007933 str_clear_free(eap->cert.pin);
7934 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007935 eap->pending_req_pin = 0;
7936 if (ssid == wpa_s->current_ssid)
7937 wpa_s->reassociate = 1;
7938 break;
7939 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007940 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007941 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007942 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007943 os_free(eap->pending_req_otp);
7944 eap->pending_req_otp = NULL;
7945 eap->pending_req_otp_len = 0;
7946 break;
7947 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007948 str_clear_free(eap->cert.private_key_passwd);
7949 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007950 eap->pending_req_passphrase = 0;
7951 if (ssid == wpa_s->current_ssid)
7952 wpa_s->reassociate = 1;
7953 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007954 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007955 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007956 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007957 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007958 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007959 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7960 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7961 return -1;
7962 ssid->mem_only_psk = 1;
7963 if (ssid->passphrase)
7964 wpa_config_update_psk(ssid);
7965 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7966 wpa_supplicant_req_scan(wpa_s, 0, 0);
7967 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007968 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7969 if (eap->pending_ext_cert_check != PENDING_CHECK)
7970 return -1;
7971 if (os_strcmp(value, "good") == 0)
7972 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7973 else if (os_strcmp(value, "bad") == 0)
7974 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7975 else
7976 return -1;
7977 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007978 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007979 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007980 return -1;
7981 }
7982
7983 return 0;
7984#else /* IEEE8021X_EAPOL */
7985 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7986 return -1;
7987#endif /* IEEE8021X_EAPOL */
7988}
Gabriel Biren57ededa2021-09-03 16:08:50 +00007989#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007990
7991
7992int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7993{
Hai Shalomfdcde762020-04-02 11:19:20 -07007994#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007995 int i;
7996 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007997#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007998
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007999 if (wpa_s->p2p_mgmt)
8000 return 1; /* no normal network profiles on p2p_mgmt interface */
8001
Dmitry Shmidt04949592012-07-19 12:16:46 -07008002 if (ssid == NULL)
8003 return 1;
8004
8005 if (ssid->disabled)
8006 return 1;
8007
Hai Shalomfdcde762020-04-02 11:19:20 -07008008#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008009 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008010 drv_enc = wpa_s->drv_enc;
8011 else
8012 drv_enc = (unsigned int) -1;
8013
8014 for (i = 0; i < NUM_WEP_KEYS; i++) {
8015 size_t len = ssid->wep_key_len[i];
8016 if (len == 0)
8017 continue;
8018 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8019 continue;
8020 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8021 continue;
8022 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8023 continue;
8024 return 1; /* invalid WEP key */
8025 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008026#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008027
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008028 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008029 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008030 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008031 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008032 return 1;
8033
Dmitry Shmidt04949592012-07-19 12:16:46 -07008034 return 0;
8035}
8036
8037
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008038int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8039{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008040 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8041 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8042 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8043 /*
8044 * Driver does not support BIP -- ignore pmf=1 default
8045 * since the connection with PMF would fail and the
8046 * configuration does not require PMF to be enabled.
8047 */
8048 return NO_MGMT_FRAME_PROTECTION;
8049 }
8050
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008051 if (ssid &&
8052 (ssid->key_mgmt &
8053 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8054 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8055 /*
8056 * Do not use the default PMF value for non-RSN networks
8057 * since PMF is available only with RSN and pmf=2
8058 * configuration would otherwise prevent connections to
8059 * all open networks.
8060 */
8061 return NO_MGMT_FRAME_PROTECTION;
8062 }
8063
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008064 return wpa_s->conf->pmf;
8065 }
8066
8067 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008068}
8069
8070
Hai Shalomc1a21442022-02-04 13:43:00 -08008071int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8072{
8073 if (wpa_s->current_ssid == NULL ||
8074 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8075 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8076 return 0;
8077 return wpa_sm_pmf_enabled(wpa_s->wpa);
8078}
8079
8080
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008081int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008082{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008083 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008084 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008085 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008086 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008087 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008088}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008089
8090
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008091void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008092{
8093 struct wpa_ssid *ssid = wpa_s->current_ssid;
8094 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008095 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008096
8097 if (ssid == NULL) {
8098 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8099 "SSID block");
8100 return;
8101 }
8102
8103 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8104 return;
8105
8106 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008107
8108#ifdef CONFIG_P2P
8109 if (ssid->p2p_group &&
8110 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8111 /*
8112 * Skip the wait time since there is a short timeout on the
8113 * connection to a P2P group.
8114 */
8115 return;
8116 }
8117#endif /* CONFIG_P2P */
8118
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008119 if (ssid->auth_failures > 50)
8120 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008121 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008122 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008123 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008124 dur = 90;
8125 else if (ssid->auth_failures > 3)
8126 dur = 60;
8127 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008128 dur = 30;
8129 else if (ssid->auth_failures > 1)
8130 dur = 20;
8131 else
8132 dur = 10;
8133
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008134 if (ssid->auth_failures > 1 &&
8135 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8136 dur += os_random() % (ssid->auth_failures * 10);
8137
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008138 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008139 if (now.sec + dur <= ssid->disabled_until.sec)
8140 return;
8141
8142 ssid->disabled_until.sec = now.sec + dur;
8143
8144 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008145 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008146 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008147 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008148
8149 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8150 int msg_len = snprintf(NULL, 0, format_str,
8151 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8152 ssid->auth_failures, dur, reason) + 1;
8153 char *msg = os_malloc(msg_len);
8154 snprintf(msg, msg_len, format_str,
8155 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8156 ssid->auth_failures, dur, reason);
8157 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8158 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008159}
8160
8161
8162void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8163 struct wpa_ssid *ssid, int clear_failures)
8164{
8165 if (ssid == NULL)
8166 return;
8167
8168 if (ssid->disabled_until.sec) {
8169 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8170 "id=%d ssid=\"%s\"",
8171 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8172 }
8173 ssid->disabled_until.sec = 0;
8174 ssid->disabled_until.usec = 0;
8175 if (clear_failures)
8176 ssid->auth_failures = 0;
8177}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008178
8179
8180int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8181{
8182 size_t i;
8183
8184 if (wpa_s->disallow_aps_bssid == NULL)
8185 return 0;
8186
8187 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8188 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8189 bssid, ETH_ALEN) == 0)
8190 return 1;
8191 }
8192
8193 return 0;
8194}
8195
8196
8197int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8198 size_t ssid_len)
8199{
8200 size_t i;
8201
8202 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8203 return 0;
8204
8205 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8206 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8207 if (ssid_len == s->ssid_len &&
8208 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8209 return 1;
8210 }
8211
8212 return 0;
8213}
8214
8215
8216/**
8217 * wpas_request_connection - Request a new connection
8218 * @wpa_s: Pointer to the network interface
8219 *
8220 * This function is used to request a new connection to be found. It will mark
8221 * the interface to allow reassociation and request a new scan to find a
8222 * suitable network to connect to.
8223 */
8224void wpas_request_connection(struct wpa_supplicant *wpa_s)
8225{
8226 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008227 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008228 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008229 wpa_s->disconnected = 0;
8230 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008231 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008232
8233 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8234 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008235 else
8236 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008237}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008238
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008239
Roshan Pius02242d72016-08-09 15:31:48 -07008240/**
8241 * wpas_request_disconnection - Request disconnection
8242 * @wpa_s: Pointer to the network interface
8243 *
8244 * This function is used to request disconnection from the currently connected
8245 * network. This will stop any ongoing scans and initiate deauthentication.
8246 */
8247void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8248{
8249#ifdef CONFIG_SME
8250 wpa_s->sme.prev_bssid_set = 0;
8251#endif /* CONFIG_SME */
8252 wpa_s->reassociate = 0;
8253 wpa_s->disconnected = 1;
8254 wpa_supplicant_cancel_sched_scan(wpa_s);
8255 wpa_supplicant_cancel_scan(wpa_s);
8256 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8257 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008258 radio_remove_works(wpa_s, "connect", 0);
8259 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008260 wpa_s->roam_in_progress = false;
8261#ifdef CONFIG_WNM
8262 wpa_s->bss_trans_mgmt_in_progress = false;
8263#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008264}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008265
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008266
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008267void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8268 struct wpa_used_freq_data *freqs_data,
8269 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008270{
8271 unsigned int i;
8272
8273 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8274 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008275 for (i = 0; i < len; i++) {
8276 struct wpa_used_freq_data *cur = &freqs_data[i];
8277 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8278 i, cur->freq, cur->flags);
8279 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008280}
8281
8282
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008283/*
8284 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008285 * are using the same radio as the current interface, and in addition, get
8286 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008287 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008288int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8289 struct wpa_used_freq_data *freqs_data,
8290 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008291{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008292 struct wpa_supplicant *ifs;
8293 u8 bssid[ETH_ALEN];
8294 int freq;
8295 unsigned int idx = 0, i;
8296
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008297 wpa_dbg(wpa_s, MSG_DEBUG,
8298 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008299 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008300
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008301 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8302 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008303 if (idx == len)
8304 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008305
8306 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8307 continue;
8308
8309 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008310 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8311 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008312 freq = ifs->current_ssid->frequency;
8313 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8314 freq = ifs->assoc_freq;
8315 else
8316 continue;
8317
8318 /* Hold only distinct freqs */
8319 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008320 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008321 break;
8322
8323 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008324 freqs_data[idx++].freq = freq;
8325
8326 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008327 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008328 WPA_FREQ_USED_BY_P2P_CLIENT :
8329 WPA_FREQ_USED_BY_INFRA_STATION;
8330 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008331 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008332
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008333 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008334 return idx;
8335}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008336
8337
8338/*
8339 * Find the operating frequencies of any of the virtual interfaces that
8340 * are using the same radio as the current interface.
8341 */
8342int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8343 int *freq_array, unsigned int len)
8344{
8345 struct wpa_used_freq_data *freqs_data;
8346 int num, i;
8347
8348 os_memset(freq_array, 0, sizeof(int) * len);
8349
8350 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8351 if (!freqs_data)
8352 return -1;
8353
8354 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8355 for (i = 0; i < num; i++)
8356 freq_array[i] = freqs_data[i].freq;
8357
8358 os_free(freqs_data);
8359
8360 return num;
8361}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008362
8363
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008364struct wpa_supplicant *
8365wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8366{
8367 switch (frame) {
8368#ifdef CONFIG_P2P
8369 case VENDOR_ELEM_PROBE_REQ_P2P:
8370 case VENDOR_ELEM_PROBE_RESP_P2P:
8371 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8372 case VENDOR_ELEM_BEACON_P2P_GO:
8373 case VENDOR_ELEM_P2P_PD_REQ:
8374 case VENDOR_ELEM_P2P_PD_RESP:
8375 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8376 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8377 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8378 case VENDOR_ELEM_P2P_INV_REQ:
8379 case VENDOR_ELEM_P2P_INV_RESP:
8380 case VENDOR_ELEM_P2P_ASSOC_REQ:
8381 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008382 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008383#endif /* CONFIG_P2P */
8384 default:
8385 return wpa_s;
8386 }
8387}
8388
8389
8390void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8391{
8392 unsigned int i;
8393 char buf[30];
8394
8395 wpa_printf(MSG_DEBUG, "Update vendor elements");
8396
8397 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8398 if (wpa_s->vendor_elem[i]) {
8399 int res;
8400
8401 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8402 if (!os_snprintf_error(sizeof(buf), res)) {
8403 wpa_hexdump_buf(MSG_DEBUG, buf,
8404 wpa_s->vendor_elem[i]);
8405 }
8406 }
8407 }
8408
8409#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008410 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008411 wpa_s->global->p2p &&
8412 !wpa_s->global->p2p_disabled)
8413 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8414#endif /* CONFIG_P2P */
8415}
8416
8417
8418int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8419 const u8 *elem, size_t len)
8420{
8421 u8 *ie, *end;
8422
8423 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8424 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8425
8426 for (; ie + 1 < end; ie += 2 + ie[1]) {
8427 if (ie + len > end)
8428 break;
8429 if (os_memcmp(ie, elem, len) != 0)
8430 continue;
8431
8432 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8433 wpabuf_free(wpa_s->vendor_elem[frame]);
8434 wpa_s->vendor_elem[frame] = NULL;
8435 } else {
8436 os_memmove(ie, ie + len, end - (ie + len));
8437 wpa_s->vendor_elem[frame]->used -= len;
8438 }
8439 wpas_vendor_elem_update(wpa_s);
8440 return 0;
8441 }
8442
8443 return -1;
8444}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008445
8446
8447struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008448 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008449 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008450{
8451 u16 i;
8452
Hai Shalomc1a21442022-02-04 13:43:00 -08008453 if (!modes)
8454 return NULL;
8455
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008456 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008457 if (modes[i].mode != mode ||
8458 !modes[i].num_channels || !modes[i].channels)
8459 continue;
8460 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8461 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008462 return &modes[i];
8463 }
8464
8465 return NULL;
8466}
8467
8468
Hai Shalomc1a21442022-02-04 13:43:00 -08008469struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8470 u16 num_modes, int freq)
8471{
8472 int i, j;
8473
8474 for (i = 0; i < num_modes; i++) {
8475 for (j = 0; j < modes[i].num_channels; j++) {
8476 if (freq == modes[i].channels[j].freq)
8477 return &modes[i];
8478 }
8479 }
8480
8481 return NULL;
8482}
8483
8484
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008485static struct
8486wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8487 const u8 *bssid)
8488{
8489 struct wpa_bss_tmp_disallowed *bss;
8490
8491 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8492 struct wpa_bss_tmp_disallowed, list) {
8493 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8494 return bss;
8495 }
8496
8497 return NULL;
8498}
8499
8500
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008501static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8502{
8503 struct wpa_bss_tmp_disallowed *tmp;
8504 unsigned int num_bssid = 0;
8505 u8 *bssids;
8506 int ret;
8507
8508 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8509 if (!bssids)
8510 return -1;
8511 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8512 struct wpa_bss_tmp_disallowed, list) {
8513 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8514 ETH_ALEN);
8515 num_bssid++;
8516 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008517 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008518 os_free(bssids);
8519 return ret;
8520}
8521
8522
8523static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8524{
8525 struct wpa_supplicant *wpa_s = eloop_ctx;
8526 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8527
8528 /* Make sure the bss is not already freed */
8529 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8530 struct wpa_bss_tmp_disallowed, list) {
8531 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008532 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008533 wpa_set_driver_tmp_disallow_list(wpa_s);
8534 break;
8535 }
8536 }
8537}
8538
8539
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008540void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008541 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008542{
8543 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008544
8545 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8546 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008547 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008548 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008549 }
8550
8551 bss = os_malloc(sizeof(*bss));
8552 if (!bss) {
8553 wpa_printf(MSG_DEBUG,
8554 "Failed to allocate memory for temp disallow BSS");
8555 return;
8556 }
8557
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008558 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8559 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008560 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008561
8562finish:
8563 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008564 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8565 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008566}
8567
8568
Hai Shalom74f70d42019-02-11 14:42:39 -08008569int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8570 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008571{
Hai Shalom74f70d42019-02-11 14:42:39 -08008572 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008573
8574 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8575 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008576 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8577 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008578 break;
8579 }
8580 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008581 if (!disallowed)
8582 return 0;
8583
8584 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008585 bss->level > disallowed->rssi_threshold) {
8586 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8587 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008588 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008589 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008590
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008591 return 1;
8592}
Hai Shalom81f62d82019-07-22 12:10:00 -07008593
8594
8595int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8596 unsigned int type, const u8 *addr,
8597 const u8 *mask)
8598{
8599 if ((addr && !mask) || (!addr && mask)) {
8600 wpa_printf(MSG_INFO,
8601 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8602 return -1;
8603 }
8604
8605 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8606 wpa_printf(MSG_INFO,
8607 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8608 return -1;
8609 }
8610
8611 if (type & MAC_ADDR_RAND_SCAN) {
8612 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8613 addr, mask))
8614 return -1;
8615 }
8616
8617 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8618 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8619 addr, mask))
8620 return -1;
8621
8622 if (wpa_s->sched_scanning && !wpa_s->pno)
8623 wpas_scan_restart_sched_scan(wpa_s);
8624 }
8625
8626 if (type & MAC_ADDR_RAND_PNO) {
8627 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8628 addr, mask))
8629 return -1;
8630
8631 if (wpa_s->pno) {
8632 wpas_stop_pno(wpa_s);
8633 wpas_start_pno(wpa_s);
8634 }
8635 }
8636
8637 return 0;
8638}
8639
8640
8641int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8642 unsigned int type)
8643{
8644 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8645 if (wpa_s->pno) {
8646 if (type & MAC_ADDR_RAND_PNO) {
8647 wpas_stop_pno(wpa_s);
8648 wpas_start_pno(wpa_s);
8649 }
8650 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8651 wpas_scan_restart_sched_scan(wpa_s);
8652 }
8653
8654 return 0;
8655}
Hai Shalomfdcde762020-04-02 11:19:20 -07008656
8657
8658int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8659 struct wpa_signal_info *si)
8660{
8661 int res;
8662
8663 if (!wpa_s->driver->signal_poll)
8664 return -1;
8665
8666 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8667
8668#ifdef CONFIG_TESTING_OPTIONS
8669 if (res == 0) {
8670 struct driver_signal_override *dso;
8671
8672 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8673 struct driver_signal_override, list) {
8674 if (os_memcmp(wpa_s->bssid, dso->bssid,
8675 ETH_ALEN) != 0)
8676 continue;
8677 wpa_printf(MSG_DEBUG,
8678 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8679 si->current_signal,
8680 dso->si_current_signal,
8681 si->avg_signal,
8682 dso->si_avg_signal,
8683 si->avg_beacon_signal,
8684 dso->si_avg_beacon_signal,
8685 si->current_noise,
8686 dso->si_current_noise);
8687 si->current_signal = dso->si_current_signal;
8688 si->avg_signal = dso->si_avg_signal;
8689 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8690 si->current_noise = dso->si_current_noise;
8691 break;
8692 }
8693 }
8694#endif /* CONFIG_TESTING_OPTIONS */
8695
8696 return res;
8697}
8698
8699
8700struct wpa_scan_results *
8701wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8702{
8703 struct wpa_scan_results *scan_res;
8704#ifdef CONFIG_TESTING_OPTIONS
8705 size_t idx;
8706#endif /* CONFIG_TESTING_OPTIONS */
8707
8708 if (!wpa_s->driver->get_scan_results2)
8709 return NULL;
8710
8711 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8712
8713#ifdef CONFIG_TESTING_OPTIONS
8714 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8715 struct driver_signal_override *dso;
8716 struct wpa_scan_res *res = scan_res->res[idx];
8717
8718 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8719 struct driver_signal_override, list) {
8720 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8721 continue;
8722 wpa_printf(MSG_DEBUG,
8723 "Override driver scan signal level %d->%d for "
8724 MACSTR,
8725 res->level, dso->scan_level,
8726 MAC2STR(res->bssid));
8727 res->flags |= WPA_SCAN_QUAL_INVALID;
8728 if (dso->scan_level < 0)
8729 res->flags |= WPA_SCAN_LEVEL_DBM;
8730 else
8731 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8732 res->level = dso->scan_level;
8733 break;
8734 }
8735 }
8736#endif /* CONFIG_TESTING_OPTIONS */
8737
8738 return scan_res;
8739}