blob: 05766b5b7f8bb2abbfc9b378bae564f7592aae29 [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);
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001718 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1719 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001720#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001721
1722 /* Extended Key ID is only supported in infrastructure BSS so far */
1723 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1724 (ssid->proto & WPA_PROTO_RSN) &&
1725 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1726 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1727 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1728 int use_ext_key_id = 0;
1729
1730 wpa_msg(wpa_s, MSG_DEBUG,
1731 "WPA: Enable Extended Key ID support");
1732 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1733 wpa_s->conf->extended_key_id);
1734 if (bss_rsn &&
1735 wpa_s->conf->extended_key_id &&
1736 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1737 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1738 use_ext_key_id = 1;
1739 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1740 use_ext_key_id);
1741 } else {
1742 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1743 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1744 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745
1746 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1747 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1748 return -1;
1749 }
1750
Hai Shalomc3565922019-10-28 11:58:20 -07001751 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1752 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1753 &wpa_s->rsnxe_len)) {
1754 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1755 return -1;
1756 }
1757
Hai Shalom021b0b52019-04-10 11:17:58 -07001758 if (0) {
1759#ifdef CONFIG_DPP
1760 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1761 /* Use PMK from DPP network introduction (PMKSA entry) */
1762 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001763#ifdef CONFIG_DPP2
1764 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1765#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001766#endif /* CONFIG_DPP */
1767 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001768 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001769 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001770
Roshan Pius3a1667e2018-07-03 15:17:14 -07001771 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1772 WPA_KEY_MGMT_FT_PSK |
1773 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1774
1775 if (ssid->psk_set && !sae_only) {
1776 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1777 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001778 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1779 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001780 psk_set = 1;
1781 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001782
Roshan Pius3a1667e2018-07-03 15:17:14 -07001783 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1784 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001785 psk_set = 1;
1786
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001787#ifndef CONFIG_NO_PBKDF2
1788 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001789 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001790 u8 psk[PMK_LEN];
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001791
1792 if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
1793 bss->ssid_len,
1794 4096, psk, PMK_LEN) != 0) {
1795 wpa_msg(wpa_s, MSG_WARNING,
1796 "Error in pbkdf2_sha1()");
1797 return -1;
1798 }
1799 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001800 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001801 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001802 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001803 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001804 }
1805#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001806#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001807 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1809 ssid->ext_psk);
1810 char pw_str[64 + 1];
1811 u8 psk[PMK_LEN];
1812
1813 if (pw == NULL) {
1814 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1815 "found from external storage");
1816 return -1;
1817 }
1818
1819 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1820 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1821 "PSK length %d in external storage",
1822 (int) wpabuf_len(pw));
1823 ext_password_free(pw);
1824 return -1;
1825 }
1826
1827 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1828 pw_str[wpabuf_len(pw)] = '\0';
1829
1830#ifndef CONFIG_NO_PBKDF2
1831 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1832 {
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001833 if (pbkdf2_sha1(pw_str, bss->ssid,
1834 bss->ssid_len,
1835 4096, psk, PMK_LEN) != 0) {
1836 wpa_msg(wpa_s, MSG_WARNING,
1837 "Error in pbkdf2_sha1()");
1838 ext_password_free(pw);
1839 return -1;
1840 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001841 os_memset(pw_str, 0, sizeof(pw_str));
1842 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1843 "external passphrase)",
1844 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001845 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1846 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001847 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001848 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001849 } else
1850#endif /* CONFIG_NO_PBKDF2 */
1851 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1852 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1853 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1854 "Invalid PSK hex string");
1855 os_memset(pw_str, 0, sizeof(pw_str));
1856 ext_password_free(pw);
1857 return -1;
1858 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001859 wpa_hexdump_key(MSG_MSGDUMP,
1860 "PSK (from external PSK)",
1861 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001862 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1863 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001864 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001865 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001866 } else {
1867 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1868 "PSK available");
1869 os_memset(pw_str, 0, sizeof(pw_str));
1870 ext_password_free(pw);
1871 return -1;
1872 }
1873
1874 os_memset(pw_str, 0, sizeof(pw_str));
1875 ext_password_free(pw);
1876 }
1877#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001878
1879 if (!psk_set) {
1880 wpa_msg(wpa_s, MSG_INFO,
1881 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001883 return -1;
1884 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885#ifdef CONFIG_OWE
1886 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1887 /* OWE Diffie-Hellman exchange in (Re)Association
1888 * Request/Response frames set the PMK, so do not override it
1889 * here. */
1890#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001891 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1893
Hai Shalomfdcde762020-04-02 11:19:20 -07001894 if (ssid->mode != WPAS_MODE_IBSS &&
1895 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1896 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1897 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1898 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1899 wpa_msg(wpa_s, MSG_INFO,
1900 "Disable PTK0 rekey support - replaced with reconnect");
1901 wpa_s->deny_ptk0_rekey = 1;
1902 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1903 } else {
1904 wpa_s->deny_ptk0_rekey = 0;
1905 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1906 }
1907
Vinayak Yadawad14709082022-03-17 14:25:11 +05301908#ifdef CONFIG_DRIVER_NL80211_BRCM
1909 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09001910 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
1911 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09001912 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
1913 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05301914 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1915 wpa_dbg(wpa_s, MSG_INFO,
1916 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1917 }
1918#endif /* CONFIG_DRIVER_NL80211_BRCM */
1919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001920 return 0;
1921}
1922
1923
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001924static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1925{
Hai Shalomc1a21442022-02-04 13:43:00 -08001926 bool scs = true, mscs = true;
1927
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001928 *pos = 0x00;
1929
1930 switch (idx) {
1931 case 0: /* Bits 0-7 */
1932 break;
1933 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001934 if (wpa_s->conf->coloc_intf_reporting) {
1935 /* Bit 13 - Collocated Interference Reporting */
1936 *pos |= 0x20;
1937 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001938 break;
1939 case 2: /* Bits 16-23 */
1940#ifdef CONFIG_WNM
1941 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001942 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001943 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001944#endif /* CONFIG_WNM */
1945 break;
1946 case 3: /* Bits 24-31 */
1947#ifdef CONFIG_WNM
1948 *pos |= 0x02; /* Bit 25 - SSID List */
1949#endif /* CONFIG_WNM */
1950#ifdef CONFIG_INTERWORKING
1951 if (wpa_s->conf->interworking)
1952 *pos |= 0x80; /* Bit 31 - Interworking */
1953#endif /* CONFIG_INTERWORKING */
1954 break;
1955 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001956#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001957 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001958 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001959#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001960 break;
1961 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001962#ifdef CONFIG_HS20
1963 if (wpa_s->conf->hs20)
1964 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1965#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001966#ifdef CONFIG_MBO
1967 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1968#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001969 break;
1970 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001971#ifdef CONFIG_TESTING_OPTIONS
1972 if (wpa_s->disable_scs_support)
1973 scs = false;
1974#endif /* CONFIG_TESTING_OPTIONS */
1975 if (scs)
1976 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001977 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001978 case 7: /* Bits 56-63 */
1979 break;
1980 case 8: /* Bits 64-71 */
1981 if (wpa_s->conf->ftm_responder)
1982 *pos |= 0x40; /* Bit 70 - FTM responder */
1983 if (wpa_s->conf->ftm_initiator)
1984 *pos |= 0x80; /* Bit 71 - FTM initiator */
1985 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001986 case 9: /* Bits 72-79 */
1987#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001988 if (!wpa_s->disable_fils)
1989 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001990#endif /* CONFIG_FILS */
1991 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001992 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001993#ifdef CONFIG_TESTING_OPTIONS
1994 if (wpa_s->disable_mscs_support)
1995 mscs = false;
1996#endif /* CONFIG_TESTING_OPTIONS */
1997 if (mscs)
1998 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001999 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002000 }
2001}
2002
2003
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002004int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002005{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002006 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002007 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002008
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002009 if (len < wpa_s->extended_capa_len)
2010 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002011 if (buflen < (size_t) len + 2) {
2012 wpa_printf(MSG_INFO,
2013 "Not enough room for building extended capabilities element");
2014 return -1;
2015 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002016
2017 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002018 *pos++ = len;
2019 for (i = 0; i < len; i++, pos++) {
2020 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002021
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002022 if (i < wpa_s->extended_capa_len) {
2023 *pos &= ~wpa_s->extended_capa_mask[i];
2024 *pos |= wpa_s->extended_capa[i];
2025 }
2026 }
2027
2028 while (len > 0 && buf[1 + len] == 0) {
2029 len--;
2030 buf[1] = len;
2031 }
2032 if (len == 0)
2033 return 0;
2034
2035 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002036}
2037
2038
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002039static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2040 struct wpa_bss *test_bss)
2041{
2042 struct wpa_bss *bss;
2043
2044 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2045 if (bss == test_bss)
2046 return 1;
2047 }
2048
2049 return 0;
2050}
2051
2052
2053static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2054 struct wpa_ssid *test_ssid)
2055{
2056 struct wpa_ssid *ssid;
2057
2058 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2059 if (ssid == test_ssid)
2060 return 1;
2061 }
2062
2063 return 0;
2064}
2065
2066
2067int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2068 struct wpa_ssid *test_ssid)
2069{
2070 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2071 return 0;
2072
2073 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2074}
2075
2076
2077void wpas_connect_work_free(struct wpa_connect_work *cwork)
2078{
2079 if (cwork == NULL)
2080 return;
2081 os_free(cwork);
2082}
2083
2084
2085void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2086{
2087 struct wpa_connect_work *cwork;
2088 struct wpa_radio_work *work = wpa_s->connect_work;
2089
2090 if (!work)
2091 return;
2092
2093 wpa_s->connect_work = NULL;
2094 cwork = work->ctx;
2095 work->ctx = NULL;
2096 wpas_connect_work_free(cwork);
2097 radio_work_done(work);
2098}
2099
2100
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002101int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2102{
2103 struct os_reltime now;
2104 u8 addr[ETH_ALEN];
2105
2106 os_get_reltime(&now);
2107 if (wpa_s->last_mac_addr_style == style &&
2108 wpa_s->last_mac_addr_change.sec != 0 &&
2109 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2110 wpa_s->conf->rand_addr_lifetime)) {
2111 wpa_msg(wpa_s, MSG_DEBUG,
2112 "Previously selected random MAC address has not yet expired");
2113 return 0;
2114 }
2115
2116 switch (style) {
2117 case 1:
2118 if (random_mac_addr(addr) < 0)
2119 return -1;
2120 break;
2121 case 2:
2122 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2123 if (random_mac_addr_keep_oui(addr) < 0)
2124 return -1;
2125 break;
2126 default:
2127 return -1;
2128 }
2129
2130 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2131 wpa_msg(wpa_s, MSG_INFO,
2132 "Failed to set random MAC address");
2133 return -1;
2134 }
2135
2136 os_get_reltime(&wpa_s->last_mac_addr_change);
2137 wpa_s->mac_addr_changed = 1;
2138 wpa_s->last_mac_addr_style = style;
2139
2140 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2141 wpa_msg(wpa_s, MSG_INFO,
2142 "Could not update MAC address information");
2143 return -1;
2144 }
2145
2146 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2147 MAC2STR(addr));
2148
2149 return 0;
2150}
2151
2152
2153int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2154{
2155 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2156 !wpa_s->conf->preassoc_mac_addr)
2157 return 0;
2158
2159 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2160}
2161
2162
Hai Shalomc3565922019-10-28 11:58:20 -07002163static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2164{
2165#ifdef CONFIG_SAE
2166 int *groups = conf->sae_groups;
2167 int default_groups[] = { 19, 20, 21, 0 };
2168 const char *password;
2169
2170 if (!groups || groups[0] <= 0)
2171 groups = default_groups;
2172
2173 password = ssid->sae_password;
2174 if (!password)
2175 password = ssid->passphrase;
2176
Hai Shalom899fcc72020-10-19 14:38:18 -07002177 if (!password ||
2178 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2179 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002180 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002181 /* PT derivation not needed */
2182 sae_deinit_pt(ssid->pt);
2183 ssid->pt = NULL;
2184 return;
2185 }
2186
2187 if (ssid->pt)
2188 return; /* PT already derived */
2189 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2190 (const u8 *) password, os_strlen(password),
2191 ssid->sae_password_id);
2192#endif /* CONFIG_SAE */
2193}
2194
2195
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002196static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2197{
2198#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2199 os_free(wpa_s->sme.sae_rejected_groups);
2200 wpa_s->sme.sae_rejected_groups = NULL;
2201#ifdef CONFIG_TESTING_OPTIONS
2202 if (wpa_s->extra_sae_rejected_groups) {
2203 int i, *groups = wpa_s->extra_sae_rejected_groups;
2204
2205 for (i = 0; groups[i]; i++) {
2206 wpa_printf(MSG_DEBUG,
2207 "TESTING: Indicate rejection of an extra SAE group %d",
2208 groups[i]);
2209 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2210 groups[i]);
2211 }
2212 }
2213#endif /* CONFIG_TESTING_OPTIONS */
2214#endif /* CONFIG_SAE && CONFIG_SME */
2215}
2216
2217
Hai Shalom60840252021-02-19 19:02:11 -08002218int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2219{
2220 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2221 wpa_msg(wpa_s, MSG_INFO,
2222 "Could not restore permanent MAC address");
2223 return -1;
2224 }
2225 wpa_s->mac_addr_changed = 0;
2226 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2227 wpa_msg(wpa_s, MSG_INFO,
2228 "Could not update MAC address information");
2229 return -1;
2230 }
2231 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2232 return 0;
2233}
2234
2235
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002236static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238/**
2239 * wpa_supplicant_associate - Request association
2240 * @wpa_s: Pointer to wpa_supplicant data
2241 * @bss: Scan results for the selected BSS, or %NULL if not available
2242 * @ssid: Configuration data for the selected network
2243 *
2244 * This function is used to request %wpa_supplicant to associate with a BSS.
2245 */
2246void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2247 struct wpa_bss *bss, struct wpa_ssid *ssid)
2248{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002249 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002250 int rand_style;
2251
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002252 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002253 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002254
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002255 /*
2256 * If we are starting a new connection, any previously pending EAPOL
2257 * RX cannot be valid anymore.
2258 */
2259 wpabuf_free(wpa_s->pending_eapol_rx);
2260 wpa_s->pending_eapol_rx = NULL;
2261
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002262 if (ssid->mac_addr == -1)
2263 rand_style = wpa_s->conf->mac_addr;
2264 else
2265 rand_style = ssid->mac_addr;
2266
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002267 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002268 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002269 wmm_ac_clear_saved_tspecs(wpa_s);
2270 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002271 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002272#ifdef CONFIG_TESTING_OPTIONS
2273 wpa_s->testing_resend_assoc = 0;
2274#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002275
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002276 if (wpa_s->last_ssid == ssid) {
2277 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002278 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002279 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2280 wmm_ac_save_tspecs(wpa_s);
2281 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002282 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2283 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002284 }
Hai Shalomc3565922019-10-28 11:58:20 -07002285 } else {
2286#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002287 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002288#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002290#ifdef CONFIG_SAE
2291 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2292#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002293
2294 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002295 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2296 return;
2297 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002298 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002299 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002300 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002301 }
2302 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303
2304#ifdef CONFIG_IBSS_RSN
2305 ibss_rsn_deinit(wpa_s->ibss_rsn);
2306 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002307#else /* CONFIG_IBSS_RSN */
2308 if (ssid->mode == WPAS_MODE_IBSS &&
2309 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2310 wpa_msg(wpa_s, MSG_INFO,
2311 "IBSS RSN not supported in the build");
2312 return;
2313 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314#endif /* CONFIG_IBSS_RSN */
2315
2316 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2317 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2318#ifdef CONFIG_AP
2319 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2320 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2321 "mode");
2322 return;
2323 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002324 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2325 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002326 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2327 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002328 return;
2329 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330 wpa_s->current_bss = bss;
2331#else /* CONFIG_AP */
2332 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2333 "the build");
2334#endif /* CONFIG_AP */
2335 return;
2336 }
2337
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002338 if (ssid->mode == WPAS_MODE_MESH) {
2339#ifdef CONFIG_MESH
2340 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2341 wpa_msg(wpa_s, MSG_INFO,
2342 "Driver does not support mesh mode");
2343 return;
2344 }
2345 if (bss)
2346 ssid->frequency = bss->freq;
2347 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2348 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2349 return;
2350 }
2351 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002352#else /* CONFIG_MESH */
2353 wpa_msg(wpa_s, MSG_ERROR,
2354 "mesh mode support not included in the build");
2355#endif /* CONFIG_MESH */
2356 return;
2357 }
2358
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002359 /*
2360 * Set WPA state machine configuration to match the selected network now
2361 * so that the information is available before wpas_start_assoc_cb()
2362 * gets called. This is needed at least for RSN pre-authentication where
2363 * candidate APs are added to a list based on scan result processing
2364 * before completion of the first association.
2365 */
2366 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2367
2368#ifdef CONFIG_DPP
2369 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2370 return;
2371#endif /* CONFIG_DPP */
2372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373#ifdef CONFIG_TDLS
2374 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002375 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376#endif /* CONFIG_TDLS */
2377
Hai Shalomc3565922019-10-28 11:58:20 -07002378#ifdef CONFIG_MBO
2379 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2380#endif /* CONFIG_MBO */
2381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002383 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 sme_authenticate(wpa_s, bss, ssid);
2385 return;
2386 }
2387
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002388 if (wpa_s->connect_work) {
2389 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2390 return;
2391 }
2392
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002393 if (radio_work_pending(wpa_s, "connect")) {
2394 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2395 return;
2396 }
2397
Dmitry Shmidt29333592017-01-09 12:27:11 -08002398#ifdef CONFIG_SME
2399 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2400 /* Clear possibly set auth_alg, if any, from last attempt. */
2401 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2402 }
2403#endif /* CONFIG_SME */
2404
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002405 wpas_abort_ongoing_scan(wpa_s);
2406
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002407 cwork = os_zalloc(sizeof(*cwork));
2408 if (cwork == NULL)
2409 return;
2410
2411 cwork->bss = bss;
2412 cwork->ssid = ssid;
2413
2414 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2415 wpas_start_assoc_cb, cwork) < 0) {
2416 os_free(cwork);
2417 }
2418}
2419
2420
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002421static int bss_is_ibss(struct wpa_bss *bss)
2422{
2423 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2424 IEEE80211_CAP_IBSS;
2425}
2426
2427
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002428static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2429 const struct wpa_ssid *ssid)
2430{
2431 enum hostapd_hw_mode hw_mode;
2432 struct hostapd_hw_modes *mode = NULL;
2433 u8 channel;
2434 int i;
2435
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002436 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2437 if (hw_mode == NUM_HOSTAPD_MODES)
2438 return 0;
2439 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2440 if (wpa_s->hw.modes[i].mode == hw_mode) {
2441 mode = &wpa_s->hw.modes[i];
2442 break;
2443 }
2444 }
2445
2446 if (!mode)
2447 return 0;
2448
2449 return mode->vht_capab != 0;
2450}
2451
2452
Hai Shalomc1a21442022-02-04 13:43:00 -08002453static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2454{
2455 int i;
2456
2457 for (i = channel; i < channel + 16; i += 4) {
2458 struct hostapd_channel_data *chan;
2459
2460 chan = hw_get_channel_chan(mode, i, NULL);
2461 if (!chan ||
2462 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2463 return false;
2464 }
2465
2466 return true;
2467}
2468
2469
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002470void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2471 const struct wpa_ssid *ssid,
2472 struct hostapd_freq_params *freq)
2473{
Hai Shalom81f62d82019-07-22 12:10:00 -07002474 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002475 enum hostapd_hw_mode hw_mode;
2476 struct hostapd_hw_modes *mode = NULL;
2477 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2478 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002479 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2480 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2481 6595, 6675, 6755, 6835, 6915, 6995 };
2482 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002483 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2484 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002485 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002486 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002487 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002488 int chwidth, seg0, seg1;
2489 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002490 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002491
2492 freq->freq = ssid->frequency;
2493
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002494 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2495 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2496
2497 if (ssid->mode != WPAS_MODE_IBSS)
2498 break;
2499
2500 /* Don't adjust control freq in case of fixed_freq */
2501 if (ssid->fixed_freq)
2502 break;
2503
2504 if (!bss_is_ibss(bss))
2505 continue;
2506
2507 if (ssid->ssid_len == bss->ssid_len &&
2508 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2509 wpa_printf(MSG_DEBUG,
2510 "IBSS already found in scan results, adjust control freq: %d",
2511 bss->freq);
2512 freq->freq = bss->freq;
2513 obss_scan = 0;
2514 break;
2515 }
2516 }
2517
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002518 /* For IBSS check HT_IBSS flag */
2519 if (ssid->mode == WPAS_MODE_IBSS &&
2520 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2521 return;
2522
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002523 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2524 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2525 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2526 wpa_printf(MSG_DEBUG,
2527 "IBSS: WEP/TKIP detected, do not try to enable HT");
2528 return;
2529 }
2530
2531 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002532 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2533 if (wpa_s->hw.modes[i].mode == hw_mode) {
2534 mode = &wpa_s->hw.modes[i];
2535 break;
2536 }
2537 }
2538
2539 if (!mode)
2540 return;
2541
Hai Shalom60840252021-02-19 19:02:11 -08002542 freq->channel = channel;
2543
Hai Shalomc3565922019-10-28 11:58:20 -07002544 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2545 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002546
Hai Shalomc1a21442022-02-04 13:43:00 -08002547 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2548 * However, HE is mandatory for 6 GHz.
2549 */
2550 is_6ghz = is_6ghz_freq(freq->freq);
2551 if (is_6ghz)
2552 goto skip_to_6ghz;
2553
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002554#ifdef CONFIG_HT_OVERRIDES
2555 if (ssid->disable_ht) {
2556 freq->ht_enabled = 0;
2557 return;
2558 }
2559#endif /* CONFIG_HT_OVERRIDES */
2560
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002561 freq->ht_enabled = ht_supported(mode);
2562 if (!freq->ht_enabled)
2563 return;
2564
Hai Shalomc3565922019-10-28 11:58:20 -07002565 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2566 if (is_24ghz)
2567 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002568#ifdef CONFIG_HE_OVERRIDES
2569 if (is_24ghz && ssid->disable_he)
2570 freq->he_enabled = 0;
2571#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002572
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002573 /* Setup higher BW only for 5 GHz */
2574 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2575 return;
2576
2577 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2578 pri_chan = &mode->channels[chan_idx];
2579 if (pri_chan->chan == channel)
2580 break;
2581 pri_chan = NULL;
2582 }
2583 if (!pri_chan)
2584 return;
2585
2586 /* Check primary channel flags */
2587 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2588 return;
2589
Hai Shalom74f70d42019-02-11 14:42:39 -08002590 freq->channel = pri_chan->chan;
2591
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002592#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002593 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002594#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002595 if (ssid->disable_vht)
2596 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002597#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002598 goto skip_ht40;
2599 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002600#endif /* CONFIG_HT_OVERRIDES */
2601
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002602 /* Check/setup HT40+/HT40- */
2603 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2604 if (ht40plus[j] == channel) {
2605 ht40 = 1;
2606 break;
2607 }
2608 }
2609
2610 /* Find secondary channel */
2611 for (i = 0; i < mode->num_channels; i++) {
2612 sec_chan = &mode->channels[i];
2613 if (sec_chan->chan == channel + ht40 * 4)
2614 break;
2615 sec_chan = NULL;
2616 }
2617 if (!sec_chan)
2618 return;
2619
2620 /* Check secondary channel flags */
2621 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2622 return;
2623
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002624 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002625 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2626 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002627 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002628 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2629 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002630 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002631 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002632
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002633 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002634 struct wpa_scan_results *scan_res;
2635
2636 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2637 if (scan_res == NULL) {
2638 /* Back to HT20 */
2639 freq->sec_channel_offset = 0;
2640 return;
2641 }
2642
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002643 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002644 switch (res) {
2645 case 0:
2646 /* Back to HT20 */
2647 freq->sec_channel_offset = 0;
2648 break;
2649 case 1:
2650 /* Configuration allowed */
2651 break;
2652 case 2:
2653 /* Switch pri/sec channels */
2654 freq->freq = hw_get_freq(mode, sec_chan->chan);
2655 freq->sec_channel_offset = -freq->sec_channel_offset;
2656 freq->channel = sec_chan->chan;
2657 break;
2658 default:
2659 freq->sec_channel_offset = 0;
2660 break;
2661 }
2662
2663 wpa_scan_results_free(scan_res);
2664 }
2665
Hai Shalom74f70d42019-02-11 14:42:39 -08002666#ifdef CONFIG_HT_OVERRIDES
2667skip_ht40:
2668#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002669 wpa_printf(MSG_DEBUG,
2670 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2671 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002673 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002674 return;
2675
2676 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002677 if (ssid->mode == WPAS_MODE_IBSS &&
2678 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002679 return;
2680
Paul Stewart092955c2017-02-06 09:13:09 -08002681#ifdef CONFIG_VHT_OVERRIDES
2682 if (ssid->disable_vht) {
2683 freq->vht_enabled = 0;
2684 return;
2685 }
2686#endif /* CONFIG_VHT_OVERRIDES */
2687
Hai Shalomc1a21442022-02-04 13:43:00 -08002688skip_to_6ghz:
2689 vht_freq = *freq;
2690
2691 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002692 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002693 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002694 return;
2695
Hai Shalomfdcde762020-04-02 11:19:20 -07002696 /* Enable HE with VHT for 5 GHz */
2697 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002698
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002699 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002700 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2701 if (freq->freq >= bw80[j] &&
2702 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002703 break;
2704 }
2705
Hai Shalomc1a21442022-02-04 13:43:00 -08002706 if (j == ARRAY_SIZE(bw80) ||
2707 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002708 return;
2709
Hai Shalomc1a21442022-02-04 13:43:00 -08002710 /* Back to HT configuration if channel not usable */
2711 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2712 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002713
Hai Shalom81f62d82019-07-22 12:10:00 -07002714 chwidth = CHANWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002715 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002716 seg1 = 0;
2717
Hai Shalomc1a21442022-02-04 13:43:00 -08002718 if ((mode->he_capab[ieee80211_mode].phy_cap[
2719 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2720 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2721 /* In 160 MHz, the initial four 20 MHz channels were validated
2722 * above; check the remaining four 20 MHz channels for the total
2723 * of 160 MHz bandwidth.
2724 */
2725 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2726 return;
2727
2728 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2729 if (freq->freq == bw160[j]) {
2730 chwidth = CHANWIDTH_160MHZ;
2731 seg0 = channel + 14;
2732 break;
2733 }
2734 }
2735 }
2736
Hai Shalom81f62d82019-07-22 12:10:00 -07002737 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002738 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002739 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002740 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002741 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002742 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002743
2744 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2745 NUM_HOSTAPD_MODES)
2746 return;
2747
2748 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002749 struct hostapd_channel_data *chan;
2750
2751 chan = hw_get_channel_chan(mode, i, NULL);
2752 if (!chan)
2753 continue;
2754
2755 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2756 HOSTAPD_CHAN_NO_IR |
2757 HOSTAPD_CHAN_RADAR))
2758 continue;
2759
2760 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002761 chwidth = CHANWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002762 if (!is_6ghz)
2763 vht_caps |=
2764 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2765 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002766 }
2767
Hai Shalom81f62d82019-07-22 12:10:00 -07002768 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002769 break;
2770 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002771 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002772 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002773 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002774 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2775 seg0 = 50;
2776 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002777 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002778 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2779 seg0 = 114;
2780 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002781 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2782 chwidth = CHANWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002783 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002784#ifdef CONFIG_HT_OVERRIDES
2785 if (ssid->disable_ht40)
2786 seg0 = 0;
2787#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002788 }
2789
Hai Shalomfdcde762020-04-02 11:19:20 -07002790#ifdef CONFIG_HE_OVERRIDES
2791 if (ssid->disable_he) {
2792 vht_freq.he_enabled = 0;
2793 freq->he_enabled = 0;
2794 }
2795#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002796 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002797 freq->channel, ssid->enable_edmg,
2798 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002799 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002800 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002801 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002802 chwidth, seg0, seg1, vht_caps,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002803 &mode->he_capab[ieee80211_mode],
2804 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002805 return;
2806
2807 *freq = vht_freq;
2808
2809 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2810 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002811}
2812
2813
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814#ifdef CONFIG_FILS
2815static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2816 size_t ie_buf_len)
2817{
2818 struct fils_hlp_req *req;
2819 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2820 const u8 *pos;
2821 u8 *buf = ie_buf;
2822
2823 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2824 list) {
2825 rem_len = ie_buf_len - ie_len;
2826 pos = wpabuf_head(req->pkt);
2827 hdr_len = 1 + 2 * ETH_ALEN + 6;
2828 hlp_len = wpabuf_len(req->pkt);
2829
2830 if (rem_len < 2 + hdr_len + hlp_len) {
2831 wpa_printf(MSG_ERROR,
2832 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2833 (unsigned long) rem_len,
2834 (unsigned long) (2 + hdr_len + hlp_len));
2835 break;
2836 }
2837
2838 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2839 /* Element ID */
2840 *buf++ = WLAN_EID_EXTENSION;
2841 /* Length */
2842 *buf++ = len;
2843 /* Element ID Extension */
2844 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2845 /* Destination MAC address */
2846 os_memcpy(buf, req->dst, ETH_ALEN);
2847 buf += ETH_ALEN;
2848 /* Source MAC address */
2849 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2850 buf += ETH_ALEN;
2851 /* LLC/SNAP Header */
2852 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2853 buf += 6;
2854 /* HLP Packet */
2855 os_memcpy(buf, pos, len - hdr_len);
2856 buf += len - hdr_len;
2857 pos += len - hdr_len;
2858
2859 hlp_len -= len - hdr_len;
2860 ie_len += 2 + len;
2861 rem_len -= 2 + len;
2862
2863 while (hlp_len) {
2864 len = (hlp_len > 255) ? 255 : hlp_len;
2865 if (rem_len < 2 + len)
2866 break;
2867 *buf++ = WLAN_EID_FRAGMENT;
2868 *buf++ = len;
2869 os_memcpy(buf, pos, len);
2870 buf += len;
2871 pos += len;
2872
2873 hlp_len -= len;
2874 ie_len += 2 + len;
2875 rem_len -= 2 + len;
2876 }
2877 }
2878
2879 return ie_len;
2880}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002881
2882
2883int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2884{
2885 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2886 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2887 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2888 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2889}
2890
2891
2892int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2893{
2894#ifdef CONFIG_FILS_SK_PFS
2895 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2896 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2897#else /* CONFIG_FILS_SK_PFS */
2898 return 0;
2899#endif /* CONFIG_FILS_SK_PFS */
2900}
2901
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002902#endif /* CONFIG_FILS */
2903
2904
Hai Shalomc1a21442022-02-04 13:43:00 -08002905static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2906 struct wpa_bss *bss,
2907 u8 *wpa_ie, size_t wpa_ie_len,
2908 size_t max_wpa_ie_len)
2909{
2910 struct wpabuf *wfa_ie = NULL;
2911 u8 wfa_capa[1];
2912 size_t wfa_ie_len, buf_len;
2913
2914 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2915 if (wpa_s->enable_dscp_policy_capa)
2916 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2917
2918 if (!wfa_capa[0])
2919 return wpa_ie_len;
2920
2921 /* Wi-Fi Alliance element */
2922 buf_len = 1 + /* Element ID */
2923 1 + /* Length */
2924 3 + /* OUI */
2925 1 + /* OUI Type */
2926 1 + /* Capabilities Length */
2927 sizeof(wfa_capa); /* Capabilities */
2928 wfa_ie = wpabuf_alloc(buf_len);
2929 if (!wfa_ie)
2930 return wpa_ie_len;
2931
2932 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2933 wpabuf_put_u8(wfa_ie, buf_len - 2);
2934 wpabuf_put_be24(wfa_ie, OUI_WFA);
2935 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2936 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2937 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2938
2939 wfa_ie_len = wpabuf_len(wfa_ie);
2940 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2941 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2942 wfa_ie);
2943 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2944 wfa_ie_len);
2945 wpa_ie_len += wfa_ie_len;
2946 }
2947
2948 wpabuf_free(wfa_ie);
2949 return wpa_ie_len;
2950}
2951
2952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002953static u8 * wpas_populate_assoc_ies(
2954 struct wpa_supplicant *wpa_s,
2955 struct wpa_bss *bss, struct wpa_ssid *ssid,
2956 struct wpa_driver_associate_params *params,
2957 enum wpa_drv_update_connect_params_mask *mask)
2958{
2959 u8 *wpa_ie;
2960 size_t max_wpa_ie_len = 500;
2961 size_t wpa_ie_len;
2962 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002963#ifdef CONFIG_MBO
2964 const u8 *mbo_ie;
2965#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302966#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2967 int pmksa_cached = 0;
2968#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002969#ifdef CONFIG_FILS
2970 const u8 *realm, *username, *rrk;
2971 size_t realm_len, username_len, rrk_len;
2972 u16 next_seq_num;
2973 struct fils_hlp_req *req;
2974
2975 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2976 list) {
2977 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2978 2 + 2 * wpabuf_len(req->pkt) / 255;
2979 }
2980#endif /* CONFIG_FILS */
2981
2982 wpa_ie = os_malloc(max_wpa_ie_len);
2983 if (!wpa_ie) {
2984 wpa_printf(MSG_ERROR,
2985 "Failed to allocate connect IE buffer for %lu bytes",
2986 (unsigned long) max_wpa_ie_len);
2987 return NULL;
2988 }
2989
2990 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2991 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2992 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2993 int try_opportunistic;
2994 const u8 *cache_id = NULL;
2995
2996 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2997 wpa_s->conf->okc :
2998 ssid->proactive_key_caching) &&
2999 (ssid->proto & WPA_PROTO_RSN);
3000#ifdef CONFIG_FILS
3001 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3002 cache_id = wpa_bss_get_fils_cache_id(bss);
3003#endif /* CONFIG_FILS */
3004 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3005 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003006 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003007 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303008#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3009 pmksa_cached = 1;
3010#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003011 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003012 wpa_ie_len = max_wpa_ie_len;
3013 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3014 wpa_ie, &wpa_ie_len)) {
3015 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3016 "key management and encryption suites");
3017 os_free(wpa_ie);
3018 return NULL;
3019 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003020#ifdef CONFIG_HS20
3021 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3022 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3023 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3024 wpa_ie_len = max_wpa_ie_len;
3025 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3026 wpa_ie, &wpa_ie_len)) {
3027 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3028 "key management and encryption suites");
3029 os_free(wpa_ie);
3030 return NULL;
3031 }
3032#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003033 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3034 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3035 /*
3036 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3037 * use non-WPA since the scan results did not indicate that the
3038 * AP is using WPA or WPA2.
3039 */
3040 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3041 wpa_ie_len = 0;
3042 wpa_s->wpa_proto = 0;
3043 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3044 wpa_ie_len = max_wpa_ie_len;
3045 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3046 wpa_ie, &wpa_ie_len)) {
3047 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3048 "key management and encryption suites (no "
3049 "scan results)");
3050 os_free(wpa_ie);
3051 return NULL;
3052 }
3053#ifdef CONFIG_WPS
3054 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3055 struct wpabuf *wps_ie;
3056 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3057 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3058 wpa_ie_len = wpabuf_len(wps_ie);
3059 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3060 } else
3061 wpa_ie_len = 0;
3062 wpabuf_free(wps_ie);
3063 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3064 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3065 params->wps = WPS_MODE_PRIVACY;
3066 else
3067 params->wps = WPS_MODE_OPEN;
3068 wpa_s->wpa_proto = 0;
3069#endif /* CONFIG_WPS */
3070 } else {
3071 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3072 wpa_ie_len = 0;
3073 wpa_s->wpa_proto = 0;
3074 }
3075
3076#ifdef IEEE8021X_EAPOL
3077 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3078 if (ssid->leap) {
3079 if (ssid->non_leap == 0)
3080 algs = WPA_AUTH_ALG_LEAP;
3081 else
3082 algs |= WPA_AUTH_ALG_LEAP;
3083 }
3084 }
3085
3086#ifdef CONFIG_FILS
3087 /* Clear FILS association */
3088 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3089
3090 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3091 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3092 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3093 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003094 &next_seq_num, &rrk, &rrk_len) == 0 &&
3095 (!wpa_s->last_con_fail_realm ||
3096 wpa_s->last_con_fail_realm_len != realm_len ||
3097 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003098 algs = WPA_AUTH_ALG_FILS;
3099 params->fils_erp_username = username;
3100 params->fils_erp_username_len = username_len;
3101 params->fils_erp_realm = realm;
3102 params->fils_erp_realm_len = realm_len;
3103 params->fils_erp_next_seq_num = next_seq_num;
3104 params->fils_erp_rrk = rrk;
3105 params->fils_erp_rrk_len = rrk_len;
3106
3107 if (mask)
3108 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303109 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3110 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3111 pmksa_cached) {
3112 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003113 }
3114#endif /* CONFIG_FILS */
3115#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003116#ifdef CONFIG_SAE
3117 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3118 algs = WPA_AUTH_ALG_SAE;
3119#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003120
3121 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3122 if (ssid->auth_alg) {
3123 algs = ssid->auth_alg;
3124 wpa_dbg(wpa_s, MSG_DEBUG,
3125 "Overriding auth_alg selection: 0x%x", algs);
3126 }
3127
Hai Shalom5f92bc92019-04-18 11:54:11 -07003128#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303129 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003130 wpa_dbg(wpa_s, MSG_DEBUG,
3131 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3132 algs = WPA_AUTH_ALG_OPEN;
3133 }
3134#endif /* CONFIG_SAE */
3135
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136#ifdef CONFIG_P2P
3137 if (wpa_s->global->p2p) {
3138 u8 *pos;
3139 size_t len;
3140 int res;
3141 pos = wpa_ie + wpa_ie_len;
3142 len = max_wpa_ie_len - wpa_ie_len;
3143 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3144 ssid->p2p_group);
3145 if (res >= 0)
3146 wpa_ie_len += res;
3147 }
3148
3149 wpa_s->cross_connect_disallowed = 0;
3150 if (bss) {
3151 struct wpabuf *p2p;
3152 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3153 if (p2p) {
3154 wpa_s->cross_connect_disallowed =
3155 p2p_get_cross_connect_disallowed(p2p);
3156 wpabuf_free(p2p);
3157 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3158 "connection",
3159 wpa_s->cross_connect_disallowed ?
3160 "disallows" : "allows");
3161 }
3162 }
3163
3164 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3165#endif /* CONFIG_P2P */
3166
3167 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003168 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003169 wpa_ie + wpa_ie_len,
3170 max_wpa_ie_len -
3171 wpa_ie_len);
3172 }
3173
3174 /*
3175 * Workaround: Add Extended Capabilities element only if the AP
3176 * included this element in Beacon/Probe Response frames. Some older
3177 * APs seem to have interoperability issues if this element is
3178 * included, so while the standard may require us to include the
3179 * element in all cases, it is justifiable to skip it to avoid
3180 * interoperability issues.
3181 */
3182 if (ssid->p2p_group)
3183 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3184 else
3185 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3186
3187 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3188 u8 ext_capab[18];
3189 int ext_capab_len;
3190 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3191 sizeof(ext_capab));
3192 if (ext_capab_len > 0 &&
3193 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3194 u8 *pos = wpa_ie;
3195 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3196 pos += 2 + pos[1];
3197 os_memmove(pos + ext_capab_len, pos,
3198 wpa_ie_len - (pos - wpa_ie));
3199 wpa_ie_len += ext_capab_len;
3200 os_memcpy(pos, ext_capab, ext_capab_len);
3201 }
3202 }
3203
3204#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003205 if (is_hs20_network(wpa_s, ssid, bss)
3206#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3207 && is_hs20_config(wpa_s)
3208#endif /* ANDROID */
3209 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003210 struct wpabuf *hs20;
3211
Roshan Pius3a1667e2018-07-03 15:17:14 -07003212 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003213 if (hs20) {
3214 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3215 size_t len;
3216
Hai Shalom74f70d42019-02-11 14:42:39 -08003217 wpas_hs20_add_indication(hs20, pps_mo_id,
3218 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003219 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003220 len = max_wpa_ie_len - wpa_ie_len;
3221 if (wpabuf_len(hs20) <= len) {
3222 os_memcpy(wpa_ie + wpa_ie_len,
3223 wpabuf_head(hs20), wpabuf_len(hs20));
3224 wpa_ie_len += wpabuf_len(hs20);
3225 }
3226 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003227 }
3228 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003229 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003230#endif /* CONFIG_HS20 */
3231
3232 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3233 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3234 size_t len;
3235
3236 len = max_wpa_ie_len - wpa_ie_len;
3237 if (wpabuf_len(buf) <= len) {
3238 os_memcpy(wpa_ie + wpa_ie_len,
3239 wpabuf_head(buf), wpabuf_len(buf));
3240 wpa_ie_len += wpabuf_len(buf);
3241 }
3242 }
3243
3244#ifdef CONFIG_FST
3245 if (wpa_s->fst_ies) {
3246 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3247
3248 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3249 os_memcpy(wpa_ie + wpa_ie_len,
3250 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3251 wpa_ie_len += fst_ies_len;
3252 }
3253 }
3254#endif /* CONFIG_FST */
3255
3256#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003257 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003258 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259 int len;
3260
3261 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003262 max_wpa_ie_len - wpa_ie_len,
3263 !!mbo_attr_from_mbo_ie(mbo_ie,
3264 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003265 if (len >= 0)
3266 wpa_ie_len += len;
3267 }
3268#endif /* CONFIG_MBO */
3269
3270#ifdef CONFIG_FILS
3271 if (algs == WPA_AUTH_ALG_FILS) {
3272 size_t len;
3273
3274 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3275 max_wpa_ie_len - wpa_ie_len);
3276 wpa_ie_len += len;
3277 }
3278#endif /* CONFIG_FILS */
3279
3280#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003281#ifdef CONFIG_TESTING_OPTIONS
3282 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3283 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3284 } else
3285#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003286 if (algs == WPA_AUTH_ALG_OPEN &&
3287 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3288 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003289 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003290
Roshan Pius3a1667e2018-07-03 15:17:14 -07003291 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003292 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003293 } else if (wpa_s->assoc_status_code ==
3294 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003295 if (wpa_s->last_owe_group == 19)
3296 group = 20;
3297 else if (wpa_s->last_owe_group == 20)
3298 group = 21;
3299 else
3300 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003301 } else {
3302 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003303 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003304
Roshan Pius3a1667e2018-07-03 15:17:14 -07003305 wpa_s->last_owe_group = group;
3306 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003307 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3308 if (owe_ie &&
3309 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3310 os_memcpy(wpa_ie + wpa_ie_len,
3311 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3312 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003314 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003315 }
3316#endif /* CONFIG_OWE */
3317
Hai Shalom021b0b52019-04-10 11:17:58 -07003318#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003319 if (DPP_VERSION > 1 &&
3320 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003321 ssid->dpp_netaccesskey &&
3322 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003323 struct rsn_pmksa_cache_entry *pmksa;
3324
3325 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3326 if (!pmksa || !pmksa->dpp_pfs)
3327 goto pfs_fail;
3328
Hai Shalom021b0b52019-04-10 11:17:58 -07003329 dpp_pfs_free(wpa_s->dpp_pfs);
3330 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3331 ssid->dpp_netaccesskey_len);
3332 if (!wpa_s->dpp_pfs) {
3333 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3334 /* Try to continue without PFS */
3335 goto pfs_fail;
3336 }
3337 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3338 max_wpa_ie_len - wpa_ie_len) {
3339 os_memcpy(wpa_ie + wpa_ie_len,
3340 wpabuf_head(wpa_s->dpp_pfs->ie),
3341 wpabuf_len(wpa_s->dpp_pfs->ie));
3342 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3343 }
3344 }
3345pfs_fail:
3346#endif /* CONFIG_DPP2 */
3347
Roshan Pius3a1667e2018-07-03 15:17:14 -07003348#ifdef CONFIG_IEEE80211R
3349 /*
3350 * Add MDIE under these conditions: the network profile allows FT,
3351 * the AP supports FT, and the mobility domain ID matches.
3352 */
3353 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3354 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3355
3356 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3357 size_t len = 0;
3358 const u8 *md = mdie + 2;
3359 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3360
3361 if (os_memcmp(md, wpa_md,
3362 MOBILITY_DOMAIN_ID_LEN) == 0) {
3363 /* Add mobility domain IE */
3364 len = wpa_ft_add_mdie(
3365 wpa_s->wpa, wpa_ie + wpa_ie_len,
3366 max_wpa_ie_len - wpa_ie_len, mdie);
3367 wpa_ie_len += len;
3368 }
3369#ifdef CONFIG_SME
3370 if (len > 0 && wpa_s->sme.ft_used &&
3371 wpa_sm_has_ptk(wpa_s->wpa)) {
3372 wpa_dbg(wpa_s, MSG_DEBUG,
3373 "SME: Trying to use FT over-the-air");
3374 algs |= WPA_AUTH_ALG_FT;
3375 }
3376#endif /* CONFIG_SME */
3377 }
3378 }
3379#endif /* CONFIG_IEEE80211R */
3380
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003381#ifdef CONFIG_TESTING_OPTIONS
3382 if (wpa_s->rsnxe_override_assoc &&
3383 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3384 max_wpa_ie_len - wpa_ie_len) {
3385 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3386 os_memcpy(wpa_ie + wpa_ie_len,
3387 wpabuf_head(wpa_s->rsnxe_override_assoc),
3388 wpabuf_len(wpa_s->rsnxe_override_assoc));
3389 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3390 } else
3391#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003392 if (wpa_s->rsnxe_len > 0 &&
3393 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3394 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3395 wpa_ie_len += wpa_s->rsnxe_len;
3396 }
3397
Hai Shalomc1a21442022-02-04 13:43:00 -08003398#ifdef CONFIG_TESTING_OPTIONS
3399 if (wpa_s->disable_mscs_support)
3400 goto mscs_end;
3401#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003402 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3403 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003404 struct wpabuf *mscs_ie;
3405 size_t mscs_ie_len, buf_len;
3406
Hai Shalom899fcc72020-10-19 14:38:18 -07003407 buf_len = 3 + /* MSCS descriptor IE header */
3408 1 + /* Request type */
3409 2 + /* User priority control */
3410 4 + /* Stream timeout */
3411 3 + /* TCLAS Mask IE header */
3412 wpa_s->robust_av.frame_classifier_len;
3413 mscs_ie = wpabuf_alloc(buf_len);
3414 if (!mscs_ie) {
3415 wpa_printf(MSG_INFO,
3416 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003417 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003418 }
3419
3420 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3421 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3422 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3423 mscs_ie_len = wpabuf_len(mscs_ie);
3424 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3425 mscs_ie_len);
3426 wpa_ie_len += mscs_ie_len;
3427 }
3428
3429 wpabuf_free(mscs_ie);
3430 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003431mscs_end:
3432
3433 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3434 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003435
Hai Shalom74f70d42019-02-11 14:42:39 -08003436 if (ssid->multi_ap_backhaul_sta) {
3437 size_t multi_ap_ie_len;
3438
3439 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3440 max_wpa_ie_len - wpa_ie_len,
3441 MULTI_AP_BACKHAUL_STA);
3442 if (multi_ap_ie_len == 0) {
3443 wpa_printf(MSG_ERROR,
3444 "Multi-AP: Failed to build Multi-AP IE");
3445 os_free(wpa_ie);
3446 return NULL;
3447 }
3448 wpa_ie_len += multi_ap_ie_len;
3449 }
3450
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003451 params->wpa_ie = wpa_ie;
3452 params->wpa_ie_len = wpa_ie_len;
3453 params->auth_alg = algs;
3454 if (mask)
3455 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3456
3457 return wpa_ie;
3458}
3459
3460
Hai Shalomc3565922019-10-28 11:58:20 -07003461#ifdef CONFIG_OWE
3462static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3463{
3464 struct wpa_driver_associate_params params;
3465 u8 *wpa_ie;
3466
3467 os_memset(&params, 0, sizeof(params));
3468 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3469 wpa_s->current_ssid, &params, NULL);
3470 if (!wpa_ie)
3471 return;
3472
3473 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3474 os_free(wpa_ie);
3475}
3476#endif /* CONFIG_OWE */
3477
3478
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003479#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3480static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3481{
3482 struct wpa_driver_associate_params params;
3483 enum wpa_drv_update_connect_params_mask mask = 0;
3484 u8 *wpa_ie;
3485
3486 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3487 return; /* nothing to do */
3488
3489 os_memset(&params, 0, sizeof(params));
3490 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3491 wpa_s->current_ssid, &params, &mask);
3492 if (!wpa_ie)
3493 return;
3494
Hai Shalomc1a21442022-02-04 13:43:00 -08003495 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3496 wpa_s->auth_alg = params.auth_alg;
3497 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003498 }
3499
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003500 os_free(wpa_ie);
3501}
3502#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3503
3504
Hai Shalomc3565922019-10-28 11:58:20 -07003505static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3506{
3507 if (!edmg_ie || edmg_ie[1] < 6)
3508 return 0;
3509 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3510}
3511
3512
3513static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3514{
3515 if (!edmg_ie || edmg_ie[1] < 6)
3516 return 0;
3517 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3518}
3519
3520
3521/* Returns the intersection of two EDMG configurations.
3522 * Note: The current implementation is limited to CB2 only (CB1 included),
3523 * i.e., the implementation supports up to 2 contiguous channels.
3524 * For supporting non-contiguous (aggregated) channels and for supporting
3525 * CB3 and above, this function will need to be extended.
3526 */
3527static struct ieee80211_edmg_config
3528get_edmg_intersection(struct ieee80211_edmg_config a,
3529 struct ieee80211_edmg_config b,
3530 u8 primary_channel)
3531{
3532 struct ieee80211_edmg_config result;
3533 int i, contiguous = 0;
3534 int max_contiguous = 0;
3535
3536 result.channels = b.channels & a.channels;
3537 if (!result.channels) {
3538 wpa_printf(MSG_DEBUG,
3539 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3540 a.channels, b.channels);
3541 goto fail;
3542 }
3543
3544 if (!(result.channels & BIT(primary_channel - 1))) {
3545 wpa_printf(MSG_DEBUG,
3546 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3547 primary_channel, result.channels);
3548 goto fail;
3549 }
3550
3551 /* Find max contiguous channels */
3552 for (i = 0; i < 6; i++) {
3553 if (result.channels & BIT(i))
3554 contiguous++;
3555 else
3556 contiguous = 0;
3557
3558 if (contiguous > max_contiguous)
3559 max_contiguous = contiguous;
3560 }
3561
3562 /* Assuming AP and STA supports ONLY contiguous channels,
3563 * bw configuration can have value between 4-7.
3564 */
3565 if ((b.bw_config < a.bw_config))
3566 result.bw_config = b.bw_config;
3567 else
3568 result.bw_config = a.bw_config;
3569
3570 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3571 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3572 wpa_printf(MSG_DEBUG,
3573 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3574 max_contiguous);
3575 goto fail;
3576 }
3577
3578 return result;
3579
3580fail:
3581 result.channels = 0;
3582 result.bw_config = 0;
3583 return result;
3584}
3585
3586
3587static struct ieee80211_edmg_config
3588get_supported_edmg(struct wpa_supplicant *wpa_s,
3589 struct hostapd_freq_params *freq,
3590 struct ieee80211_edmg_config request_edmg)
3591{
3592 enum hostapd_hw_mode hw_mode;
3593 struct hostapd_hw_modes *mode = NULL;
3594 u8 primary_channel;
3595
3596 if (!wpa_s->hw.modes)
3597 goto fail;
3598
3599 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3600 if (hw_mode == NUM_HOSTAPD_MODES)
3601 goto fail;
3602
Hai Shalom60840252021-02-19 19:02:11 -08003603 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003604 if (!mode)
3605 goto fail;
3606
3607 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3608
3609fail:
3610 request_edmg.channels = 0;
3611 request_edmg.bw_config = 0;
3612 return request_edmg;
3613}
3614
3615
Hai Shalom021b0b52019-04-10 11:17:58 -07003616#ifdef CONFIG_MBO
3617void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3618{
3619 struct wpa_driver_associate_params params;
3620 u8 *wpa_ie;
3621
3622 /*
3623 * Update MBO connect params only in case of change of MBO attributes
3624 * when connected, if the AP support MBO.
3625 */
3626
3627 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3628 !wpa_s->current_bss ||
3629 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3630 return;
3631
3632 os_memset(&params, 0, sizeof(params));
3633 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3634 wpa_s->current_ssid, &params, NULL);
3635 if (!wpa_ie)
3636 return;
3637
3638 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3639 os_free(wpa_ie);
3640}
3641#endif /* CONFIG_MBO */
3642
3643
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003644static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3645{
3646 struct wpa_connect_work *cwork = work->ctx;
3647 struct wpa_bss *bss = cwork->bss;
3648 struct wpa_ssid *ssid = cwork->ssid;
3649 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003650 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003651 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003652 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003653 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003654 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003655#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003656 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003657#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003658 int assoc_failed = 0;
3659 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003660 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003661#ifdef CONFIG_HT_OVERRIDES
3662 struct ieee80211_ht_capabilities htcaps;
3663 struct ieee80211_ht_capabilities htcaps_mask;
3664#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003665#ifdef CONFIG_VHT_OVERRIDES
3666 struct ieee80211_vht_capabilities vhtcaps;
3667 struct ieee80211_vht_capabilities vhtcaps_mask;
3668#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003669
Hai Shalomc1a21442022-02-04 13:43:00 -08003670 wpa_s->roam_in_progress = false;
3671#ifdef CONFIG_WNM
3672 wpa_s->bss_trans_mgmt_in_progress = false;
3673#endif /* CONFIG_WNM */
3674
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003675 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003676 if (work->started) {
3677 wpa_s->connect_work = NULL;
3678
3679 /* cancel possible auth. timeout */
3680 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3681 NULL);
3682 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003683 wpas_connect_work_free(cwork);
3684 return;
3685 }
3686
3687 wpa_s->connect_work = work;
3688
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003689 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3690 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003691 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3692 wpas_connect_work_done(wpa_s);
3693 return;
3694 }
3695
Dmitry Shmidte4663042016-04-04 10:07:49 -07003696 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003697 os_memset(&params, 0, sizeof(params));
3698 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003699 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003700
3701 /* Starting new association, so clear the possibly used WPA IE from the
3702 * previous association. */
3703 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3704 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3705 wpa_s->rsnxe_len = 0;
3706 wpa_s->mscs_setup_done = false;
3707
3708 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3709 if (!wpa_ie) {
3710 wpas_connect_work_done(wpa_s);
3711 return;
3712 }
3713
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003714 if (bss &&
3715 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716#ifdef CONFIG_IEEE80211R
3717 const u8 *ie, *md = NULL;
3718#endif /* CONFIG_IEEE80211R */
3719 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3720 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3721 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3722 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3723 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3724 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3725 if (bssid_changed)
3726 wpas_notify_bssid_changed(wpa_s);
3727#ifdef CONFIG_IEEE80211R
3728 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3729 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3730 md = ie + 2;
3731 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3732 if (md) {
3733 /* Prepare for the next transition */
3734 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3735 }
3736#endif /* CONFIG_IEEE80211R */
3737#ifdef CONFIG_WPS
3738 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3739 wpa_s->conf->ap_scan == 2 &&
3740 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3741 /* Use ap_scan==1 style network selection to find the network
3742 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003743 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003744 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003745 wpa_s->reassociate = 1;
3746 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003747 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003748 return;
3749#endif /* CONFIG_WPS */
3750 } else {
3751 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3752 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003753 if (bss)
3754 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3755 else
3756 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003758 if (!wpa_s->pno)
3759 wpa_supplicant_cancel_sched_scan(wpa_s);
3760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 wpa_supplicant_cancel_scan(wpa_s);
3762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3764 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003765 cipher_pairwise = wpa_s->pairwise_cipher;
3766 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003767 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3769 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3770 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3771 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003772#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003773 if (wpa_set_wep_keys(wpa_s, ssid)) {
3774 use_crypt = 1;
3775 wep_keys_set = 1;
3776 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003777#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003778 }
3779 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3780 use_crypt = 0;
3781
3782#ifdef IEEE8021X_EAPOL
3783 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3784 if ((ssid->eapol_flags &
3785 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3786 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3787 !wep_keys_set) {
3788 use_crypt = 0;
3789 } else {
3790 /* Assume that dynamic WEP-104 keys will be used and
3791 * set cipher suites in order for drivers to expect
3792 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003793 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003794 }
3795 }
3796#endif /* IEEE8021X_EAPOL */
3797
3798 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3799 /* Set the key before (and later after) association */
3800 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3801 }
3802
3803 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3804 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805 params.ssid = bss->ssid;
3806 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003807 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3808 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003809 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3810 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003811 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003812 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003813 ssid->bssid_set,
3814 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003815 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003816 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003817 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003818 params.bssid_hint = bss->bssid;
3819 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003820 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003822 if (ssid->bssid_hint_set)
3823 params.bssid_hint = ssid->bssid_hint;
3824
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 params.ssid = ssid->ssid;
3826 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003827 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003829
3830 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3831 wpa_s->conf->ap_scan == 2) {
3832 params.bssid = ssid->bssid;
3833 params.fixed_bssid = 1;
3834 }
3835
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003836 /* Initial frequency for IBSS/mesh */
3837 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003838 ssid->frequency > 0 && params.freq.freq == 0)
3839 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003840
3841 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003842 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003843 if (ssid->beacon_int)
3844 params.beacon_int = ssid->beacon_int;
3845 else
3846 params.beacon_int = wpa_s->conf->beacon_int;
3847 }
3848
Hai Shalomc3565922019-10-28 11:58:20 -07003849 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003850 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3851 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003852 else
3853 edmg_ie_oper = NULL;
3854
3855 if (edmg_ie_oper) {
3856 params.freq.edmg.channels =
3857 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3858 params.freq.edmg.bw_config =
3859 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3860 wpa_printf(MSG_DEBUG,
3861 "AP supports EDMG channels 0x%x, bw_config %d",
3862 params.freq.edmg.channels,
3863 params.freq.edmg.bw_config);
3864
3865 /* User may ask for specific EDMG channel for EDMG connection
3866 * (must be supported by AP)
3867 */
3868 if (ssid->edmg_channel) {
3869 struct ieee80211_edmg_config configured_edmg;
3870 enum hostapd_hw_mode hw_mode;
3871 u8 primary_channel;
3872
3873 hw_mode = ieee80211_freq_to_chan(bss->freq,
3874 &primary_channel);
3875 if (hw_mode == NUM_HOSTAPD_MODES)
3876 goto edmg_fail;
3877
3878 hostapd_encode_edmg_chan(ssid->enable_edmg,
3879 ssid->edmg_channel,
3880 primary_channel,
3881 &configured_edmg);
3882
3883 if (ieee802_edmg_is_allowed(params.freq.edmg,
3884 configured_edmg)) {
3885 params.freq.edmg = configured_edmg;
3886 wpa_printf(MSG_DEBUG,
3887 "Use EDMG channel %d for connection",
3888 ssid->edmg_channel);
3889 } else {
3890 edmg_fail:
3891 params.freq.edmg.channels = 0;
3892 params.freq.edmg.bw_config = 0;
3893 wpa_printf(MSG_WARNING,
3894 "EDMG channel %d not supported by AP, fallback to DMG",
3895 ssid->edmg_channel);
3896 }
3897 }
3898
3899 if (params.freq.edmg.channels) {
3900 wpa_printf(MSG_DEBUG,
3901 "EDMG before: channels 0x%x, bw_config %d",
3902 params.freq.edmg.channels,
3903 params.freq.edmg.bw_config);
3904 params.freq.edmg = get_supported_edmg(wpa_s,
3905 &params.freq,
3906 params.freq.edmg);
3907 wpa_printf(MSG_DEBUG,
3908 "EDMG after: channels 0x%x, bw_config %d",
3909 params.freq.edmg.channels,
3910 params.freq.edmg.bw_config);
3911 }
3912 }
3913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914 params.pairwise_suite = cipher_pairwise;
3915 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003916 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003917 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003918 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003919 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003921 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003922#ifdef CONFIG_WEP
3923 {
3924 int i;
3925
3926 for (i = 0; i < NUM_WEP_KEYS; i++) {
3927 if (ssid->wep_key_len[i])
3928 params.wep_key[i] = ssid->wep_key[i];
3929 params.wep_key_len[i] = ssid->wep_key_len[i];
3930 }
3931 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003933#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934
Hai Shalom74f70d42019-02-11 14:42:39 -08003935 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303936 (
3937#ifdef CONFIG_DRIVER_NL80211_BRCM
3938 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3939#else
3940 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3941#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003942 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 params.passphrase = ssid->passphrase;
3944 if (ssid->psk_set)
3945 params.psk = ssid->psk;
3946 }
3947
Hai Shalom74f70d42019-02-11 14:42:39 -08003948 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3949 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3950 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3951 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3952 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003953 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003954
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003955 if (wpa_s->conf->key_mgmt_offload) {
3956 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3957 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003958 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3959 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003960 params.req_key_mgmt_offload =
3961 ssid->proactive_key_caching < 0 ?
3962 wpa_s->conf->okc : ssid->proactive_key_caching;
3963 else
3964 params.req_key_mgmt_offload = 1;
3965
Vinayak Yadawad14709082022-03-17 14:25:11 +05303966 if ((
3967#ifdef CONFIG_DRIVER_NL80211_BRCM
3968 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3969#else
3970 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3971#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003972 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3973 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3974 ssid->psk_set)
3975 params.psk = ssid->psk;
3976 }
3977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978 params.drop_unencrypted = use_crypt;
3979
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003980 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003981 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003982 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3983 struct wpa_ie_data ie;
3984 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3985 ie.capabilities &
3986 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3987 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3988 "MFP: require MFP");
3989 params.mgmt_frame_protection =
3990 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003991#ifdef CONFIG_OWE
3992 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3993 !ssid->owe_only) {
3994 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3995#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 }
3997 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003999 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004001 if (wpa_s->p2pdev->set_sta_uapsd)
4002 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003 else
4004 params.uapsd = -1;
4005
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004006#ifdef CONFIG_HT_OVERRIDES
4007 os_memset(&htcaps, 0, sizeof(htcaps));
4008 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4009 params.htcaps = (u8 *) &htcaps;
4010 params.htcaps_mask = (u8 *) &htcaps_mask;
4011 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4012#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004013#ifdef CONFIG_VHT_OVERRIDES
4014 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4015 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4016 params.vhtcaps = &vhtcaps;
4017 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004018 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004019#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004020#ifdef CONFIG_HE_OVERRIDES
4021 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4022#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004023
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004024#ifdef CONFIG_P2P
4025 /*
4026 * If multi-channel concurrency is not supported, check for any
4027 * frequency conflict. In case of any frequency conflict, remove the
4028 * least prioritized connection.
4029 */
4030 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004031 int freq, num;
4032 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004033 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004034 wpa_printf(MSG_DEBUG,
4035 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004036 freq, params.freq.freq);
4037 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004038 wpa_s, params.freq.freq, ssid) < 0) {
4039 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004040 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004041 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004042 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004043 }
4044 }
4045#endif /* CONFIG_P2P */
4046
Dmitry Shmidte4663042016-04-04 10:07:49 -07004047 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
4048 wpa_s->current_ssid)
4049 params.prev_bssid = prev_bssid;
4050
Hai Shalom60840252021-02-19 19:02:11 -08004051#ifdef CONFIG_SAE
4052 params.sae_pwe = wpa_s->conf->sae_pwe;
4053#endif /* CONFIG_SAE */
4054
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004055 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004056 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004057 if (ret < 0) {
4058 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4059 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004060 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004061 /*
4062 * The driver is known to mean what is saying, so we
4063 * can stop right here; the association will not
4064 * succeed.
4065 */
4066 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004067 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004068 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004069 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4071 return;
4072 }
4073 /* try to continue anyway; new association will be tried again
4074 * after timeout */
4075 assoc_failed = 1;
4076 }
4077
4078 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4079 /* Set the key after the association just in case association
4080 * cleared the previously configured key. */
4081 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4082 /* No need to timeout authentication since there is no key
4083 * management. */
4084 wpa_supplicant_cancel_auth_timeout(wpa_s);
4085 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4086#ifdef CONFIG_IBSS_RSN
4087 } else if (ssid->mode == WPAS_MODE_IBSS &&
4088 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4089 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4090 /*
4091 * RSN IBSS authentication is per-STA and we can disable the
4092 * per-BSSID authentication.
4093 */
4094 wpa_supplicant_cancel_auth_timeout(wpa_s);
4095#endif /* CONFIG_IBSS_RSN */
4096 } else {
4097 /* Timeout for IEEE 802.11 authentication and association */
4098 int timeout = 60;
4099
4100 if (assoc_failed) {
4101 /* give IBSS a bit more time */
4102 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4103 } else if (wpa_s->conf->ap_scan == 1) {
4104 /* give IBSS a bit more time */
4105 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4106 }
4107 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4108 }
4109
Hai Shalomfdcde762020-04-02 11:19:20 -07004110#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004111 if (wep_keys_set &&
4112 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113 /* Set static WEP keys again */
4114 wpa_set_wep_keys(wpa_s, ssid);
4115 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004116#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004117
4118 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
4119 /*
4120 * Do not allow EAP session resumption between different
4121 * network configurations.
4122 */
4123 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4124 }
4125 old_ssid = wpa_s->current_ssid;
4126 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004127
4128 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004129 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004130#ifdef CONFIG_HS20
4131 hs20_configure_frame_filters(wpa_s);
4132#endif /* CONFIG_HS20 */
4133 }
4134
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004135 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4136 wpa_supplicant_initiate_eapol(wpa_s);
4137 if (old_ssid != wpa_s->current_ssid)
4138 wpas_notify_network_changed(wpa_s);
4139}
4140
4141
4142static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4143 const u8 *addr)
4144{
4145 struct wpa_ssid *old_ssid;
4146
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004147 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004150 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151 wpa_sm_set_config(wpa_s->wpa, NULL);
4152 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4153 if (old_ssid != wpa_s->current_ssid)
4154 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004155
4156 wpas_scs_deinit(wpa_s);
4157 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4159}
4160
4161
4162/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4164 * @wpa_s: Pointer to wpa_supplicant data
4165 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4166 *
4167 * This function is used to request %wpa_supplicant to deauthenticate from the
4168 * current AP.
4169 */
4170void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004171 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004172{
4173 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004174 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004175 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004177 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004178 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004179 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004180 reason_code, reason2str(reason_code),
4181 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004182
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004183 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4184 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4185 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004186 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004187 else if (!is_zero_ether_addr(wpa_s->bssid))
4188 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004189 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4190 /*
4191 * When using driver-based BSS selection, we may not know the
4192 * BSSID with which we are currently trying to associate. We
4193 * need to notify the driver of this disconnection even in such
4194 * a case, so use the all zeros address here.
4195 */
4196 addr = wpa_s->bssid;
4197 zero_addr = 1;
4198 }
4199
Hai Shalom74f70d42019-02-11 14:42:39 -08004200 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4201 wpa_s->enabled_4addr_mode = 0;
4202
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004203#ifdef CONFIG_TDLS
4204 wpa_tdls_teardown_peers(wpa_s->wpa);
4205#endif /* CONFIG_TDLS */
4206
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004207#ifdef CONFIG_MESH
4208 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004209 struct mesh_conf *mconf;
4210
4211 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004212 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4213 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004214 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4215 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004216 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004217 }
4218#endif /* CONFIG_MESH */
4219
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004220 if (addr) {
4221 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004222 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004223 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004224 event.deauth_info.locally_generated = 1;
4225 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004226 if (zero_addr)
4227 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228 }
4229
4230 wpa_supplicant_clear_connection(wpa_s, addr);
4231}
4232
Hai Shalomfdcde762020-04-02 11:19:20 -07004233
4234void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4235{
4236 wpa_s->own_reconnect_req = 1;
4237 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4238
4239}
4240
4241
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004242static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4243 struct wpa_ssid *ssid)
4244{
4245 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4246 return;
4247
4248 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004249 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004250 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4251 wpas_notify_network_enabled_changed(wpa_s, ssid);
4252
4253 /*
4254 * Try to reassociate since there is no current configuration and a new
4255 * network was made available.
4256 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004257 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004258 wpa_s->reassociate = 1;
4259}
4260
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004261
Roshan Pius950bec92016-07-19 09:49:24 -07004262/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004263 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004264 * @wpa_s: wpa_supplicant structure for a network interface
4265 * Returns: The new network configuration or %NULL if operation failed
4266 *
4267 * This function performs the following operations:
4268 * 1. Adds a new network.
4269 * 2. Send network addition notification.
4270 * 3. Marks the network disabled.
4271 * 4. Set network default parameters.
4272 */
4273struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4274{
4275 struct wpa_ssid *ssid;
4276
4277 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004278 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004279 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004280 wpas_notify_network_added(wpa_s, ssid);
4281 ssid->disabled = 1;
4282 wpa_config_set_network_defaults(ssid);
4283
4284 return ssid;
4285}
4286
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004287
Roshan Pius950bec92016-07-19 09:49:24 -07004288/**
4289 * wpa_supplicant_remove_network - Remove a configured network based on id
4290 * @wpa_s: wpa_supplicant structure for a network interface
4291 * @id: Unique network id to search for
4292 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4293 * could not be removed
4294 *
4295 * This function performs the following operations:
4296 * 1. Removes the network.
4297 * 2. Send network removal notification.
4298 * 3. Update internal state machines.
4299 * 4. Stop any running sched scans.
4300 */
4301int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4302{
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004303 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004304 int was_disabled;
4305
4306 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004307 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004308 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004309 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004310
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004311 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004312#ifdef CONFIG_SME
4313 wpa_s->sme.prev_bssid_set = 0;
4314#endif /* CONFIG_SME */
4315 /*
4316 * Invalidate the EAP session cache if the current or
4317 * previously used network is removed.
4318 */
4319 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4320 }
4321
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004322 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004323 wpa_sm_set_config(wpa_s->wpa, NULL);
4324 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4325
4326 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4327 wpa_s->own_disconnect_req = 1;
4328 wpa_supplicant_deauthenticate(wpa_s,
4329 WLAN_REASON_DEAUTH_LEAVING);
4330 }
4331
4332 was_disabled = ssid->disabled;
4333
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004334 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004335 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004336
4337 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004338 wpa_printf(MSG_DEBUG,
4339 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004340 wpa_supplicant_cancel_sched_scan(wpa_s);
4341 wpa_supplicant_req_scan(wpa_s, 0, 0);
4342 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004343
Roshan Pius950bec92016-07-19 09:49:24 -07004344 return 0;
4345}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004346
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004347
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004349 * wpa_supplicant_remove_all_networks - Remove all configured networks
4350 * @wpa_s: wpa_supplicant structure for a network interface
4351 * Returns: 0 on success (errors are currently ignored)
4352 *
4353 * This function performs the following operations:
4354 * 1. Remove all networks.
4355 * 2. Send network removal notifications.
4356 * 3. Update internal state machines.
4357 * 4. Stop any running sched scans.
4358 */
4359int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4360{
4361 struct wpa_ssid *ssid;
4362
4363 if (wpa_s->sched_scanning)
4364 wpa_supplicant_cancel_sched_scan(wpa_s);
4365
4366 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4367 if (wpa_s->current_ssid) {
4368#ifdef CONFIG_SME
4369 wpa_s->sme.prev_bssid_set = 0;
4370#endif /* CONFIG_SME */
4371 wpa_sm_set_config(wpa_s->wpa, NULL);
4372 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4373 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4374 wpa_s->own_disconnect_req = 1;
4375 wpa_supplicant_deauthenticate(
4376 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4377 }
4378 ssid = wpa_s->conf->ssid;
4379 while (ssid) {
4380 struct wpa_ssid *remove_ssid = ssid;
4381 int id;
4382
4383 id = ssid->id;
4384 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004385 wpas_notify_network_removed(wpa_s, remove_ssid);
4386 wpa_config_remove_network(wpa_s->conf, id);
4387 }
4388 return 0;
4389}
4390
4391
4392/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004393 * wpa_supplicant_enable_network - Mark a configured network as enabled
4394 * @wpa_s: wpa_supplicant structure for a network interface
4395 * @ssid: wpa_ssid structure for a configured network or %NULL
4396 *
4397 * Enables the specified network or all networks if no network specified.
4398 */
4399void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4400 struct wpa_ssid *ssid)
4401{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004402 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004403 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4404 wpa_supplicant_enable_one_network(wpa_s, ssid);
4405 } else
4406 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004408 if (wpa_s->reassociate && !wpa_s->disconnected &&
4409 (!wpa_s->current_ssid ||
4410 wpa_s->wpa_state == WPA_DISCONNECTED ||
4411 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004412 if (wpa_s->sched_scanning) {
4413 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4414 "new network to scan filters");
4415 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004416 }
4417
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004418 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4419 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004420 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004421 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004422 }
4423}
4424
4425
4426/**
4427 * wpa_supplicant_disable_network - Mark a configured network as disabled
4428 * @wpa_s: wpa_supplicant structure for a network interface
4429 * @ssid: wpa_ssid structure for a configured network or %NULL
4430 *
4431 * Disables the specified network or all networks if no network specified.
4432 */
4433void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4434 struct wpa_ssid *ssid)
4435{
4436 struct wpa_ssid *other_ssid;
4437 int was_disabled;
4438
4439 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004440 if (wpa_s->sched_scanning)
4441 wpa_supplicant_cancel_sched_scan(wpa_s);
4442
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4444 other_ssid = other_ssid->next) {
4445 was_disabled = other_ssid->disabled;
4446 if (was_disabled == 2)
4447 continue; /* do not change persistent P2P group
4448 * data */
4449
4450 other_ssid->disabled = 1;
4451
4452 if (was_disabled != other_ssid->disabled)
4453 wpas_notify_network_enabled_changed(
4454 wpa_s, other_ssid);
4455 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004456 if (wpa_s->current_ssid) {
4457 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4458 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004459 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004461 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004462 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004463 if (ssid == wpa_s->current_ssid) {
4464 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4465 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004466 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004468 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469
4470 was_disabled = ssid->disabled;
4471
4472 ssid->disabled = 1;
4473
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004474 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004475 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004476 if (wpa_s->sched_scanning) {
4477 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4478 "to remove network from filters");
4479 wpa_supplicant_cancel_sched_scan(wpa_s);
4480 wpa_supplicant_req_scan(wpa_s, 0, 0);
4481 }
4482 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483 }
4484}
4485
4486
4487/**
4488 * wpa_supplicant_select_network - Attempt association with a network
4489 * @wpa_s: wpa_supplicant structure for a network interface
4490 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4491 */
4492void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4493 struct wpa_ssid *ssid)
4494{
4495
4496 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004497 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004498
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004499 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004500 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4501 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004502 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004504 disconnected = 1;
4505 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004506
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004507 if (ssid)
4508 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4509
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004510 /*
4511 * Mark all other networks disabled or mark all networks enabled if no
4512 * network specified.
4513 */
4514 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4515 other_ssid = other_ssid->next) {
4516 int was_disabled = other_ssid->disabled;
4517 if (was_disabled == 2)
4518 continue; /* do not change persistent P2P group data */
4519
4520 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004521 if (was_disabled && !other_ssid->disabled)
4522 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004523
4524 if (was_disabled != other_ssid->disabled)
4525 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4526 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004527
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004528 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4529 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004530 /* We are already associated with the selected network */
4531 wpa_printf(MSG_DEBUG, "Already associated with the "
4532 "selected network - do nothing");
4533 return;
4534 }
4535
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004536 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004537 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004538 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004539 wpa_s->connect_without_scan =
4540 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004541
4542 /*
4543 * Don't optimize next scan freqs since a new ESS has been
4544 * selected.
4545 */
4546 os_free(wpa_s->next_scan_freqs);
4547 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004548 } else {
4549 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004550 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 wpa_s->disconnected = 0;
4553 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004554 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004555 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004556 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004557 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004558 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4559 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004560
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004561 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004562 wpa_supplicant_fast_associate(wpa_s) != 1) {
4563 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004564 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004565 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004566 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004567
4568 if (ssid)
4569 wpas_notify_network_selected(wpa_s, ssid);
4570}
4571
4572
4573/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004574 * wpas_remove_cred - Remove the specified credential and all the network
4575 * entries created based on the removed credential
4576 * @wpa_s: wpa_supplicant structure for a network interface
4577 * @cred: The credential to remove
4578 * Returns: 0 on success, -1 on failure
4579 */
4580int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4581{
4582 struct wpa_ssid *ssid, *next;
4583 int id;
4584
4585 if (!cred) {
4586 wpa_printf(MSG_DEBUG, "Could not find cred");
4587 return -1;
4588 }
4589
4590 id = cred->id;
4591 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4592 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4593 return -1;
4594 }
4595
4596 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4597
4598 /* Remove any network entry created based on the removed credential */
4599 ssid = wpa_s->conf->ssid;
4600 while (ssid) {
4601 next = ssid->next;
4602
4603 if (ssid->parent_cred == cred) {
4604 wpa_printf(MSG_DEBUG,
4605 "Remove network id %d since it used the removed credential",
4606 ssid->id);
4607 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4608 -1) {
4609 wpa_printf(MSG_DEBUG,
4610 "Could not find network id=%d",
4611 ssid->id);
4612 }
4613 }
4614
4615 ssid = next;
4616 }
4617
4618 return 0;
4619}
4620
4621
4622/**
4623 * wpas_remove_cred - Remove all the Interworking credentials
4624 * @wpa_s: wpa_supplicant structure for a network interface
4625 * Returns: 0 on success, -1 on failure
4626 */
4627int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4628{
4629 int res, ret = 0;
4630 struct wpa_cred *cred, *prev;
4631
4632 cred = wpa_s->conf->cred;
4633 while (cred) {
4634 prev = cred;
4635 cred = cred->next;
4636 res = wpas_remove_cred(wpa_s, prev);
4637 if (res < 0) {
4638 wpa_printf(MSG_DEBUG,
4639 "Removal of all credentials failed - failed to remove credential id=%d",
4640 prev->id);
4641 ret = -1;
4642 }
4643 }
4644
4645 return ret;
4646}
4647
4648
4649/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004650 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4651 * @wpa_s: wpa_supplicant structure for a network interface
4652 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4653 * @pkcs11_module_path: PKCS #11 module path or NULL
4654 * Returns: 0 on success; -1 on failure
4655 *
4656 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4657 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4658 * module path fails the paths will be reset to the default value (NULL).
4659 */
4660int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4661 const char *pkcs11_engine_path,
4662 const char *pkcs11_module_path)
4663{
4664 char *pkcs11_engine_path_copy = NULL;
4665 char *pkcs11_module_path_copy = NULL;
4666
4667 if (pkcs11_engine_path != NULL) {
4668 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4669 if (pkcs11_engine_path_copy == NULL)
4670 return -1;
4671 }
4672 if (pkcs11_module_path != NULL) {
4673 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004674 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004675 os_free(pkcs11_engine_path_copy);
4676 return -1;
4677 }
4678 }
4679
4680 os_free(wpa_s->conf->pkcs11_engine_path);
4681 os_free(wpa_s->conf->pkcs11_module_path);
4682 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4683 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4684
4685 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4686 eapol_sm_deinit(wpa_s->eapol);
4687 wpa_s->eapol = NULL;
4688 if (wpa_supplicant_init_eapol(wpa_s)) {
4689 /* Error -> Reset paths to the default value (NULL) once. */
4690 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4691 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4692 NULL);
4693
4694 return -1;
4695 }
4696 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4697
4698 return 0;
4699}
4700
4701
4702/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4704 * @wpa_s: wpa_supplicant structure for a network interface
4705 * @ap_scan: AP scan mode
4706 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4707 *
4708 */
4709int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4710{
4711
4712 int old_ap_scan;
4713
4714 if (ap_scan < 0 || ap_scan > 2)
4715 return -1;
4716
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004717 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4718 wpa_printf(MSG_INFO,
4719 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4720 }
4721
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004722#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004723 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4724 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4725 wpa_s->wpa_state < WPA_COMPLETED) {
4726 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4727 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004728 return 0;
4729 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004730#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004732 old_ap_scan = wpa_s->conf->ap_scan;
4733 wpa_s->conf->ap_scan = ap_scan;
4734
4735 if (old_ap_scan != wpa_s->conf->ap_scan)
4736 wpas_notify_ap_scan_changed(wpa_s);
4737
4738 return 0;
4739}
4740
4741
4742/**
4743 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4744 * @wpa_s: wpa_supplicant structure for a network interface
4745 * @expire_age: Expiration age in seconds
4746 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4747 *
4748 */
4749int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4750 unsigned int bss_expire_age)
4751{
4752 if (bss_expire_age < 10) {
4753 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4754 bss_expire_age);
4755 return -1;
4756 }
4757 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4758 bss_expire_age);
4759 wpa_s->conf->bss_expiration_age = bss_expire_age;
4760
4761 return 0;
4762}
4763
4764
4765/**
4766 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4767 * @wpa_s: wpa_supplicant structure for a network interface
4768 * @expire_count: number of scans after which an unseen BSS is reclaimed
4769 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4770 *
4771 */
4772int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4773 unsigned int bss_expire_count)
4774{
4775 if (bss_expire_count < 1) {
4776 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4777 bss_expire_count);
4778 return -1;
4779 }
4780 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4781 bss_expire_count);
4782 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4783
4784 return 0;
4785}
4786
4787
4788/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004789 * wpa_supplicant_set_scan_interval - Set scan interval
4790 * @wpa_s: wpa_supplicant structure for a network interface
4791 * @scan_interval: scan interval in seconds
4792 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4793 *
4794 */
4795int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4796 int scan_interval)
4797{
4798 if (scan_interval < 0) {
4799 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4800 scan_interval);
4801 return -1;
4802 }
4803 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4804 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004805 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004806
4807 return 0;
4808}
4809
4810
4811/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004812 * wpa_supplicant_set_debug_params - Set global debug params
4813 * @global: wpa_global structure
4814 * @debug_level: debug level
4815 * @debug_timestamp: determines if show timestamp in debug data
4816 * @debug_show_keys: determines if show keys in debug data
4817 * Returns: 0 if succeed or -1 if debug_level has wrong value
4818 */
4819int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4820 int debug_timestamp, int debug_show_keys)
4821{
4822
4823 int old_level, old_timestamp, old_show_keys;
4824
4825 /* check for allowed debuglevels */
4826 if (debug_level != MSG_EXCESSIVE &&
4827 debug_level != MSG_MSGDUMP &&
4828 debug_level != MSG_DEBUG &&
4829 debug_level != MSG_INFO &&
4830 debug_level != MSG_WARNING &&
4831 debug_level != MSG_ERROR)
4832 return -1;
4833
4834 old_level = wpa_debug_level;
4835 old_timestamp = wpa_debug_timestamp;
4836 old_show_keys = wpa_debug_show_keys;
4837
4838 wpa_debug_level = debug_level;
4839 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4840 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4841
4842 if (wpa_debug_level != old_level)
4843 wpas_notify_debug_level_changed(global);
4844 if (wpa_debug_timestamp != old_timestamp)
4845 wpas_notify_debug_timestamp_changed(global);
4846 if (wpa_debug_show_keys != old_show_keys)
4847 wpas_notify_debug_show_keys_changed(global);
4848
4849 return 0;
4850}
4851
4852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004853#ifdef CONFIG_OWE
4854static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4855 const u8 *entry_ssid, size_t entry_ssid_len)
4856{
4857 const u8 *owe, *pos, *end;
4858 u8 ssid_len;
4859 struct wpa_bss *bss;
4860
4861 /* Check network profile SSID aganst the SSID in the
4862 * OWE Transition Mode element. */
4863
4864 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4865 if (!bss)
4866 return 0;
4867
4868 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4869 if (!owe)
4870 return 0;
4871
4872 pos = owe + 6;
4873 end = owe + 2 + owe[1];
4874
4875 if (end - pos < ETH_ALEN + 1)
4876 return 0;
4877 pos += ETH_ALEN;
4878 ssid_len = *pos++;
4879 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4880 return 0;
4881
4882 return entry_ssid_len == ssid_len &&
4883 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4884}
4885#endif /* CONFIG_OWE */
4886
4887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004888/**
4889 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4890 * @wpa_s: Pointer to wpa_supplicant data
4891 * Returns: A pointer to the current network structure or %NULL on failure
4892 */
4893struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4894{
4895 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004896 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897 int res;
4898 size_t ssid_len;
4899 u8 bssid[ETH_ALEN];
4900 int wired;
4901
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004902 res = wpa_drv_get_ssid(wpa_s, ssid);
4903 if (res < 0) {
4904 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4905 "driver");
4906 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004908 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004910 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004911 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4912 "driver");
4913 return NULL;
4914 }
4915
4916 wired = wpa_s->conf->ap_scan == 0 &&
4917 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4918
4919 entry = wpa_s->conf->ssid;
4920 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004921 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004923 (!entry->ssid ||
4924 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4925 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004926 (!entry->bssid_set ||
4927 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4928 return entry;
4929#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004930 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004931 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4932 (entry->ssid == NULL || entry->ssid_len == 0) &&
4933 (!entry->bssid_set ||
4934 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4935 return entry;
4936#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004937
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004938#ifdef CONFIG_OWE
4939 if (!wpas_network_disabled(wpa_s, entry) &&
4940 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4941 entry->ssid_len) &&
4942 (!entry->bssid_set ||
4943 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4944 return entry;
4945#endif /* CONFIG_OWE */
4946
Dmitry Shmidt04949592012-07-19 12:16:46 -07004947 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004948 entry->ssid_len == 0 &&
4949 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4950 return entry;
4951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004952 entry = entry->next;
4953 }
4954
4955 return NULL;
4956}
4957
4958
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004959static int select_driver(struct wpa_supplicant *wpa_s, int i)
4960{
4961 struct wpa_global *global = wpa_s->global;
4962
4963 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004964 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004965 if (global->drv_priv[i] == NULL) {
4966 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4967 "'%s'", wpa_drivers[i]->name);
4968 return -1;
4969 }
4970 }
4971
4972 wpa_s->driver = wpa_drivers[i];
4973 wpa_s->global_drv_priv = global->drv_priv[i];
4974
4975 return 0;
4976}
4977
4978
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004979static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4980 const char *name)
4981{
4982 int i;
4983 size_t len;
4984 const char *pos, *driver = name;
4985
4986 if (wpa_s == NULL)
4987 return -1;
4988
4989 if (wpa_drivers[0] == NULL) {
4990 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4991 "wpa_supplicant");
4992 return -1;
4993 }
4994
4995 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004996 /* Default to first successful driver in the list */
4997 for (i = 0; wpa_drivers[i]; i++) {
4998 if (select_driver(wpa_s, i) == 0)
4999 return 0;
5000 }
5001 /* Drivers have each reported failure, so no wpa_msg() here. */
5002 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005003 }
5004
5005 do {
5006 pos = os_strchr(driver, ',');
5007 if (pos)
5008 len = pos - driver;
5009 else
5010 len = os_strlen(driver);
5011
5012 for (i = 0; wpa_drivers[i]; i++) {
5013 if (os_strlen(wpa_drivers[i]->name) == len &&
5014 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005015 0) {
5016 /* First driver that succeeds wins */
5017 if (select_driver(wpa_s, i) == 0)
5018 return 0;
5019 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005020 }
5021
5022 driver = pos + 1;
5023 } while (pos);
5024
5025 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5026 return -1;
5027}
5028
5029
5030/**
5031 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5032 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5033 * with struct wpa_driver_ops::init()
5034 * @src_addr: Source address of the EAPOL frame
5035 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5036 * @len: Length of the EAPOL data
5037 *
5038 * This function is called for each received EAPOL frame. Most driver
5039 * interfaces rely on more generic OS mechanism for receiving frames through
5040 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5041 * take care of received EAPOL frames and deliver them to the core supplicant
5042 * code by calling this function.
5043 */
5044void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
5045 const u8 *buf, size_t len)
5046{
5047 struct wpa_supplicant *wpa_s = ctx;
5048
5049 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
5050 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5051
Hai Shalomc1a21442022-02-04 13:43:00 -08005052 if (wpa_s->own_disconnect_req) {
5053 wpa_printf(MSG_DEBUG,
5054 "Drop received EAPOL frame as we are disconnecting");
5055 return;
5056 }
5057
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005058#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005059 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5060 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005061 if (wpa_s->ignore_auth_resp) {
5062 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5063 return;
5064 }
5065#endif /* CONFIG_TESTING_OPTIONS */
5066
Jouni Malinena05074c2012-12-21 21:35:35 +02005067 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5068 (wpa_s->last_eapol_matches_bssid &&
5069#ifdef CONFIG_AP
5070 !wpa_s->ap_iface &&
5071#endif /* CONFIG_AP */
5072 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005073 /*
5074 * There is possible race condition between receiving the
5075 * association event and the EAPOL frame since they are coming
5076 * through different paths from the driver. In order to avoid
5077 * issues in trying to process the EAPOL frame before receiving
5078 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005079 * the association event is received. This may also be needed in
5080 * driver-based roaming case, so also use src_addr != BSSID as a
5081 * trigger if we have previously confirmed that the
5082 * Authenticator uses BSSID as the src_addr (which is not the
5083 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005084 */
5085 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005086 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5087 wpa_supplicant_state_txt(wpa_s->wpa_state),
5088 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005089 wpabuf_free(wpa_s->pending_eapol_rx);
5090 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5091 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005092 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005093 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5094 ETH_ALEN);
5095 }
5096 return;
5097 }
5098
Jouni Malinena05074c2012-12-21 21:35:35 +02005099 wpa_s->last_eapol_matches_bssid =
5100 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102#ifdef CONFIG_AP
5103 if (wpa_s->ap_iface) {
5104 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
5105 return;
5106 }
5107#endif /* CONFIG_AP */
5108
5109 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5110 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5111 "no key management is configured");
5112 return;
5113 }
5114
5115 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005116 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005117 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5118 wpa_s->wpa_state != WPA_COMPLETED) &&
5119 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005120 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005121 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005122 int timeout = 10;
5123
5124 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5125 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5126 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5127 /* Use longer timeout for IEEE 802.1X/EAP */
5128 timeout = 70;
5129 }
5130
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005131#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005132 if (wpa_s->current_ssid && wpa_s->current_bss &&
5133 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5134 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5135 /*
5136 * Use shorter timeout if going through WPS AP iteration
5137 * for PIN config method with an AP that does not
5138 * advertise Selected Registrar.
5139 */
5140 struct wpabuf *wps_ie;
5141
5142 wps_ie = wpa_bss_get_vendor_ie_multi(
5143 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5144 if (wps_ie &&
5145 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5146 timeout = 10;
5147 wpabuf_free(wps_ie);
5148 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005149#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005150
5151 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005152 }
5153 wpa_s->eapol_received++;
5154
5155 if (wpa_s->countermeasures) {
5156 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5157 "EAPOL packet");
5158 return;
5159 }
5160
5161#ifdef CONFIG_IBSS_RSN
5162 if (wpa_s->current_ssid &&
5163 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
5164 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
5165 return;
5166 }
5167#endif /* CONFIG_IBSS_RSN */
5168
5169 /* Source address of the incoming EAPOL frame could be compared to the
5170 * current BSSID. However, it is possible that a centralized
5171 * Authenticator could be using another MAC address than the BSSID of
5172 * an AP, so just allow any address to be used for now. The replies are
5173 * still sent to the current BSSID (if available), though. */
5174
5175 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5176 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005177 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5178 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005179 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
5180 return;
5181 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005182 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005183 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
5184 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5185 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005186 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005187 * handshake processing which would normally set portValid. We
5188 * need this to allow the EAPOL state machines to be completed
5189 * without going through EAPOL-Key handshake.
5190 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005191 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192 }
5193}
5194
5195
Hai Shalomb755a2a2020-04-23 21:49:02 -07005196static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5197{
5198 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5199 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5200}
5201
5202
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005203int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005204{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005205 if ((!wpa_s->p2p_mgmt ||
5206 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5207 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005208 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005209 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5210 wpa_drv_get_mac_addr(wpa_s),
5211 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005212 wpas_eapol_needs_l2_packet(wpa_s) ?
5213 wpa_supplicant_rx_eapol : NULL,
5214 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005215 if (wpa_s->l2 == NULL)
5216 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005217
5218 if (l2_packet_set_packet_filter(wpa_s->l2,
5219 L2_PACKET_FILTER_PKTTYPE))
5220 wpa_dbg(wpa_s, MSG_DEBUG,
5221 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005222
5223 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5224 wpa_msg(wpa_s, MSG_ERROR,
5225 "Failed to get own L2 address");
5226 return -1;
5227 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005228 } else {
5229 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5230 if (addr)
5231 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5232 }
5233
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005234 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005235 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005236
Hai Shalomc3565922019-10-28 11:58:20 -07005237#ifdef CONFIG_FST
5238 if (wpa_s->fst)
5239 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5240#endif /* CONFIG_FST */
5241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005242 return 0;
5243}
5244
5245
Dmitry Shmidt04949592012-07-19 12:16:46 -07005246static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5247 const u8 *buf, size_t len)
5248{
5249 struct wpa_supplicant *wpa_s = ctx;
5250 const struct l2_ethhdr *eth;
5251
5252 if (len < sizeof(*eth))
5253 return;
5254 eth = (const struct l2_ethhdr *) buf;
5255
5256 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5257 !(eth->h_dest[0] & 0x01)) {
5258 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5259 " (bridge - not for this interface - ignore)",
5260 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5261 return;
5262 }
5263
5264 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5265 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5266 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5267 len - sizeof(*eth));
5268}
5269
5270
Hai Shalom899fcc72020-10-19 14:38:18 -07005271int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5272 const char *bridge_ifname)
5273{
5274 if (wpa_s->wpa_state > WPA_SCANNING)
5275 return -EBUSY;
5276
5277 if (bridge_ifname &&
5278 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5279 return -EINVAL;
5280
5281 if (!bridge_ifname)
5282 bridge_ifname = "";
5283
5284 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5285 return 0;
5286
5287 if (wpa_s->l2_br) {
5288 l2_packet_deinit(wpa_s->l2_br);
5289 wpa_s->l2_br = NULL;
5290 }
5291
5292 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5293 sizeof(wpa_s->bridge_ifname));
5294
5295 if (wpa_s->bridge_ifname[0]) {
5296 wpa_dbg(wpa_s, MSG_DEBUG,
5297 "Receiving packets from bridge interface '%s'",
5298 wpa_s->bridge_ifname);
5299 wpa_s->l2_br = l2_packet_init_bridge(
5300 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5301 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5302 if (!wpa_s->l2_br) {
5303 wpa_msg(wpa_s, MSG_ERROR,
5304 "Failed to open l2_packet connection for the bridge interface '%s'",
5305 wpa_s->bridge_ifname);
5306 goto fail;
5307 }
5308 }
5309
5310#ifdef CONFIG_TDLS
5311 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5312 goto fail;
5313#endif /* CONFIG_TDLS */
5314
5315 return 0;
5316fail:
5317 wpa_s->bridge_ifname[0] = 0;
5318 if (wpa_s->l2_br) {
5319 l2_packet_deinit(wpa_s->l2_br);
5320 wpa_s->l2_br = NULL;
5321 }
5322#ifdef CONFIG_TDLS
5323 if (!wpa_s->p2p_mgmt)
5324 wpa_tdls_init(wpa_s->wpa);
5325#endif /* CONFIG_TDLS */
5326 return -EIO;
5327}
5328
5329
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005330/**
5331 * wpa_supplicant_driver_init - Initialize driver interface parameters
5332 * @wpa_s: Pointer to wpa_supplicant data
5333 * Returns: 0 on success, -1 on failure
5334 *
5335 * This function is called to initialize driver interface parameters.
5336 * wpa_drv_init() must have been called before this function to initialize the
5337 * driver interface.
5338 */
5339int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5340{
5341 static int interface_count = 0;
5342
5343 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5344 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005345
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005346 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5347 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005348 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005349 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5350
Hai Shalomb755a2a2020-04-23 21:49:02 -07005351 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005352 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5353 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005354 wpa_s->l2_br = l2_packet_init_bridge(
5355 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5356 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005357 if (wpa_s->l2_br == NULL) {
5358 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5359 "connection for the bridge interface '%s'",
5360 wpa_s->bridge_ifname);
5361 return -1;
5362 }
5363 }
5364
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005365 if (wpa_s->conf->ap_scan == 2 &&
5366 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5367 wpa_printf(MSG_INFO,
5368 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5369 }
5370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005371 wpa_clear_keys(wpa_s, NULL);
5372
5373 /* Make sure that TKIP countermeasures are not left enabled (could
5374 * happen if wpa_supplicant is killed during countermeasures. */
5375 wpa_drv_set_countermeasures(wpa_s, 0);
5376
5377 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5378 wpa_drv_flush_pmkid(wpa_s);
5379
5380 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005381 wpa_s->prev_scan_wildcard = 0;
5382
Dmitry Shmidt04949592012-07-19 12:16:46 -07005383 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005384 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5385 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5386 interface_count = 0;
5387 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005388#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005389 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005390 wpa_supplicant_delayed_sched_scan(wpa_s,
5391 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005392 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005393 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005394 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005395#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005396 interface_count++;
5397 } else
5398 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5399
5400 return 0;
5401}
5402
5403
5404static int wpa_supplicant_daemon(const char *pid_file)
5405{
5406 wpa_printf(MSG_DEBUG, "Daemonize..");
5407 return os_daemonize(pid_file);
5408}
5409
5410
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005411static struct wpa_supplicant *
5412wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005413{
5414 struct wpa_supplicant *wpa_s;
5415
5416 wpa_s = os_zalloc(sizeof(*wpa_s));
5417 if (wpa_s == NULL)
5418 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005419 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005420 wpa_s->scan_interval = 5;
5421 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005422 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005423 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005424 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005425 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005426
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005427 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005428 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005429#ifdef CONFIG_TESTING_OPTIONS
5430 dl_list_init(&wpa_s->drv_signal_override);
5431#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005432 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434 return wpa_s;
5435}
5436
5437
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005438#ifdef CONFIG_HT_OVERRIDES
5439
5440static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5441 struct ieee80211_ht_capabilities *htcaps,
5442 struct ieee80211_ht_capabilities *htcaps_mask,
5443 const char *ht_mcs)
5444{
5445 /* parse ht_mcs into hex array */
5446 int i;
5447 const char *tmp = ht_mcs;
5448 char *end = NULL;
5449
5450 /* If ht_mcs is null, do not set anything */
5451 if (!ht_mcs)
5452 return 0;
5453
5454 /* This is what we are setting in the kernel */
5455 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5456
5457 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5458
5459 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005460 long v;
5461
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005462 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005463 v = strtol(tmp, &end, 16);
5464
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005465 if (errno == 0) {
5466 wpa_msg(wpa_s, MSG_DEBUG,
5467 "htcap value[%i]: %ld end: %p tmp: %p",
5468 i, v, end, tmp);
5469 if (end == tmp)
5470 break;
5471
5472 htcaps->supported_mcs_set[i] = v;
5473 tmp = end;
5474 } else {
5475 wpa_msg(wpa_s, MSG_ERROR,
5476 "Failed to parse ht-mcs: %s, error: %s\n",
5477 ht_mcs, strerror(errno));
5478 return -1;
5479 }
5480 }
5481
5482 /*
5483 * If we were able to parse any values, then set mask for the MCS set.
5484 */
5485 if (i) {
5486 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5487 IEEE80211_HT_MCS_MASK_LEN - 1);
5488 /* skip the 3 reserved bits */
5489 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5490 0x1f;
5491 }
5492
5493 return 0;
5494}
5495
5496
5497static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5498 struct ieee80211_ht_capabilities *htcaps,
5499 struct ieee80211_ht_capabilities *htcaps_mask,
5500 int disabled)
5501{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005502 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005503
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005504 if (disabled == -1)
5505 return 0;
5506
Hai Shalom74f70d42019-02-11 14:42:39 -08005507 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5508
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005509 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5510 htcaps_mask->ht_capabilities_info |= msk;
5511 if (disabled)
5512 htcaps->ht_capabilities_info &= msk;
5513 else
5514 htcaps->ht_capabilities_info |= msk;
5515
5516 return 0;
5517}
5518
5519
5520static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5521 struct ieee80211_ht_capabilities *htcaps,
5522 struct ieee80211_ht_capabilities *htcaps_mask,
5523 int factor)
5524{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005525 if (factor == -1)
5526 return 0;
5527
Hai Shalom74f70d42019-02-11 14:42:39 -08005528 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5529
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005530 if (factor < 0 || factor > 3) {
5531 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5532 "Must be 0-3 or -1", factor);
5533 return -EINVAL;
5534 }
5535
5536 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5537 htcaps->a_mpdu_params &= ~0x3;
5538 htcaps->a_mpdu_params |= factor & 0x3;
5539
5540 return 0;
5541}
5542
5543
5544static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5545 struct ieee80211_ht_capabilities *htcaps,
5546 struct ieee80211_ht_capabilities *htcaps_mask,
5547 int density)
5548{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005549 if (density == -1)
5550 return 0;
5551
Hai Shalom74f70d42019-02-11 14:42:39 -08005552 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5553
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005554 if (density < 0 || density > 7) {
5555 wpa_msg(wpa_s, MSG_ERROR,
5556 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5557 density);
5558 return -EINVAL;
5559 }
5560
5561 htcaps_mask->a_mpdu_params |= 0x1C;
5562 htcaps->a_mpdu_params &= ~(0x1C);
5563 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5564
5565 return 0;
5566}
5567
5568
5569static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5570 struct ieee80211_ht_capabilities *htcaps,
5571 struct ieee80211_ht_capabilities *htcaps_mask,
5572 int disabled)
5573{
Hai Shalom74f70d42019-02-11 14:42:39 -08005574 if (disabled)
5575 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005576
Paul Stewart092955c2017-02-06 09:13:09 -08005577 set_disable_ht40(htcaps, disabled);
5578 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005579
5580 return 0;
5581}
5582
5583
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005584static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5585 struct ieee80211_ht_capabilities *htcaps,
5586 struct ieee80211_ht_capabilities *htcaps_mask,
5587 int disabled)
5588{
5589 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005590 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5591 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005592
Hai Shalom74f70d42019-02-11 14:42:39 -08005593 if (disabled)
5594 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005595
5596 if (disabled)
5597 htcaps->ht_capabilities_info &= ~msk;
5598 else
5599 htcaps->ht_capabilities_info |= msk;
5600
5601 htcaps_mask->ht_capabilities_info |= msk;
5602
5603 return 0;
5604}
5605
5606
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005607static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5608 struct ieee80211_ht_capabilities *htcaps,
5609 struct ieee80211_ht_capabilities *htcaps_mask,
5610 int disabled)
5611{
5612 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005613 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005614
Hai Shalom74f70d42019-02-11 14:42:39 -08005615 if (disabled)
5616 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005617
5618 if (disabled)
5619 htcaps->ht_capabilities_info &= ~msk;
5620 else
5621 htcaps->ht_capabilities_info |= msk;
5622
5623 htcaps_mask->ht_capabilities_info |= msk;
5624
5625 return 0;
5626}
5627
5628
Hai Shalom74f70d42019-02-11 14:42:39 -08005629static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5630 struct ieee80211_ht_capabilities *htcaps,
5631 struct ieee80211_ht_capabilities *htcaps_mask,
5632 int tx_stbc)
5633{
5634 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5635
5636 if (tx_stbc == -1)
5637 return 0;
5638
5639 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5640
5641 if (tx_stbc < 0 || tx_stbc > 1) {
5642 wpa_msg(wpa_s, MSG_ERROR,
5643 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5644 return -EINVAL;
5645 }
5646
5647 htcaps_mask->ht_capabilities_info |= msk;
5648 htcaps->ht_capabilities_info &= ~msk;
5649 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5650
5651 return 0;
5652}
5653
5654
5655static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5656 struct ieee80211_ht_capabilities *htcaps,
5657 struct ieee80211_ht_capabilities *htcaps_mask,
5658 int rx_stbc)
5659{
5660 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5661
5662 if (rx_stbc == -1)
5663 return 0;
5664
5665 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5666
5667 if (rx_stbc < 0 || rx_stbc > 3) {
5668 wpa_msg(wpa_s, MSG_ERROR,
5669 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5670 return -EINVAL;
5671 }
5672
5673 htcaps_mask->ht_capabilities_info |= msk;
5674 htcaps->ht_capabilities_info &= ~msk;
5675 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5676
5677 return 0;
5678}
5679
5680
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005681void wpa_supplicant_apply_ht_overrides(
5682 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5683 struct wpa_driver_associate_params *params)
5684{
5685 struct ieee80211_ht_capabilities *htcaps;
5686 struct ieee80211_ht_capabilities *htcaps_mask;
5687
5688 if (!ssid)
5689 return;
5690
5691 params->disable_ht = ssid->disable_ht;
5692 if (!params->htcaps || !params->htcaps_mask)
5693 return;
5694
5695 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5696 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5697 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5698 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5699 ssid->disable_max_amsdu);
5700 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5701 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5702 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005703 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005704 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005705 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5706 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005707
5708 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005709 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005710 htcaps->ht_capabilities_info |= bit;
5711 htcaps_mask->ht_capabilities_info |= bit;
5712 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005713}
5714
5715#endif /* CONFIG_HT_OVERRIDES */
5716
5717
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005718#ifdef CONFIG_VHT_OVERRIDES
5719void wpa_supplicant_apply_vht_overrides(
5720 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5721 struct wpa_driver_associate_params *params)
5722{
5723 struct ieee80211_vht_capabilities *vhtcaps;
5724 struct ieee80211_vht_capabilities *vhtcaps_mask;
5725
5726 if (!ssid)
5727 return;
5728
5729 params->disable_vht = ssid->disable_vht;
5730
5731 vhtcaps = (void *) params->vhtcaps;
5732 vhtcaps_mask = (void *) params->vhtcaps_mask;
5733
5734 if (!vhtcaps || !vhtcaps_mask)
5735 return;
5736
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005737 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5738 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005739
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005740#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005741 if (ssid->disable_sgi) {
5742 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5743 VHT_CAP_SHORT_GI_160);
5744 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5745 VHT_CAP_SHORT_GI_160);
5746 wpa_msg(wpa_s, MSG_DEBUG,
5747 "disable-sgi override specified, vht-caps: 0x%x",
5748 vhtcaps->vht_capabilities_info);
5749 }
5750
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005751 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005752 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5753 int max_ampdu;
5754
5755 max_ampdu = (ssid->vht_capa &
5756 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5757 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005758
5759 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5760 wpa_set_ampdu_factor(wpa_s,
5761 (void *) params->htcaps,
5762 (void *) params->htcaps_mask,
5763 max_ampdu);
5764 }
5765#endif /* CONFIG_HT_OVERRIDES */
5766
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005767#define OVERRIDE_MCS(i) \
5768 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5769 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005770 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005771 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005772 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5773 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005774 } \
5775 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5776 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005777 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005778 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005779 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5780 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005781 }
5782
5783 OVERRIDE_MCS(1);
5784 OVERRIDE_MCS(2);
5785 OVERRIDE_MCS(3);
5786 OVERRIDE_MCS(4);
5787 OVERRIDE_MCS(5);
5788 OVERRIDE_MCS(6);
5789 OVERRIDE_MCS(7);
5790 OVERRIDE_MCS(8);
5791}
5792#endif /* CONFIG_VHT_OVERRIDES */
5793
5794
Hai Shalomfdcde762020-04-02 11:19:20 -07005795#ifdef CONFIG_HE_OVERRIDES
5796void wpa_supplicant_apply_he_overrides(
5797 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5798 struct wpa_driver_associate_params *params)
5799{
5800 if (!ssid)
5801 return;
5802
5803 params->disable_he = ssid->disable_he;
5804}
5805#endif /* CONFIG_HE_OVERRIDES */
5806
5807
Dmitry Shmidt04949592012-07-19 12:16:46 -07005808static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5809{
5810#ifdef PCSC_FUNCS
5811 size_t len;
5812
5813 if (!wpa_s->conf->pcsc_reader)
5814 return 0;
5815
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005816 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005817 if (!wpa_s->scard)
5818 return 1;
5819
5820 if (wpa_s->conf->pcsc_pin &&
5821 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5822 scard_deinit(wpa_s->scard);
5823 wpa_s->scard = NULL;
5824 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5825 return -1;
5826 }
5827
5828 len = sizeof(wpa_s->imsi) - 1;
5829 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5830 scard_deinit(wpa_s->scard);
5831 wpa_s->scard = NULL;
5832 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5833 return -1;
5834 }
5835 wpa_s->imsi[len] = '\0';
5836
5837 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5838
5839 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5840 wpa_s->imsi, wpa_s->mnc_len);
5841
5842 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5843 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5844#endif /* PCSC_FUNCS */
5845
5846 return 0;
5847}
5848
5849
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005850int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5851{
5852 char *val, *pos;
5853
5854 ext_password_deinit(wpa_s->ext_pw);
5855 wpa_s->ext_pw = NULL;
5856 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5857
5858 if (!wpa_s->conf->ext_password_backend)
5859 return 0;
5860
5861 val = os_strdup(wpa_s->conf->ext_password_backend);
5862 if (val == NULL)
5863 return -1;
5864 pos = os_strchr(val, ':');
5865 if (pos)
5866 *pos++ = '\0';
5867
5868 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5869
5870 wpa_s->ext_pw = ext_password_init(val, pos);
5871 os_free(val);
5872 if (wpa_s->ext_pw == NULL) {
5873 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5874 return -1;
5875 }
5876 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5877
5878 return 0;
5879}
5880
5881
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005882#ifdef CONFIG_FST
5883
5884static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5885{
5886 struct wpa_supplicant *wpa_s = ctx;
5887
5888 return (is_zero_ether_addr(wpa_s->bssid) ||
5889 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5890}
5891
5892
5893static void wpas_fst_get_channel_info_cb(void *ctx,
5894 enum hostapd_hw_mode *hw_mode,
5895 u8 *channel)
5896{
5897 struct wpa_supplicant *wpa_s = ctx;
5898
5899 if (wpa_s->current_bss) {
5900 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5901 channel);
5902 } else if (wpa_s->hw.num_modes) {
5903 *hw_mode = wpa_s->hw.modes[0].mode;
5904 } else {
5905 WPA_ASSERT(0);
5906 *hw_mode = 0;
5907 }
5908}
5909
5910
5911static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5912{
5913 struct wpa_supplicant *wpa_s = ctx;
5914
5915 *modes = wpa_s->hw.modes;
5916 return wpa_s->hw.num_modes;
5917}
5918
5919
5920static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5921{
5922 struct wpa_supplicant *wpa_s = ctx;
5923
5924 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5925 wpa_s->fst_ies = fst_ies;
5926}
5927
5928
5929static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5930{
5931 struct wpa_supplicant *wpa_s = ctx;
5932
Paul Stewart092955c2017-02-06 09:13:09 -08005933 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5934 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5935 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5936 return -1;
5937 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005938 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005939 wpa_s->own_addr, wpa_s->bssid,
5940 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005941 0);
5942}
5943
5944
5945static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5946{
5947 struct wpa_supplicant *wpa_s = ctx;
5948
5949 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5950 return wpa_s->received_mb_ies;
5951}
5952
5953
5954static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5955 const u8 *buf, size_t size)
5956{
5957 struct wpa_supplicant *wpa_s = ctx;
5958 struct mb_ies_info info;
5959
5960 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5961
5962 if (!mb_ies_info_by_ies(&info, buf, size)) {
5963 wpabuf_free(wpa_s->received_mb_ies);
5964 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5965 }
5966}
5967
5968
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005969static const u8 * wpas_fst_get_peer_first(void *ctx,
5970 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005971 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005972{
5973 struct wpa_supplicant *wpa_s = ctx;
5974
5975 *get_ctx = NULL;
5976 if (!is_zero_ether_addr(wpa_s->bssid))
5977 return (wpa_s->received_mb_ies || !mb_only) ?
5978 wpa_s->bssid : NULL;
5979 return NULL;
5980}
5981
5982
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005983static const u8 * wpas_fst_get_peer_next(void *ctx,
5984 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005985 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005986{
5987 return NULL;
5988}
5989
5990void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5991 struct fst_wpa_obj *iface_obj)
5992{
5993 iface_obj->ctx = wpa_s;
5994 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5995 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5996 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5997 iface_obj->set_ies = wpas_fst_set_ies_cb;
5998 iface_obj->send_action = wpas_fst_send_action_cb;
5999 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6000 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6001 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6002 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6003}
6004#endif /* CONFIG_FST */
6005
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006006static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006007 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006008{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006009 struct wowlan_triggers *triggers;
6010 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006011
6012 if (!wpa_s->conf->wowlan_triggers)
6013 return 0;
6014
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006015 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6016 if (triggers) {
6017 ret = wpa_drv_wowlan(wpa_s, triggers);
6018 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006019 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006020 return ret;
6021}
6022
6023
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006024enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006025{
6026 if (freq < 3000)
6027 return BAND_2_4_GHZ;
6028 if (freq > 50000)
6029 return BAND_60_GHZ;
6030 return BAND_5_GHZ;
6031}
6032
6033
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006034unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006035{
6036 int i;
6037 unsigned int band = 0;
6038
6039 if (freqs) {
6040 /* freqs are specified for the radio work */
6041 for (i = 0; freqs[i]; i++)
6042 band |= wpas_freq_to_band(freqs[i]);
6043 } else {
6044 /*
6045 * freqs are not specified, implies all
6046 * the supported freqs by HW
6047 */
6048 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6049 if (wpa_s->hw.modes[i].num_channels != 0) {
6050 if (wpa_s->hw.modes[i].mode ==
6051 HOSTAPD_MODE_IEEE80211B ||
6052 wpa_s->hw.modes[i].mode ==
6053 HOSTAPD_MODE_IEEE80211G)
6054 band |= BAND_2_4_GHZ;
6055 else if (wpa_s->hw.modes[i].mode ==
6056 HOSTAPD_MODE_IEEE80211A)
6057 band |= BAND_5_GHZ;
6058 else if (wpa_s->hw.modes[i].mode ==
6059 HOSTAPD_MODE_IEEE80211AD)
6060 band |= BAND_60_GHZ;
6061 else if (wpa_s->hw.modes[i].mode ==
6062 HOSTAPD_MODE_IEEE80211ANY)
6063 band = BAND_2_4_GHZ | BAND_5_GHZ |
6064 BAND_60_GHZ;
6065 }
6066 }
6067 }
6068
6069 return band;
6070}
6071
6072
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006073static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6074 const char *rn)
6075{
6076 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6077 struct wpa_radio *radio;
6078
6079 while (rn && iface) {
6080 radio = iface->radio;
6081 if (radio && os_strcmp(rn, radio->name) == 0) {
6082 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6083 wpa_s->ifname, rn);
6084 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6085 return radio;
6086 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006087
6088 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006089 }
6090
6091 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6092 wpa_s->ifname, rn ? rn : "N/A");
6093 radio = os_zalloc(sizeof(*radio));
6094 if (radio == NULL)
6095 return NULL;
6096
6097 if (rn)
6098 os_strlcpy(radio->name, rn, sizeof(radio->name));
6099 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006100 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006101 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6102
6103 return radio;
6104}
6105
6106
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006107static void radio_work_free(struct wpa_radio_work *work)
6108{
6109 if (work->wpa_s->scan_work == work) {
6110 /* This should not really happen. */
6111 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6112 work->type, work, work->started);
6113 work->wpa_s->scan_work = NULL;
6114 }
6115
6116#ifdef CONFIG_P2P
6117 if (work->wpa_s->p2p_scan_work == work) {
6118 /* This should not really happen. */
6119 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6120 work->type, work, work->started);
6121 work->wpa_s->p2p_scan_work = NULL;
6122 }
6123#endif /* CONFIG_P2P */
6124
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006125 if (work->started) {
6126 work->wpa_s->radio->num_active_works--;
6127 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006128 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006129 work->type, work,
6130 work->wpa_s->radio->num_active_works);
6131 }
6132
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006133 dl_list_del(&work->list);
6134 os_free(work);
6135}
6136
6137
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006138static int radio_work_is_connect(struct wpa_radio_work *work)
6139{
6140 return os_strcmp(work->type, "sme-connect") == 0 ||
6141 os_strcmp(work->type, "connect") == 0;
6142}
6143
6144
6145static int radio_work_is_scan(struct wpa_radio_work *work)
6146{
6147 return os_strcmp(work->type, "scan") == 0 ||
6148 os_strcmp(work->type, "p2p-scan") == 0;
6149}
6150
6151
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006152static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6153{
6154 struct wpa_radio_work *active_work = NULL;
6155 struct wpa_radio_work *tmp;
6156
6157 /* Get the active work to know the type and band. */
6158 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6159 if (tmp->started) {
6160 active_work = tmp;
6161 break;
6162 }
6163 }
6164
6165 if (!active_work) {
6166 /* No active work, start one */
6167 radio->num_active_works = 0;
6168 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6169 list) {
6170 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006171 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006172 (((struct wpa_driver_scan_params *)
6173 tmp->ctx)->only_new_results ||
6174 tmp->wpa_s->clear_driver_scan_cache))
6175 continue;
6176 return tmp;
6177 }
6178 return NULL;
6179 }
6180
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006181 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006182 /*
6183 * If the active work is either connect or sme-connect,
6184 * do not parallelize them with other radio works.
6185 */
6186 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6187 "Do not parallelize radio work with %s",
6188 active_work->type);
6189 return NULL;
6190 }
6191
6192 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6193 if (tmp->started)
6194 continue;
6195
6196 /*
6197 * If connect or sme-connect are enqueued, parallelize only
6198 * those operations ahead of them in the queue.
6199 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006200 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006201 break;
6202
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006203 /* Serialize parallel scan and p2p_scan operations on the same
6204 * interface since the driver_nl80211 mechanism for tracking
6205 * scan cookies does not yet have support for this. */
6206 if (active_work->wpa_s == tmp->wpa_s &&
6207 radio_work_is_scan(active_work) &&
6208 radio_work_is_scan(tmp)) {
6209 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6210 "Do not start work '%s' when another work '%s' is already scheduled",
6211 tmp->type, active_work->type);
6212 continue;
6213 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006214 /*
6215 * Check that the radio works are distinct and
6216 * on different bands.
6217 */
6218 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6219 (active_work->bands != tmp->bands)) {
6220 /*
6221 * If a scan has to be scheduled through nl80211 scan
6222 * interface and if an external scan is already running,
6223 * do not schedule the scan since it is likely to get
6224 * rejected by kernel.
6225 */
6226 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006227 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006228 (((struct wpa_driver_scan_params *)
6229 tmp->ctx)->only_new_results ||
6230 tmp->wpa_s->clear_driver_scan_cache))
6231 continue;
6232
6233 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6234 "active_work:%s new_work:%s",
6235 active_work->type, tmp->type);
6236 return tmp;
6237 }
6238 }
6239
6240 /* Did not find a radio work to schedule in parallel. */
6241 return NULL;
6242}
6243
6244
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006245static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6246{
6247 struct wpa_radio *radio = eloop_ctx;
6248 struct wpa_radio_work *work;
6249 struct os_reltime now, diff;
6250 struct wpa_supplicant *wpa_s;
6251
6252 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006253 if (work == NULL) {
6254 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006255 return;
6256 }
6257
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006258 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6259 radio_list);
6260
6261 if (!(wpa_s &&
6262 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6263 if (work->started)
6264 return; /* already started and still in progress */
6265
Hai Shalom60840252021-02-19 19:02:11 -08006266 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006267 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6268 return;
6269 }
6270 } else {
6271 work = NULL;
6272 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6273 /* get the work to schedule next */
6274 work = radio_work_get_next_work(radio);
6275 }
6276 if (!work)
6277 return;
6278 }
6279
6280 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006281 os_get_reltime(&now);
6282 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006283 wpa_dbg(wpa_s, MSG_DEBUG,
6284 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006285 work->type, work, diff.sec, diff.usec);
6286 work->started = 1;
6287 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006288 radio->num_active_works++;
6289
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006290 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006291
6292 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6293 radio->num_active_works < MAX_ACTIVE_WORKS)
6294 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006295}
6296
6297
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006298/*
6299 * This function removes both started and pending radio works running on
6300 * the provided interface's radio.
6301 * Prior to the removal of the radio work, its callback (cb) is called with
6302 * deinit set to be 1. Each work's callback is responsible for clearing its
6303 * internal data and restoring to a correct state.
6304 * @wpa_s: wpa_supplicant data
6305 * @type: type of works to be removed
6306 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6307 * this interface's works.
6308 */
6309void radio_remove_works(struct wpa_supplicant *wpa_s,
6310 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006311{
6312 struct wpa_radio_work *work, *tmp;
6313 struct wpa_radio *radio = wpa_s->radio;
6314
6315 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6316 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006317 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006318 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006319
6320 /* skip other ifaces' works */
6321 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006322 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006323
6324 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6325 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006326 work->cb(work, 1);
6327 radio_work_free(work);
6328 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006329
6330 /* in case we removed the started work */
6331 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006332}
6333
6334
Roshan Pius3a1667e2018-07-03 15:17:14 -07006335void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6336{
6337 struct wpa_radio_work *work;
6338 struct wpa_radio *radio = wpa_s->radio;
6339
6340 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6341 if (work->ctx != ctx)
6342 continue;
6343 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6344 work->type, work, work->started ? " (started)" : "");
6345 radio_work_free(work);
6346 break;
6347 }
6348}
6349
6350
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006351static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6352{
6353 struct wpa_radio *radio = wpa_s->radio;
6354
6355 if (!radio)
6356 return;
6357
6358 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6359 wpa_s->ifname, radio->name);
6360 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006361 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006362 /* If the interface that triggered the external scan was removed, the
6363 * external scan is no longer running. */
6364 if (wpa_s == radio->external_scan_req_interface)
6365 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006366 wpa_s->radio = NULL;
6367 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006368 return; /* Interfaces remain for this radio */
6369
6370 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006371 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006372 os_free(radio);
6373}
6374
6375
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006376void radio_work_check_next(struct wpa_supplicant *wpa_s)
6377{
6378 struct wpa_radio *radio = wpa_s->radio;
6379
6380 if (dl_list_empty(&radio->work))
6381 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006382 if (wpa_s->ext_work_in_progress) {
6383 wpa_printf(MSG_DEBUG,
6384 "External radio work in progress - delay start of pending item");
6385 return;
6386 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006387 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6388 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6389}
6390
6391
6392/**
6393 * radio_add_work - Add a radio work item
6394 * @wpa_s: Pointer to wpa_supplicant data
6395 * @freq: Frequency of the offchannel operation in MHz or 0
6396 * @type: Unique identifier for each type of work
6397 * @next: Force as the next work to be executed
6398 * @cb: Callback function for indicating when radio is available
6399 * @ctx: Context pointer for the work (work->ctx in cb())
6400 * Returns: 0 on success, -1 on failure
6401 *
6402 * This function is used to request time for an operation that requires
6403 * exclusive radio control. Once the radio is available, the registered callback
6404 * function will be called. radio_work_done() must be called once the exclusive
6405 * radio operation has been completed, so that the radio is freed for other
6406 * operations. The special case of deinit=1 is used to free the context data
6407 * during interface removal. That does not allow the callback function to start
6408 * the radio operation, i.e., it must free any resources allocated for the radio
6409 * work and return.
6410 *
6411 * The @freq parameter can be used to indicate a single channel on which the
6412 * offchannel operation will occur. This may allow multiple radio work
6413 * operations to be performed in parallel if they apply for the same channel.
6414 * Setting this to 0 indicates that the work item may use multiple channels or
6415 * requires exclusive control of the radio.
6416 */
6417int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6418 const char *type, int next,
6419 void (*cb)(struct wpa_radio_work *work, int deinit),
6420 void *ctx)
6421{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006422 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006423 struct wpa_radio_work *work;
6424 int was_empty;
6425
6426 work = os_zalloc(sizeof(*work));
6427 if (work == NULL)
6428 return -1;
6429 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6430 os_get_reltime(&work->time);
6431 work->freq = freq;
6432 work->type = type;
6433 work->wpa_s = wpa_s;
6434 work->cb = cb;
6435 work->ctx = ctx;
6436
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006437 if (freq)
6438 work->bands = wpas_freq_to_band(freq);
6439 else if (os_strcmp(type, "scan") == 0 ||
6440 os_strcmp(type, "p2p-scan") == 0)
6441 work->bands = wpas_get_bands(wpa_s,
6442 ((struct wpa_driver_scan_params *)
6443 ctx)->freqs);
6444 else
6445 work->bands = wpas_get_bands(wpa_s, NULL);
6446
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006447 was_empty = dl_list_empty(&wpa_s->radio->work);
6448 if (next)
6449 dl_list_add(&wpa_s->radio->work, &work->list);
6450 else
6451 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6452 if (was_empty) {
6453 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6454 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006455 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6456 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6457 wpa_dbg(wpa_s, MSG_DEBUG,
6458 "Try to schedule a radio work (num_active_works=%u)",
6459 radio->num_active_works);
6460 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006461 }
6462
6463 return 0;
6464}
6465
6466
6467/**
6468 * radio_work_done - Indicate that a radio work item has been completed
6469 * @work: Completed work
6470 *
6471 * This function is called once the callback function registered with
6472 * radio_add_work() has completed its work.
6473 */
6474void radio_work_done(struct wpa_radio_work *work)
6475{
6476 struct wpa_supplicant *wpa_s = work->wpa_s;
6477 struct os_reltime now, diff;
6478 unsigned int started = work->started;
6479
6480 os_get_reltime(&now);
6481 os_reltime_sub(&now, &work->time, &diff);
6482 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6483 work->type, work, started ? "done" : "canceled",
6484 diff.sec, diff.usec);
6485 radio_work_free(work);
6486 if (started)
6487 radio_work_check_next(wpa_s);
6488}
6489
6490
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006491struct wpa_radio_work *
6492radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006493{
6494 struct wpa_radio_work *work;
6495 struct wpa_radio *radio = wpa_s->radio;
6496
6497 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6498 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006499 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006500 }
6501
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006502 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006503}
6504
6505
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006506static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006507 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006508{
6509 const char *ifname, *driver, *rn;
6510
6511 driver = iface->driver;
6512next_driver:
6513 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6514 return -1;
6515
6516 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6517 if (wpa_s->drv_priv == NULL) {
6518 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006519 int level = MSG_ERROR;
6520
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006521 pos = driver ? os_strchr(driver, ',') : NULL;
6522 if (pos) {
6523 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6524 "driver interface - try next driver wrapper");
6525 driver = pos + 1;
6526 goto next_driver;
6527 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006528
6529#ifdef CONFIG_MATCH_IFACE
6530 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6531 level = MSG_DEBUG;
6532#endif /* CONFIG_MATCH_IFACE */
6533 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006534 return -1;
6535 }
6536 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6537 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6538 "driver_param '%s'", wpa_s->conf->driver_param);
6539 return -1;
6540 }
6541
6542 ifname = wpa_drv_get_ifname(wpa_s);
6543 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6544 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6545 "interface name with '%s'", ifname);
6546 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6547 }
6548
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006549 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006550 if (rn && rn[0] == '\0')
6551 rn = NULL;
6552
6553 wpa_s->radio = radio_add_interface(wpa_s, rn);
6554 if (wpa_s->radio == NULL)
6555 return -1;
6556
6557 return 0;
6558}
6559
6560
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006561#ifdef CONFIG_GAS_SERVER
6562
6563static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6564 unsigned int freq, const u8 *dst,
6565 const u8 *src, const u8 *bssid,
6566 const u8 *data, size_t data_len,
6567 enum offchannel_send_action_result result)
6568{
6569 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6570 " result=%s",
6571 freq, MAC2STR(dst),
6572 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6573 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6574 "FAILED"));
6575 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6576 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6577}
6578
6579
6580static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6581 struct wpabuf *buf, unsigned int wait_time)
6582{
6583 struct wpa_supplicant *wpa_s = ctx;
6584 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6585
6586 if (wait_time > wpa_s->max_remain_on_chan)
6587 wait_time = wpa_s->max_remain_on_chan;
6588
6589 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6590 wpabuf_head(buf), wpabuf_len(buf),
6591 wait_time, wpas_gas_server_tx_status, 0);
6592}
6593
6594#endif /* CONFIG_GAS_SERVER */
6595
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006596static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006597 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006598{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006599 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006600 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006601 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006602
6603 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6604 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6605 iface->confname ? iface->confname : "N/A",
6606 iface->driver ? iface->driver : "default",
6607 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6608 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6609
6610 if (iface->confname) {
6611#ifdef CONFIG_BACKEND_FILE
6612 wpa_s->confname = os_rel2abs_path(iface->confname);
6613 if (wpa_s->confname == NULL) {
6614 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6615 "for configuration file '%s'.",
6616 iface->confname);
6617 return -1;
6618 }
6619 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6620 iface->confname, wpa_s->confname);
6621#else /* CONFIG_BACKEND_FILE */
6622 wpa_s->confname = os_strdup(iface->confname);
6623#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006624 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006625 if (wpa_s->conf == NULL) {
6626 wpa_printf(MSG_ERROR, "Failed to read or parse "
6627 "configuration '%s'.", wpa_s->confname);
6628 return -1;
6629 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006630 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006631 if (wpa_s->confanother &&
6632 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6633 wpa_printf(MSG_ERROR,
6634 "Failed to read or parse configuration '%s'.",
6635 wpa_s->confanother);
6636 return -1;
6637 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006638
6639 /*
6640 * Override ctrl_interface and driver_param if set on command
6641 * line.
6642 */
6643 if (iface->ctrl_interface) {
6644 os_free(wpa_s->conf->ctrl_interface);
6645 wpa_s->conf->ctrl_interface =
6646 os_strdup(iface->ctrl_interface);
6647 }
6648
6649 if (iface->driver_param) {
6650 os_free(wpa_s->conf->driver_param);
6651 wpa_s->conf->driver_param =
6652 os_strdup(iface->driver_param);
6653 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006654
6655 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6656 os_free(wpa_s->conf->ctrl_interface);
6657 wpa_s->conf->ctrl_interface = NULL;
6658 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006659 } else
6660 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6661 iface->driver_param);
6662
6663 if (wpa_s->conf == NULL) {
6664 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6665 return -1;
6666 }
6667
6668 if (iface->ifname == NULL) {
6669 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6670 return -1;
6671 }
6672 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6673 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6674 iface->ifname);
6675 return -1;
6676 }
6677 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006678#ifdef CONFIG_MATCH_IFACE
6679 wpa_s->matched = iface->matched;
6680#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006681
6682 if (iface->bridge_ifname) {
6683 if (os_strlen(iface->bridge_ifname) >=
6684 sizeof(wpa_s->bridge_ifname)) {
6685 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6686 "name '%s'.", iface->bridge_ifname);
6687 return -1;
6688 }
6689 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6690 sizeof(wpa_s->bridge_ifname));
6691 }
6692
6693 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006694 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6695 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006696
6697 /* Initialize driver interface and register driver event handler before
6698 * L2 receive handler so that association events are processed before
6699 * EAPOL-Key packets if both become available for the same select()
6700 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006701 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006702 return -1;
6703
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006704 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6705 return -1;
6706
6707 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6708 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6709 NULL);
6710 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6711
6712 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6713 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6714 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6715 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6716 "dot11RSNAConfigPMKLifetime");
6717 return -1;
6718 }
6719
6720 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6721 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6722 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6723 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6724 "dot11RSNAConfigPMKReauthThreshold");
6725 return -1;
6726 }
6727
6728 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6729 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6730 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6731 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6732 "dot11RSNAConfigSATimeout");
6733 return -1;
6734 }
6735
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006736 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6737 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006738 &wpa_s->hw.flags,
6739 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006740 if (wpa_s->hw.modes) {
6741 u16 i;
6742
6743 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6744 if (wpa_s->hw.modes[i].vht_capab) {
6745 wpa_s->hw_capab = CAPAB_VHT;
6746 break;
6747 }
6748
6749 if (wpa_s->hw.modes[i].ht_capab &
6750 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6751 wpa_s->hw_capab = CAPAB_HT40;
6752 else if (wpa_s->hw.modes[i].ht_capab &&
6753 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6754 wpa_s->hw_capab = CAPAB_HT;
6755 }
6756 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006757
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006758 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6759 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006760 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006761 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006762 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006763 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006764 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravi59fa4b42022-05-02 22:54:18 -07006765 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006766 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006767 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006768 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006769 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6770 wpa_s->max_sched_scan_plan_interval =
6771 capa.max_sched_scan_plan_interval;
6772 wpa_s->max_sched_scan_plan_iterations =
6773 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006774 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6775 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006776 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6777 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006778 wpa_s->extended_capa = capa.extended_capa;
6779 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6780 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006781 wpa_s->num_multichan_concurrent =
6782 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006783 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6784
6785 if (capa.mac_addr_rand_scan_supported)
6786 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6787 if (wpa_s->sched_scan_supported &&
6788 capa.mac_addr_rand_sched_scan_supported)
6789 wpa_s->mac_addr_rand_supported |=
6790 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006791
6792 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6793 if (wpa_s->extended_capa &&
6794 wpa_s->extended_capa_len >= 3 &&
6795 wpa_s->extended_capa[2] & 0x40)
6796 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006797 }
6798 if (wpa_s->max_remain_on_chan == 0)
6799 wpa_s->max_remain_on_chan = 1000;
6800
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006801 /*
6802 * Only take p2p_mgmt parameters when P2P Device is supported.
6803 * Doing it here as it determines whether l2_packet_init() will be done
6804 * during wpa_supplicant_driver_init().
6805 */
6806 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6807 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006808
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006809 if (wpa_s->num_multichan_concurrent == 0)
6810 wpa_s->num_multichan_concurrent = 1;
6811
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006812 if (wpa_supplicant_driver_init(wpa_s) < 0)
6813 return -1;
6814
6815#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006816 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006817 return -1;
6818#endif /* CONFIG_TDLS */
6819
6820 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6821 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6822 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6823 return -1;
6824 }
6825
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006826#ifdef CONFIG_FST
6827 if (wpa_s->conf->fst_group_id) {
6828 struct fst_iface_cfg cfg;
6829 struct fst_wpa_obj iface_obj;
6830
6831 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6832 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6833 sizeof(cfg.group_id));
6834 cfg.priority = wpa_s->conf->fst_priority;
6835 cfg.llt = wpa_s->conf->fst_llt;
6836
6837 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6838 &iface_obj, &cfg);
6839 if (!wpa_s->fst) {
6840 wpa_msg(wpa_s, MSG_ERROR,
6841 "FST: Cannot attach iface %s to group %s",
6842 wpa_s->ifname, cfg.group_id);
6843 return -1;
6844 }
6845 }
6846#endif /* CONFIG_FST */
6847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006848 if (wpas_wps_init(wpa_s))
6849 return -1;
6850
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006851#ifdef CONFIG_GAS_SERVER
6852 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6853 if (!wpa_s->gas_server) {
6854 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6855 return -1;
6856 }
6857#endif /* CONFIG_GAS_SERVER */
6858
6859#ifdef CONFIG_DPP
6860 if (wpas_dpp_init(wpa_s) < 0)
6861 return -1;
6862#endif /* CONFIG_DPP */
6863
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006864 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6865 return -1;
6866 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6867
6868 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6869 if (wpa_s->ctrl_iface == NULL) {
6870 wpa_printf(MSG_ERROR,
6871 "Failed to initialize control interface '%s'.\n"
6872 "You may have another wpa_supplicant process "
6873 "already running or the file was\n"
6874 "left by an unclean termination of wpa_supplicant "
6875 "in which case you will need\n"
6876 "to manually remove this file before starting "
6877 "wpa_supplicant again.\n",
6878 wpa_s->conf->ctrl_interface);
6879 return -1;
6880 }
6881
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006882 wpa_s->gas = gas_query_init(wpa_s);
6883 if (wpa_s->gas == NULL) {
6884 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6885 return -1;
6886 }
6887
Roshan Pius3a1667e2018-07-03 15:17:14 -07006888 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6889 wpa_s->p2p_mgmt) &&
6890 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006891 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6892 return -1;
6893 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006894
6895 if (wpa_bss_init(wpa_s) < 0)
6896 return -1;
6897
Paul Stewart092955c2017-02-06 09:13:09 -08006898#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6899#ifdef CONFIG_MESH
6900 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6901#endif /* CONFIG_MESH */
6902#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6903
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006904 /*
6905 * Set Wake-on-WLAN triggers, if configured.
6906 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6907 * have effect anyway when the interface is down).
6908 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006909 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006910 return -1;
6911
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006912#ifdef CONFIG_EAP_PROXY
6913{
6914 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006915 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6916 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006917 if (wpa_s->mnc_len > 0) {
6918 wpa_s->imsi[len] = '\0';
6919 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6920 wpa_s->imsi, wpa_s->mnc_len);
6921 } else {
6922 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6923 }
6924}
6925#endif /* CONFIG_EAP_PROXY */
6926
Dmitry Shmidt04949592012-07-19 12:16:46 -07006927 if (pcsc_reader_init(wpa_s) < 0)
6928 return -1;
6929
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006930 if (wpas_init_ext_pw(wpa_s) < 0)
6931 return -1;
6932
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006933 wpas_rrm_reset(wpa_s);
6934
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006935 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6936
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006937#ifdef CONFIG_HS20
6938 hs20_init(wpa_s);
6939#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006940#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006941 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006942 if ((wpa_s->conf->oce & OCE_STA) &&
6943 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6944 wpa_s->enable_oce = OCE_STA;
6945 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6946 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6947 /* TODO: Need to add STA-CFON support */
6948 wpa_printf(MSG_ERROR,
6949 "OCE STA-CFON feature is not yet supported");
6950 }
6951 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006952 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6953#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006954
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006955 wpa_supplicant_set_default_scan_ies(wpa_s);
6956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006957 return 0;
6958}
6959
6960
6961static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006962 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006963{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006964 struct wpa_global *global = wpa_s->global;
6965 struct wpa_supplicant *iface, *prev;
6966
Jimmy Chen0e73c002021-08-18 13:21:30 +08006967 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006968 wpas_p2p_group_remove(wpa_s, "*");
6969
6970 iface = global->ifaces;
6971 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006972 if (iface->p2pdev == wpa_s)
6973 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006974 if (iface == wpa_s || iface->parent != wpa_s) {
6975 iface = iface->next;
6976 continue;
6977 }
6978 wpa_printf(MSG_DEBUG,
6979 "Remove remaining child interface %s from parent %s",
6980 iface->ifname, wpa_s->ifname);
6981 prev = iface;
6982 iface = iface->next;
6983 wpa_supplicant_remove_iface(global, prev, terminate);
6984 }
6985
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006986 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006987 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006988 /*
6989 * Don't deauthenticate if WoWLAN is enable and not explicitly
6990 * been configured to disconnect.
6991 */
6992 if (!wpa_drv_get_wowlan(wpa_s) ||
6993 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006994 wpa_supplicant_deauthenticate(
6995 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006996
Hai Shalomfdcde762020-04-02 11:19:20 -07006997 wpa_drv_set_countermeasures(wpa_s, 0);
6998 wpa_clear_keys(wpa_s, NULL);
6999 } else {
7000 wpa_msg(wpa_s, MSG_INFO,
7001 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7002 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007003 }
7004
7005 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007006 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007007
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007008 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007009 radio_remove_interface(wpa_s);
7010
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007011#ifdef CONFIG_FST
7012 if (wpa_s->fst) {
7013 fst_detach(wpa_s->fst);
7014 wpa_s->fst = NULL;
7015 }
7016 if (wpa_s->received_mb_ies) {
7017 wpabuf_free(wpa_s->received_mb_ies);
7018 wpa_s->received_mb_ies = NULL;
7019 }
7020#endif /* CONFIG_FST */
7021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007022 if (wpa_s->drv_priv)
7023 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007024
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007025 if (notify)
7026 wpas_notify_iface_removed(wpa_s);
7027
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007028 if (terminate)
7029 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007030
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007031 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7032 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007033
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007034#ifdef CONFIG_MESH
7035 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007036 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007037 wpa_s->ifmsh = NULL;
7038 }
7039#endif /* CONFIG_MESH */
7040
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007041 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007042 wpa_config_free(wpa_s->conf);
7043 wpa_s->conf = NULL;
7044 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007045
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007046 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007047 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007048
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007049 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007050}
7051
7052
Dmitry Shmidte4663042016-04-04 10:07:49 -07007053#ifdef CONFIG_MATCH_IFACE
7054
7055/**
7056 * wpa_supplicant_match_iface - Match an interface description to a name
7057 * @global: Pointer to global data from wpa_supplicant_init()
7058 * @ifname: Name of the interface to match
7059 * Returns: Pointer to the created interface description or %NULL on failure
7060 */
7061struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7062 const char *ifname)
7063{
7064 int i;
7065 struct wpa_interface *iface, *miface;
7066
7067 for (i = 0; i < global->params.match_iface_count; i++) {
7068 miface = &global->params.match_ifaces[i];
7069 if (!miface->ifname ||
7070 fnmatch(miface->ifname, ifname, 0) == 0) {
7071 iface = os_zalloc(sizeof(*iface));
7072 if (!iface)
7073 return NULL;
7074 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007075 if (!miface->ifname)
7076 iface->matched = WPA_IFACE_MATCHED_NULL;
7077 else
7078 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007079 iface->ifname = ifname;
7080 return iface;
7081 }
7082 }
7083
7084 return NULL;
7085}
7086
7087
7088/**
7089 * wpa_supplicant_match_existing - Match existing interfaces
7090 * @global: Pointer to global data from wpa_supplicant_init()
7091 * Returns: 0 on success, -1 on failure
7092 */
7093static int wpa_supplicant_match_existing(struct wpa_global *global)
7094{
7095 struct if_nameindex *ifi, *ifp;
7096 struct wpa_supplicant *wpa_s;
7097 struct wpa_interface *iface;
7098
7099 ifp = if_nameindex();
7100 if (!ifp) {
7101 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7102 return -1;
7103 }
7104
7105 for (ifi = ifp; ifi->if_name; ifi++) {
7106 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7107 if (wpa_s)
7108 continue;
7109 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7110 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007111 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007112 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007113 }
7114 }
7115
7116 if_freenameindex(ifp);
7117 return 0;
7118}
7119
7120#endif /* CONFIG_MATCH_IFACE */
7121
7122
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007123/**
7124 * wpa_supplicant_add_iface - Add a new network interface
7125 * @global: Pointer to global data from wpa_supplicant_init()
7126 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007127 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007128 * Returns: Pointer to the created interface or %NULL on failure
7129 *
7130 * This function is used to add new network interfaces for %wpa_supplicant.
7131 * This can be called before wpa_supplicant_run() to add interfaces before the
7132 * main event loop has been started. In addition, new interfaces can be added
7133 * dynamically while %wpa_supplicant is already running. This could happen,
7134 * e.g., when a hotplug network adapter is inserted.
7135 */
7136struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007137 struct wpa_interface *iface,
7138 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007139{
7140 struct wpa_supplicant *wpa_s;
7141 struct wpa_interface t_iface;
7142 struct wpa_ssid *ssid;
7143
7144 if (global == NULL || iface == NULL)
7145 return NULL;
7146
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007147 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007148 if (wpa_s == NULL)
7149 return NULL;
7150
7151 wpa_s->global = global;
7152
7153 t_iface = *iface;
7154 if (global->params.override_driver) {
7155 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7156 "('%s' -> '%s')",
7157 iface->driver, global->params.override_driver);
7158 t_iface.driver = global->params.override_driver;
7159 }
7160 if (global->params.override_ctrl_interface) {
7161 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7162 "ctrl_interface ('%s' -> '%s')",
7163 iface->ctrl_interface,
7164 global->params.override_ctrl_interface);
7165 t_iface.ctrl_interface =
7166 global->params.override_ctrl_interface;
7167 }
7168 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7169 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7170 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007171 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007172 return NULL;
7173 }
7174
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007175 /* Notify the control interfaces about new iface */
7176 if (wpas_notify_iface_added(wpa_s)) {
7177 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7178 return NULL;
7179 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007180
Jimmy Chen115616e2022-07-10 10:25:21 +08007181 /* Notify the control interfaces about new networks */
7182 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7183 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007184 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chen115616e2022-07-10 10:25:21 +08007185 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7186 && os_strncmp((const char *) ssid->ssid,
7187 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7188 wpas_notify_persistent_group_added(wpa_s, ssid);
7189 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007190 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007191
7192 wpa_s->next = global->ifaces;
7193 global->ifaces = wpa_s;
7194
7195 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007196 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007197
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007198#ifdef CONFIG_P2P
7199 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007200 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007201 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007202 wpas_p2p_add_p2pdev_interface(
7203 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007204 wpa_printf(MSG_INFO,
7205 "P2P: Failed to enable P2P Device interface");
7206 /* Try to continue without. P2P will be disabled. */
7207 }
7208#endif /* CONFIG_P2P */
7209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210 return wpa_s;
7211}
7212
7213
7214/**
7215 * wpa_supplicant_remove_iface - Remove a network interface
7216 * @global: Pointer to global data from wpa_supplicant_init()
7217 * @wpa_s: Pointer to the network interface to be removed
7218 * Returns: 0 if interface was removed, -1 if interface was not found
7219 *
7220 * This function can be used to dynamically remove network interfaces from
7221 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7222 * addition, this function is used to remove all remaining interfaces when
7223 * %wpa_supplicant is terminated.
7224 */
7225int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007226 struct wpa_supplicant *wpa_s,
7227 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007228{
7229 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007230#ifdef CONFIG_MESH
7231 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7232 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007233 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007234#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007235
7236 /* Remove interface from the global list of interfaces */
7237 prev = global->ifaces;
7238 if (prev == wpa_s) {
7239 global->ifaces = wpa_s->next;
7240 } else {
7241 while (prev && prev->next != wpa_s)
7242 prev = prev->next;
7243 if (prev == NULL)
7244 return -1;
7245 prev->next = wpa_s->next;
7246 }
7247
7248 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7249
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007250#ifdef CONFIG_MESH
7251 if (mesh_if_created) {
7252 ifname = os_strdup(wpa_s->ifname);
7253 if (ifname == NULL) {
7254 wpa_dbg(wpa_s, MSG_ERROR,
7255 "mesh: Failed to malloc ifname");
7256 return -1;
7257 }
7258 }
7259#endif /* CONFIG_MESH */
7260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007261 if (global->p2p_group_formation == wpa_s)
7262 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007263 if (global->p2p_invite_group == wpa_s)
7264 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007265 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007266
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007267#ifdef CONFIG_MESH
7268 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007269 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007270 os_free(ifname);
7271 }
7272#endif /* CONFIG_MESH */
7273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007274 return 0;
7275}
7276
7277
7278/**
7279 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7280 * @wpa_s: Pointer to the network interface
7281 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7282 */
7283const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7284{
7285 const char *eapol_method;
7286
7287 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7288 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7289 return "NO-EAP";
7290 }
7291
7292 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7293 if (eapol_method == NULL)
7294 return "UNKNOWN-EAP";
7295
7296 return eapol_method;
7297}
7298
7299
7300/**
7301 * wpa_supplicant_get_iface - Get a new network interface
7302 * @global: Pointer to global data from wpa_supplicant_init()
7303 * @ifname: Interface name
7304 * Returns: Pointer to the interface or %NULL if not found
7305 */
7306struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7307 const char *ifname)
7308{
7309 struct wpa_supplicant *wpa_s;
7310
7311 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7312 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7313 return wpa_s;
7314 }
7315 return NULL;
7316}
7317
7318
7319#ifndef CONFIG_NO_WPA_MSG
7320static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7321{
7322 struct wpa_supplicant *wpa_s = ctx;
7323 if (wpa_s == NULL)
7324 return NULL;
7325 return wpa_s->ifname;
7326}
7327#endif /* CONFIG_NO_WPA_MSG */
7328
7329
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007330#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7331#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7332#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7333
7334/* Periodic cleanup tasks */
7335static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7336{
7337 struct wpa_global *global = eloop_ctx;
7338 struct wpa_supplicant *wpa_s;
7339
7340 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7341 wpas_periodic, global, NULL);
7342
7343#ifdef CONFIG_P2P
7344 if (global->p2p)
7345 p2p_expire_peers(global->p2p);
7346#endif /* CONFIG_P2P */
7347
7348 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7349 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7350#ifdef CONFIG_AP
7351 ap_periodic(wpa_s);
7352#endif /* CONFIG_AP */
7353 }
7354}
7355
7356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007357/**
7358 * wpa_supplicant_init - Initialize %wpa_supplicant
7359 * @params: Parameters for %wpa_supplicant
7360 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7361 *
7362 * This function is used to initialize %wpa_supplicant. After successful
7363 * initialization, the returned data pointer can be used to add and remove
7364 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7365 */
7366struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7367{
7368 struct wpa_global *global;
7369 int ret, i;
7370
7371 if (params == NULL)
7372 return NULL;
7373
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007374#ifdef CONFIG_DRIVER_NDIS
7375 {
7376 void driver_ndis_init_ops(void);
7377 driver_ndis_init_ops();
7378 }
7379#endif /* CONFIG_DRIVER_NDIS */
7380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007381#ifndef CONFIG_NO_WPA_MSG
7382 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7383#endif /* CONFIG_NO_WPA_MSG */
7384
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007385 if (params->wpa_debug_file_path)
7386 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007387 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007388 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007389 if (params->wpa_debug_syslog)
7390 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007391 if (params->wpa_debug_tracing) {
7392 ret = wpa_debug_open_linux_tracing();
7393 if (ret) {
7394 wpa_printf(MSG_ERROR,
7395 "Failed to enable trace logging");
7396 return NULL;
7397 }
7398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007399
7400 ret = eap_register_methods();
7401 if (ret) {
7402 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7403 if (ret == -2)
7404 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7405 "the same EAP type.");
7406 return NULL;
7407 }
7408
7409 global = os_zalloc(sizeof(*global));
7410 if (global == NULL)
7411 return NULL;
7412 dl_list_init(&global->p2p_srv_bonjour);
7413 dl_list_init(&global->p2p_srv_upnp);
7414 global->params.daemonize = params->daemonize;
7415 global->params.wait_for_monitor = params->wait_for_monitor;
7416 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7417 if (params->pid_file)
7418 global->params.pid_file = os_strdup(params->pid_file);
7419 if (params->ctrl_interface)
7420 global->params.ctrl_interface =
7421 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007422 if (params->ctrl_interface_group)
7423 global->params.ctrl_interface_group =
7424 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007425 if (params->override_driver)
7426 global->params.override_driver =
7427 os_strdup(params->override_driver);
7428 if (params->override_ctrl_interface)
7429 global->params.override_ctrl_interface =
7430 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007431#ifdef CONFIG_MATCH_IFACE
7432 global->params.match_iface_count = params->match_iface_count;
7433 if (params->match_iface_count) {
7434 global->params.match_ifaces =
7435 os_calloc(params->match_iface_count,
7436 sizeof(struct wpa_interface));
7437 os_memcpy(global->params.match_ifaces,
7438 params->match_ifaces,
7439 params->match_iface_count *
7440 sizeof(struct wpa_interface));
7441 }
7442#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007443#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007444 if (params->conf_p2p_dev)
7445 global->params.conf_p2p_dev =
7446 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007447#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007448 wpa_debug_level = global->params.wpa_debug_level =
7449 params->wpa_debug_level;
7450 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7451 params->wpa_debug_show_keys;
7452 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7453 params->wpa_debug_timestamp;
7454
Hai Shalomfdcde762020-04-02 11:19:20 -07007455 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007456
7457 if (eloop_init()) {
7458 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7459 wpa_supplicant_deinit(global);
7460 return NULL;
7461 }
7462
Jouni Malinen75ecf522011-06-27 15:19:46 -07007463 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007464
7465 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7466 if (global->ctrl_iface == NULL) {
7467 wpa_supplicant_deinit(global);
7468 return NULL;
7469 }
7470
7471 if (wpas_notify_supplicant_initialized(global)) {
7472 wpa_supplicant_deinit(global);
7473 return NULL;
7474 }
7475
7476 for (i = 0; wpa_drivers[i]; i++)
7477 global->drv_count++;
7478 if (global->drv_count == 0) {
7479 wpa_printf(MSG_ERROR, "No drivers enabled");
7480 wpa_supplicant_deinit(global);
7481 return NULL;
7482 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007483 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007484 if (global->drv_priv == NULL) {
7485 wpa_supplicant_deinit(global);
7486 return NULL;
7487 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007488
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007489#ifdef CONFIG_WIFI_DISPLAY
7490 if (wifi_display_init(global) < 0) {
7491 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7492 wpa_supplicant_deinit(global);
7493 return NULL;
7494 }
7495#endif /* CONFIG_WIFI_DISPLAY */
7496
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007497 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7498 wpas_periodic, global, NULL);
7499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007500 return global;
7501}
7502
7503
7504/**
7505 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7506 * @global: Pointer to global data from wpa_supplicant_init()
7507 * Returns: 0 after successful event loop run, -1 on failure
7508 *
7509 * This function starts the main event loop and continues running as long as
7510 * there are any remaining events. In most cases, this function is running as
7511 * long as the %wpa_supplicant process in still in use.
7512 */
7513int wpa_supplicant_run(struct wpa_global *global)
7514{
7515 struct wpa_supplicant *wpa_s;
7516
7517 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007518 (wpa_supplicant_daemon(global->params.pid_file) ||
7519 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007520 return -1;
7521
Dmitry Shmidte4663042016-04-04 10:07:49 -07007522#ifdef CONFIG_MATCH_IFACE
7523 if (wpa_supplicant_match_existing(global))
7524 return -1;
7525#endif
7526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007527 if (global->params.wait_for_monitor) {
7528 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007529 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007530 wpa_supplicant_ctrl_iface_wait(
7531 wpa_s->ctrl_iface);
7532 }
7533
7534 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7535 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7536
7537 eloop_run();
7538
7539 return 0;
7540}
7541
7542
7543/**
7544 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7545 * @global: Pointer to global data from wpa_supplicant_init()
7546 *
7547 * This function is called to deinitialize %wpa_supplicant and to free all
7548 * allocated resources. Remaining network interfaces will also be removed.
7549 */
7550void wpa_supplicant_deinit(struct wpa_global *global)
7551{
7552 int i;
7553
7554 if (global == NULL)
7555 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007556
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007557 eloop_cancel_timeout(wpas_periodic, global, NULL);
7558
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007559#ifdef CONFIG_WIFI_DISPLAY
7560 wifi_display_deinit(global);
7561#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007562
7563 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007564 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007565
7566 if (global->ctrl_iface)
7567 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7568
7569 wpas_notify_supplicant_deinitialized(global);
7570
7571 eap_peer_unregister_methods();
7572#ifdef CONFIG_AP
7573 eap_server_unregister_methods();
7574#endif /* CONFIG_AP */
7575
7576 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7577 if (!global->drv_priv[i])
7578 continue;
7579 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7580 }
7581 os_free(global->drv_priv);
7582
7583 random_deinit();
7584
7585 eloop_destroy();
7586
7587 if (global->params.pid_file) {
7588 os_daemonize_terminate(global->params.pid_file);
7589 os_free(global->params.pid_file);
7590 }
7591 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007592 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007593 os_free(global->params.override_driver);
7594 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007595#ifdef CONFIG_MATCH_IFACE
7596 os_free(global->params.match_ifaces);
7597#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007598#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007599 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007600#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007601
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007602 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007603 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007604 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007606 os_free(global);
7607 wpa_debug_close_syslog();
7608 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007609 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007610}
7611
7612
7613void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7614{
7615 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7616 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7617 char country[3];
7618 country[0] = wpa_s->conf->country[0];
7619 country[1] = wpa_s->conf->country[1];
7620 country[2] = '\0';
7621 if (wpa_drv_set_country(wpa_s, country) < 0) {
7622 wpa_printf(MSG_ERROR, "Failed to set country code "
7623 "'%s'", country);
7624 }
7625 }
7626
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007627 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7628 wpas_init_ext_pw(wpa_s);
7629
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007630 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7631 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7632
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007633 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7634 struct wpa_driver_capa capa;
7635 int res = wpa_drv_get_capa(wpa_s, &capa);
7636
7637 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7638 wpa_printf(MSG_ERROR,
7639 "Failed to update wowlan_triggers to '%s'",
7640 wpa_s->conf->wowlan_triggers);
7641 }
7642
Hai Shalom81f62d82019-07-22 12:10:00 -07007643 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7644 wpa_supplicant_set_default_scan_ies(wpa_s);
7645
Hai Shalom899fcc72020-10-19 14:38:18 -07007646#ifdef CONFIG_BGSCAN
7647 /*
7648 * We default to global bgscan parameters only when per-network bgscan
7649 * parameters aren't set. Only bother resetting bgscan parameters if
7650 * this is the case.
7651 */
7652 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7653 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7654 wpa_s->wpa_state == WPA_COMPLETED)
7655 wpa_supplicant_reset_bgscan(wpa_s);
7656#endif /* CONFIG_BGSCAN */
7657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007658#ifdef CONFIG_WPS
7659 wpas_wps_update_config(wpa_s);
7660#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007661 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007662 wpa_s->conf->changed_parameters = 0;
7663}
7664
7665
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007666void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007667{
7668 int i;
7669
7670 for (i = 0; i < *num_freqs; i++) {
7671 if (freqs[i] == freq)
7672 return;
7673 }
7674
7675 freqs[*num_freqs] = freq;
7676 (*num_freqs)++;
7677}
7678
7679
7680static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7681{
7682 struct wpa_bss *bss, *cbss;
7683 const int max_freqs = 10;
7684 int *freqs;
7685 int num_freqs = 0;
7686
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007687 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007688 if (freqs == NULL)
7689 return NULL;
7690
7691 cbss = wpa_s->current_bss;
7692
7693 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7694 if (bss == cbss)
7695 continue;
7696 if (bss->ssid_len == cbss->ssid_len &&
7697 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007698 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007699 add_freq(freqs, &num_freqs, bss->freq);
7700 if (num_freqs == max_freqs)
7701 break;
7702 }
7703 }
7704
7705 if (num_freqs == 0) {
7706 os_free(freqs);
7707 freqs = NULL;
7708 }
7709
7710 return freqs;
7711}
7712
7713
7714void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7715{
7716 int timeout;
7717 int count;
7718 int *freqs = NULL;
7719
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007720 wpas_connect_work_done(wpa_s);
7721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007722 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007723 * Remove possible authentication timeout since the connection failed.
7724 */
7725 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7726
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007727 /*
Hai Shalom60840252021-02-19 19:02:11 -08007728 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007729 * generated based on local request to disconnect.
7730 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007731 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007732 wpa_s->own_disconnect_req = 0;
7733 wpa_dbg(wpa_s, MSG_DEBUG,
7734 "Ignore connection failure due to local request to disconnect");
7735 return;
7736 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007737 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007738 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7739 "indication since interface has been put into "
7740 "disconnected state");
7741 return;
7742 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007743 if (wpa_s->auto_reconnect_disabled) {
7744 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7745 "indication since auto connect is disabled");
7746 return;
7747 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007748
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007749 /*
Hai Shalom60840252021-02-19 19:02:11 -08007750 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007751 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007752 */
Hai Shalom60840252021-02-19 19:02:11 -08007753 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007754 if (count == 1 && wpa_s->current_bss) {
7755 /*
Hai Shalom60840252021-02-19 19:02:11 -08007756 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007757 * another BSS available for the same ESS, we should try that
7758 * next. Otherwise, we may as well try this one once more
7759 * before allowing other, likely worse, ESSes to be considered.
7760 */
7761 freqs = get_bss_freqs_in_ess(wpa_s);
7762 if (freqs) {
7763 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7764 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007765 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007766 /*
7767 * On the next scan, go through only the known channels
7768 * used in this ESS based on previous scans to speed up
7769 * common load balancing use case.
7770 */
7771 os_free(wpa_s->next_scan_freqs);
7772 wpa_s->next_scan_freqs = freqs;
7773 }
7774 }
7775
Hai Shalom899fcc72020-10-19 14:38:18 -07007776 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007777
Hai Shalom899fcc72020-10-19 14:38:18 -07007778 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007779 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7780 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007781 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007782 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007783 /*
7784 * Multiple consecutive connection failures mean that other APs are
7785 * either not available or have already been tried, so we can start
7786 * increasing the delay here to avoid constant scanning.
7787 */
7788 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007789 case 1:
7790 timeout = 100;
7791 break;
7792 case 2:
7793 timeout = 500;
7794 break;
7795 case 3:
7796 timeout = 1000;
7797 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007798 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007799 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007800 break;
7801 default:
7802 timeout = 10000;
7803 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007804 }
7805
Hai Shalom899fcc72020-10-19 14:38:18 -07007806 wpa_dbg(wpa_s, MSG_DEBUG,
7807 "Consecutive connection failures: %d --> request scan in %d ms",
7808 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007809
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007810 /*
7811 * TODO: if more than one possible AP is available in scan results,
7812 * could try the other ones before requesting a new scan.
7813 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007814
7815 /* speed up the connection attempt with normal scan */
7816 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007817 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7818 1000 * (timeout % 1000));
7819}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007820
7821
Hai Shalomce48b4a2018-09-05 11:41:35 -07007822#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007823
7824void fils_pmksa_cache_flush(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 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7832 * Check for ERP keys existing to limit when this can be done since
7833 * the rejection response is not protected and such triggers should
7834 * really not allow internal state to be modified unless required to
7835 * avoid significant issues in functionality. In addition, drop
7836 * externally configure PMKSA entries even without ERP keys since it
7837 * is possible for an external component to add PMKSA entries for FILS
7838 * authentication without restoring previously generated ERP keys.
7839 *
7840 * In this case, this is needed to allow recovery from cases where the
7841 * AP or authentication server has dropped PMKSAs and ERP keys. */
7842 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7843 return;
7844
7845 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7846 &username, &username_len,
7847 &realm, &realm_len, &next_seq_num,
7848 &rrk, &rrk_len) != 0 ||
7849 !realm) {
7850 wpa_dbg(wpa_s, MSG_DEBUG,
7851 "FILS: Drop external PMKSA cache entry");
7852 wpa_sm_aborted_external_cached(wpa_s->wpa);
7853 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7854 return;
7855 }
7856
7857 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7858 wpa_sm_aborted_cached(wpa_s->wpa);
7859 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7860}
7861
7862
Hai Shalomce48b4a2018-09-05 11:41:35 -07007863void fils_connection_failure(struct wpa_supplicant *wpa_s)
7864{
7865 struct wpa_ssid *ssid = wpa_s->current_ssid;
7866 const u8 *realm, *username, *rrk;
7867 size_t realm_len, username_len, rrk_len;
7868 u16 next_seq_num;
7869
7870 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7871 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7872 &username, &username_len,
7873 &realm, &realm_len, &next_seq_num,
7874 &rrk, &rrk_len) != 0 ||
7875 !realm)
7876 return;
7877
7878 wpa_hexdump_ascii(MSG_DEBUG,
7879 "FILS: Store last connection failure realm",
7880 realm, realm_len);
7881 os_free(wpa_s->last_con_fail_realm);
7882 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7883 if (wpa_s->last_con_fail_realm) {
7884 wpa_s->last_con_fail_realm_len = realm_len;
7885 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7886 }
7887}
7888#endif /* CONFIG_FILS */
7889
7890
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007891int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7892{
7893 return wpa_s->conf->ap_scan == 2 ||
7894 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7895}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007896
Dmitry Shmidt04949592012-07-19 12:16:46 -07007897
Gabriel Biren57ededa2021-09-03 16:08:50 +00007898#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007899int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7900 struct wpa_ssid *ssid,
7901 const char *field,
7902 const char *value)
7903{
7904#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007905 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007906
7907 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7908 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7909 (const u8 *) value, os_strlen(value));
7910
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007911 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007912 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007913#else /* IEEE8021X_EAPOL */
7914 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7915 return -1;
7916#endif /* IEEE8021X_EAPOL */
7917}
7918
7919int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7920 struct wpa_ssid *ssid,
7921 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007922 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007923{
7924#ifdef IEEE8021X_EAPOL
7925 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007926 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007927
7928 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007929 case WPA_CTRL_REQ_EAP_IDENTITY:
7930 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007931 os_free(eap->imsi_identity);
7932 if (value == NULL)
7933 return -1;
7934 identity = os_strchr(value, ':');
7935 if (identity == NULL) {
7936 /* plain identity */
7937 eap->identity = (u8 *)os_strdup(value);
7938 eap->identity_len = os_strlen(value);
7939 } else {
7940 /* have both plain identity and encrypted identity */
7941 imsi_identity = value;
7942 *identity++ = '\0';
7943 /* plain identity */
7944 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7945 eap->imsi_identity_len = strlen(imsi_identity);
7946 /* encrypted identity */
7947 eap->identity = (u8 *)dup_binstr(identity,
7948 value_len - strlen(imsi_identity) - 1);
7949 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7950 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007951 eap->pending_req_identity = 0;
7952 if (ssid == wpa_s->current_ssid)
7953 wpa_s->reassociate = 1;
7954 break;
7955 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007956 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007957 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007958 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007959 eap->pending_req_password = 0;
7960 if (ssid == wpa_s->current_ssid)
7961 wpa_s->reassociate = 1;
7962 break;
7963 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007964 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007965 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007966 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007967 eap->pending_req_new_password = 0;
7968 if (ssid == wpa_s->current_ssid)
7969 wpa_s->reassociate = 1;
7970 break;
7971 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007972 str_clear_free(eap->cert.pin);
7973 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007974 eap->pending_req_pin = 0;
7975 if (ssid == wpa_s->current_ssid)
7976 wpa_s->reassociate = 1;
7977 break;
7978 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007979 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007980 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007981 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007982 os_free(eap->pending_req_otp);
7983 eap->pending_req_otp = NULL;
7984 eap->pending_req_otp_len = 0;
7985 break;
7986 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007987 str_clear_free(eap->cert.private_key_passwd);
7988 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007989 eap->pending_req_passphrase = 0;
7990 if (ssid == wpa_s->current_ssid)
7991 wpa_s->reassociate = 1;
7992 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007993 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007994 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007995 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007996 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007997 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007998 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7999 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8000 return -1;
8001 ssid->mem_only_psk = 1;
8002 if (ssid->passphrase)
8003 wpa_config_update_psk(ssid);
8004 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8005 wpa_supplicant_req_scan(wpa_s, 0, 0);
8006 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008007 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8008 if (eap->pending_ext_cert_check != PENDING_CHECK)
8009 return -1;
8010 if (os_strcmp(value, "good") == 0)
8011 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8012 else if (os_strcmp(value, "bad") == 0)
8013 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8014 else
8015 return -1;
8016 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008017 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008018 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008019 return -1;
8020 }
8021
8022 return 0;
8023#else /* IEEE8021X_EAPOL */
8024 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8025 return -1;
8026#endif /* IEEE8021X_EAPOL */
8027}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008028#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008029
8030
8031int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8032{
Hai Shalomfdcde762020-04-02 11:19:20 -07008033#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008034 int i;
8035 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008036#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008037
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008038 if (wpa_s->p2p_mgmt)
8039 return 1; /* no normal network profiles on p2p_mgmt interface */
8040
Dmitry Shmidt04949592012-07-19 12:16:46 -07008041 if (ssid == NULL)
8042 return 1;
8043
8044 if (ssid->disabled)
8045 return 1;
8046
Hai Shalomfdcde762020-04-02 11:19:20 -07008047#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008048 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008049 drv_enc = wpa_s->drv_enc;
8050 else
8051 drv_enc = (unsigned int) -1;
8052
8053 for (i = 0; i < NUM_WEP_KEYS; i++) {
8054 size_t len = ssid->wep_key_len[i];
8055 if (len == 0)
8056 continue;
8057 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8058 continue;
8059 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8060 continue;
8061 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8062 continue;
8063 return 1; /* invalid WEP key */
8064 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008065#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008066
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008067 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008068 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008069 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008070 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008071 return 1;
8072
Dmitry Shmidt04949592012-07-19 12:16:46 -07008073 return 0;
8074}
8075
8076
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008077int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8078{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008079 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8080 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8081 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8082 /*
8083 * Driver does not support BIP -- ignore pmf=1 default
8084 * since the connection with PMF would fail and the
8085 * configuration does not require PMF to be enabled.
8086 */
8087 return NO_MGMT_FRAME_PROTECTION;
8088 }
8089
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008090 if (ssid &&
8091 (ssid->key_mgmt &
8092 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8093 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8094 /*
8095 * Do not use the default PMF value for non-RSN networks
8096 * since PMF is available only with RSN and pmf=2
8097 * configuration would otherwise prevent connections to
8098 * all open networks.
8099 */
8100 return NO_MGMT_FRAME_PROTECTION;
8101 }
8102
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008103 return wpa_s->conf->pmf;
8104 }
8105
8106 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008107}
8108
8109
Hai Shalomc1a21442022-02-04 13:43:00 -08008110int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8111{
8112 if (wpa_s->current_ssid == NULL ||
8113 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8114 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8115 return 0;
8116 return wpa_sm_pmf_enabled(wpa_s->wpa);
8117}
8118
8119
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008120int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008121{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008122 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008123 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008124 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008125 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008126 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008127}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008128
8129
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008130void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008131{
8132 struct wpa_ssid *ssid = wpa_s->current_ssid;
8133 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008134 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008135
8136 if (ssid == NULL) {
8137 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8138 "SSID block");
8139 return;
8140 }
8141
8142 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8143 return;
8144
8145 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008146
8147#ifdef CONFIG_P2P
8148 if (ssid->p2p_group &&
8149 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8150 /*
8151 * Skip the wait time since there is a short timeout on the
8152 * connection to a P2P group.
8153 */
8154 return;
8155 }
8156#endif /* CONFIG_P2P */
8157
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008158 if (ssid->auth_failures > 50)
8159 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008160 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008161 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008162 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008163 dur = 90;
8164 else if (ssid->auth_failures > 3)
8165 dur = 60;
8166 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008167 dur = 30;
8168 else if (ssid->auth_failures > 1)
8169 dur = 20;
8170 else
8171 dur = 10;
8172
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008173 if (ssid->auth_failures > 1 &&
8174 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8175 dur += os_random() % (ssid->auth_failures * 10);
8176
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008177 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008178 if (now.sec + dur <= ssid->disabled_until.sec)
8179 return;
8180
8181 ssid->disabled_until.sec = now.sec + dur;
8182
8183 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008184 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008185 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008186 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008187
8188 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8189 int msg_len = snprintf(NULL, 0, format_str,
8190 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8191 ssid->auth_failures, dur, reason) + 1;
8192 char *msg = os_malloc(msg_len);
8193 snprintf(msg, msg_len, format_str,
8194 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8195 ssid->auth_failures, dur, reason);
8196 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8197 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008198}
8199
8200
8201void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8202 struct wpa_ssid *ssid, int clear_failures)
8203{
8204 if (ssid == NULL)
8205 return;
8206
8207 if (ssid->disabled_until.sec) {
8208 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8209 "id=%d ssid=\"%s\"",
8210 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8211 }
8212 ssid->disabled_until.sec = 0;
8213 ssid->disabled_until.usec = 0;
8214 if (clear_failures)
8215 ssid->auth_failures = 0;
8216}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008217
8218
8219int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8220{
8221 size_t i;
8222
8223 if (wpa_s->disallow_aps_bssid == NULL)
8224 return 0;
8225
8226 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8227 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8228 bssid, ETH_ALEN) == 0)
8229 return 1;
8230 }
8231
8232 return 0;
8233}
8234
8235
8236int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8237 size_t ssid_len)
8238{
8239 size_t i;
8240
8241 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8242 return 0;
8243
8244 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8245 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8246 if (ssid_len == s->ssid_len &&
8247 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8248 return 1;
8249 }
8250
8251 return 0;
8252}
8253
8254
8255/**
8256 * wpas_request_connection - Request a new connection
8257 * @wpa_s: Pointer to the network interface
8258 *
8259 * This function is used to request a new connection to be found. It will mark
8260 * the interface to allow reassociation and request a new scan to find a
8261 * suitable network to connect to.
8262 */
8263void wpas_request_connection(struct wpa_supplicant *wpa_s)
8264{
8265 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008266 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008267 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008268 wpa_s->disconnected = 0;
8269 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008270 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008271
8272 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8273 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008274 else
8275 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008276}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008278
Roshan Pius02242d72016-08-09 15:31:48 -07008279/**
8280 * wpas_request_disconnection - Request disconnection
8281 * @wpa_s: Pointer to the network interface
8282 *
8283 * This function is used to request disconnection from the currently connected
8284 * network. This will stop any ongoing scans and initiate deauthentication.
8285 */
8286void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8287{
8288#ifdef CONFIG_SME
8289 wpa_s->sme.prev_bssid_set = 0;
8290#endif /* CONFIG_SME */
8291 wpa_s->reassociate = 0;
8292 wpa_s->disconnected = 1;
8293 wpa_supplicant_cancel_sched_scan(wpa_s);
8294 wpa_supplicant_cancel_scan(wpa_s);
8295 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8296 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008297 radio_remove_works(wpa_s, "connect", 0);
8298 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008299 wpa_s->roam_in_progress = false;
8300#ifdef CONFIG_WNM
8301 wpa_s->bss_trans_mgmt_in_progress = false;
8302#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008303}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008304
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008305
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008306void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8307 struct wpa_used_freq_data *freqs_data,
8308 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008309{
8310 unsigned int i;
8311
8312 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8313 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008314 for (i = 0; i < len; i++) {
8315 struct wpa_used_freq_data *cur = &freqs_data[i];
8316 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8317 i, cur->freq, cur->flags);
8318 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008319}
8320
8321
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008322/*
8323 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008324 * are using the same radio as the current interface, and in addition, get
8325 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008326 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008327int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8328 struct wpa_used_freq_data *freqs_data,
8329 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008330{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008331 struct wpa_supplicant *ifs;
8332 u8 bssid[ETH_ALEN];
8333 int freq;
8334 unsigned int idx = 0, i;
8335
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008336 wpa_dbg(wpa_s, MSG_DEBUG,
8337 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008338 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008339
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008340 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8341 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008342 if (idx == len)
8343 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008344
8345 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8346 continue;
8347
8348 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008349 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8350 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008351 freq = ifs->current_ssid->frequency;
8352 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8353 freq = ifs->assoc_freq;
8354 else
8355 continue;
8356
8357 /* Hold only distinct freqs */
8358 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008359 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008360 break;
8361
8362 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008363 freqs_data[idx++].freq = freq;
8364
8365 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008366 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008367 WPA_FREQ_USED_BY_P2P_CLIENT :
8368 WPA_FREQ_USED_BY_INFRA_STATION;
8369 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008370 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008371
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008372 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008373 return idx;
8374}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008375
8376
8377/*
8378 * Find the operating frequencies of any of the virtual interfaces that
8379 * are using the same radio as the current interface.
8380 */
8381int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8382 int *freq_array, unsigned int len)
8383{
8384 struct wpa_used_freq_data *freqs_data;
8385 int num, i;
8386
8387 os_memset(freq_array, 0, sizeof(int) * len);
8388
8389 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8390 if (!freqs_data)
8391 return -1;
8392
8393 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8394 for (i = 0; i < num; i++)
8395 freq_array[i] = freqs_data[i].freq;
8396
8397 os_free(freqs_data);
8398
8399 return num;
8400}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008401
8402
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008403struct wpa_supplicant *
8404wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8405{
8406 switch (frame) {
8407#ifdef CONFIG_P2P
8408 case VENDOR_ELEM_PROBE_REQ_P2P:
8409 case VENDOR_ELEM_PROBE_RESP_P2P:
8410 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8411 case VENDOR_ELEM_BEACON_P2P_GO:
8412 case VENDOR_ELEM_P2P_PD_REQ:
8413 case VENDOR_ELEM_P2P_PD_RESP:
8414 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8415 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8416 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8417 case VENDOR_ELEM_P2P_INV_REQ:
8418 case VENDOR_ELEM_P2P_INV_RESP:
8419 case VENDOR_ELEM_P2P_ASSOC_REQ:
8420 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008421 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008422#endif /* CONFIG_P2P */
8423 default:
8424 return wpa_s;
8425 }
8426}
8427
8428
8429void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8430{
8431 unsigned int i;
8432 char buf[30];
8433
8434 wpa_printf(MSG_DEBUG, "Update vendor elements");
8435
8436 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8437 if (wpa_s->vendor_elem[i]) {
8438 int res;
8439
8440 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8441 if (!os_snprintf_error(sizeof(buf), res)) {
8442 wpa_hexdump_buf(MSG_DEBUG, buf,
8443 wpa_s->vendor_elem[i]);
8444 }
8445 }
8446 }
8447
8448#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008449 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008450 wpa_s->global->p2p &&
8451 !wpa_s->global->p2p_disabled)
8452 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8453#endif /* CONFIG_P2P */
8454}
8455
8456
8457int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8458 const u8 *elem, size_t len)
8459{
8460 u8 *ie, *end;
8461
8462 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8463 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8464
8465 for (; ie + 1 < end; ie += 2 + ie[1]) {
8466 if (ie + len > end)
8467 break;
8468 if (os_memcmp(ie, elem, len) != 0)
8469 continue;
8470
8471 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8472 wpabuf_free(wpa_s->vendor_elem[frame]);
8473 wpa_s->vendor_elem[frame] = NULL;
8474 } else {
8475 os_memmove(ie, ie + len, end - (ie + len));
8476 wpa_s->vendor_elem[frame]->used -= len;
8477 }
8478 wpas_vendor_elem_update(wpa_s);
8479 return 0;
8480 }
8481
8482 return -1;
8483}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008484
8485
8486struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008487 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008488 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008489{
8490 u16 i;
8491
Hai Shalomc1a21442022-02-04 13:43:00 -08008492 if (!modes)
8493 return NULL;
8494
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008495 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008496 if (modes[i].mode != mode ||
8497 !modes[i].num_channels || !modes[i].channels)
8498 continue;
8499 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8500 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008501 return &modes[i];
8502 }
8503
8504 return NULL;
8505}
8506
8507
Hai Shalomc1a21442022-02-04 13:43:00 -08008508struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8509 u16 num_modes, int freq)
8510{
8511 int i, j;
8512
8513 for (i = 0; i < num_modes; i++) {
8514 for (j = 0; j < modes[i].num_channels; j++) {
8515 if (freq == modes[i].channels[j].freq)
8516 return &modes[i];
8517 }
8518 }
8519
8520 return NULL;
8521}
8522
8523
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008524static struct
8525wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8526 const u8 *bssid)
8527{
8528 struct wpa_bss_tmp_disallowed *bss;
8529
8530 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8531 struct wpa_bss_tmp_disallowed, list) {
8532 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8533 return bss;
8534 }
8535
8536 return NULL;
8537}
8538
8539
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008540static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8541{
8542 struct wpa_bss_tmp_disallowed *tmp;
8543 unsigned int num_bssid = 0;
8544 u8 *bssids;
8545 int ret;
8546
8547 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8548 if (!bssids)
8549 return -1;
8550 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8551 struct wpa_bss_tmp_disallowed, list) {
8552 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8553 ETH_ALEN);
8554 num_bssid++;
8555 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008556 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008557 os_free(bssids);
8558 return ret;
8559}
8560
8561
8562static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8563{
8564 struct wpa_supplicant *wpa_s = eloop_ctx;
8565 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8566
8567 /* Make sure the bss is not already freed */
8568 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8569 struct wpa_bss_tmp_disallowed, list) {
8570 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008571 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008572 wpa_set_driver_tmp_disallow_list(wpa_s);
8573 break;
8574 }
8575 }
8576}
8577
8578
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008579void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008580 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008581{
8582 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008583
8584 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8585 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008586 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008587 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008588 }
8589
8590 bss = os_malloc(sizeof(*bss));
8591 if (!bss) {
8592 wpa_printf(MSG_DEBUG,
8593 "Failed to allocate memory for temp disallow BSS");
8594 return;
8595 }
8596
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008597 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8598 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008599 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008600
8601finish:
8602 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008603 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8604 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008605}
8606
8607
Hai Shalom74f70d42019-02-11 14:42:39 -08008608int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8609 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008610{
Hai Shalom74f70d42019-02-11 14:42:39 -08008611 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008612
8613 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8614 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008615 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8616 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008617 break;
8618 }
8619 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008620 if (!disallowed)
8621 return 0;
8622
8623 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008624 bss->level > disallowed->rssi_threshold) {
8625 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8626 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008627 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008628 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008629
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008630 return 1;
8631}
Hai Shalom81f62d82019-07-22 12:10:00 -07008632
8633
8634int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8635 unsigned int type, const u8 *addr,
8636 const u8 *mask)
8637{
8638 if ((addr && !mask) || (!addr && mask)) {
8639 wpa_printf(MSG_INFO,
8640 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8641 return -1;
8642 }
8643
8644 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8645 wpa_printf(MSG_INFO,
8646 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8647 return -1;
8648 }
8649
8650 if (type & MAC_ADDR_RAND_SCAN) {
8651 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8652 addr, mask))
8653 return -1;
8654 }
8655
8656 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8657 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8658 addr, mask))
8659 return -1;
8660
8661 if (wpa_s->sched_scanning && !wpa_s->pno)
8662 wpas_scan_restart_sched_scan(wpa_s);
8663 }
8664
8665 if (type & MAC_ADDR_RAND_PNO) {
8666 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8667 addr, mask))
8668 return -1;
8669
8670 if (wpa_s->pno) {
8671 wpas_stop_pno(wpa_s);
8672 wpas_start_pno(wpa_s);
8673 }
8674 }
8675
8676 return 0;
8677}
8678
8679
8680int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8681 unsigned int type)
8682{
8683 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8684 if (wpa_s->pno) {
8685 if (type & MAC_ADDR_RAND_PNO) {
8686 wpas_stop_pno(wpa_s);
8687 wpas_start_pno(wpa_s);
8688 }
8689 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8690 wpas_scan_restart_sched_scan(wpa_s);
8691 }
8692
8693 return 0;
8694}
Hai Shalomfdcde762020-04-02 11:19:20 -07008695
8696
8697int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8698 struct wpa_signal_info *si)
8699{
8700 int res;
8701
8702 if (!wpa_s->driver->signal_poll)
8703 return -1;
8704
8705 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8706
8707#ifdef CONFIG_TESTING_OPTIONS
8708 if (res == 0) {
8709 struct driver_signal_override *dso;
8710
8711 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8712 struct driver_signal_override, list) {
8713 if (os_memcmp(wpa_s->bssid, dso->bssid,
8714 ETH_ALEN) != 0)
8715 continue;
8716 wpa_printf(MSG_DEBUG,
8717 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8718 si->current_signal,
8719 dso->si_current_signal,
8720 si->avg_signal,
8721 dso->si_avg_signal,
8722 si->avg_beacon_signal,
8723 dso->si_avg_beacon_signal,
8724 si->current_noise,
8725 dso->si_current_noise);
8726 si->current_signal = dso->si_current_signal;
8727 si->avg_signal = dso->si_avg_signal;
8728 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8729 si->current_noise = dso->si_current_noise;
8730 break;
8731 }
8732 }
8733#endif /* CONFIG_TESTING_OPTIONS */
8734
8735 return res;
8736}
8737
8738
8739struct wpa_scan_results *
8740wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8741{
8742 struct wpa_scan_results *scan_res;
8743#ifdef CONFIG_TESTING_OPTIONS
8744 size_t idx;
8745#endif /* CONFIG_TESTING_OPTIONS */
8746
8747 if (!wpa_s->driver->get_scan_results2)
8748 return NULL;
8749
8750 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8751
8752#ifdef CONFIG_TESTING_OPTIONS
8753 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8754 struct driver_signal_override *dso;
8755 struct wpa_scan_res *res = scan_res->res[idx];
8756
8757 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8758 struct driver_signal_override, list) {
8759 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8760 continue;
8761 wpa_printf(MSG_DEBUG,
8762 "Override driver scan signal level %d->%d for "
8763 MACSTR,
8764 res->level, dso->scan_level,
8765 MAC2STR(res->bssid));
8766 res->flags |= WPA_SCAN_QUAL_INVALID;
8767 if (dso->scan_level < 0)
8768 res->flags |= WPA_SCAN_LEVEL_DBM;
8769 else
8770 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8771 res->level = dso->scan_level;
8772 break;
8773 }
8774 }
8775#endif /* CONFIG_TESTING_OPTIONS */
8776
8777 return scan_res;
8778}