blob: cb429940b45c079fcfa2970a3c2b5172f218104a [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) &&
1910 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt)) {
1911 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1912 wpa_dbg(wpa_s, MSG_INFO,
1913 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1914 }
1915#endif /* CONFIG_DRIVER_NL80211_BRCM */
1916
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001917 return 0;
1918}
1919
1920
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001921static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1922{
Hai Shalomc1a21442022-02-04 13:43:00 -08001923 bool scs = true, mscs = true;
1924
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001925 *pos = 0x00;
1926
1927 switch (idx) {
1928 case 0: /* Bits 0-7 */
1929 break;
1930 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001931 if (wpa_s->conf->coloc_intf_reporting) {
1932 /* Bit 13 - Collocated Interference Reporting */
1933 *pos |= 0x20;
1934 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001935 break;
1936 case 2: /* Bits 16-23 */
1937#ifdef CONFIG_WNM
1938 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001939 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001940 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001941#endif /* CONFIG_WNM */
1942 break;
1943 case 3: /* Bits 24-31 */
1944#ifdef CONFIG_WNM
1945 *pos |= 0x02; /* Bit 25 - SSID List */
1946#endif /* CONFIG_WNM */
1947#ifdef CONFIG_INTERWORKING
1948 if (wpa_s->conf->interworking)
1949 *pos |= 0x80; /* Bit 31 - Interworking */
1950#endif /* CONFIG_INTERWORKING */
1951 break;
1952 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001953#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001954 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001955 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001956#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001957 break;
1958 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001959#ifdef CONFIG_HS20
1960 if (wpa_s->conf->hs20)
1961 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1962#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001963#ifdef CONFIG_MBO
1964 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1965#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001966 break;
1967 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001968#ifdef CONFIG_TESTING_OPTIONS
1969 if (wpa_s->disable_scs_support)
1970 scs = false;
1971#endif /* CONFIG_TESTING_OPTIONS */
1972 if (scs)
1973 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001974 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001975 case 7: /* Bits 56-63 */
1976 break;
1977 case 8: /* Bits 64-71 */
1978 if (wpa_s->conf->ftm_responder)
1979 *pos |= 0x40; /* Bit 70 - FTM responder */
1980 if (wpa_s->conf->ftm_initiator)
1981 *pos |= 0x80; /* Bit 71 - FTM initiator */
1982 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001983 case 9: /* Bits 72-79 */
1984#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001985 if (!wpa_s->disable_fils)
1986 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001987#endif /* CONFIG_FILS */
1988 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001989 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001990#ifdef CONFIG_TESTING_OPTIONS
1991 if (wpa_s->disable_mscs_support)
1992 mscs = false;
1993#endif /* CONFIG_TESTING_OPTIONS */
1994 if (mscs)
1995 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001996 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001997 }
1998}
1999
2000
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002001int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002002{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002003 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002004 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002005
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002006 if (len < wpa_s->extended_capa_len)
2007 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002008 if (buflen < (size_t) len + 2) {
2009 wpa_printf(MSG_INFO,
2010 "Not enough room for building extended capabilities element");
2011 return -1;
2012 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002013
2014 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002015 *pos++ = len;
2016 for (i = 0; i < len; i++, pos++) {
2017 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002018
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002019 if (i < wpa_s->extended_capa_len) {
2020 *pos &= ~wpa_s->extended_capa_mask[i];
2021 *pos |= wpa_s->extended_capa[i];
2022 }
2023 }
2024
2025 while (len > 0 && buf[1 + len] == 0) {
2026 len--;
2027 buf[1] = len;
2028 }
2029 if (len == 0)
2030 return 0;
2031
2032 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002033}
2034
2035
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002036static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2037 struct wpa_bss *test_bss)
2038{
2039 struct wpa_bss *bss;
2040
2041 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2042 if (bss == test_bss)
2043 return 1;
2044 }
2045
2046 return 0;
2047}
2048
2049
2050static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2051 struct wpa_ssid *test_ssid)
2052{
2053 struct wpa_ssid *ssid;
2054
2055 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2056 if (ssid == test_ssid)
2057 return 1;
2058 }
2059
2060 return 0;
2061}
2062
2063
2064int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2065 struct wpa_ssid *test_ssid)
2066{
2067 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2068 return 0;
2069
2070 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2071}
2072
2073
2074void wpas_connect_work_free(struct wpa_connect_work *cwork)
2075{
2076 if (cwork == NULL)
2077 return;
2078 os_free(cwork);
2079}
2080
2081
2082void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2083{
2084 struct wpa_connect_work *cwork;
2085 struct wpa_radio_work *work = wpa_s->connect_work;
2086
2087 if (!work)
2088 return;
2089
2090 wpa_s->connect_work = NULL;
2091 cwork = work->ctx;
2092 work->ctx = NULL;
2093 wpas_connect_work_free(cwork);
2094 radio_work_done(work);
2095}
2096
2097
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002098int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2099{
2100 struct os_reltime now;
2101 u8 addr[ETH_ALEN];
2102
2103 os_get_reltime(&now);
2104 if (wpa_s->last_mac_addr_style == style &&
2105 wpa_s->last_mac_addr_change.sec != 0 &&
2106 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2107 wpa_s->conf->rand_addr_lifetime)) {
2108 wpa_msg(wpa_s, MSG_DEBUG,
2109 "Previously selected random MAC address has not yet expired");
2110 return 0;
2111 }
2112
2113 switch (style) {
2114 case 1:
2115 if (random_mac_addr(addr) < 0)
2116 return -1;
2117 break;
2118 case 2:
2119 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2120 if (random_mac_addr_keep_oui(addr) < 0)
2121 return -1;
2122 break;
2123 default:
2124 return -1;
2125 }
2126
2127 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2128 wpa_msg(wpa_s, MSG_INFO,
2129 "Failed to set random MAC address");
2130 return -1;
2131 }
2132
2133 os_get_reltime(&wpa_s->last_mac_addr_change);
2134 wpa_s->mac_addr_changed = 1;
2135 wpa_s->last_mac_addr_style = style;
2136
2137 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2138 wpa_msg(wpa_s, MSG_INFO,
2139 "Could not update MAC address information");
2140 return -1;
2141 }
2142
2143 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2144 MAC2STR(addr));
2145
2146 return 0;
2147}
2148
2149
2150int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2151{
2152 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2153 !wpa_s->conf->preassoc_mac_addr)
2154 return 0;
2155
2156 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2157}
2158
2159
Hai Shalomc3565922019-10-28 11:58:20 -07002160static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2161{
2162#ifdef CONFIG_SAE
2163 int *groups = conf->sae_groups;
2164 int default_groups[] = { 19, 20, 21, 0 };
2165 const char *password;
2166
2167 if (!groups || groups[0] <= 0)
2168 groups = default_groups;
2169
2170 password = ssid->sae_password;
2171 if (!password)
2172 password = ssid->passphrase;
2173
Hai Shalom899fcc72020-10-19 14:38:18 -07002174 if (!password ||
2175 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2176 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002177 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002178 /* PT derivation not needed */
2179 sae_deinit_pt(ssid->pt);
2180 ssid->pt = NULL;
2181 return;
2182 }
2183
2184 if (ssid->pt)
2185 return; /* PT already derived */
2186 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2187 (const u8 *) password, os_strlen(password),
2188 ssid->sae_password_id);
2189#endif /* CONFIG_SAE */
2190}
2191
2192
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002193static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2194{
2195#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2196 os_free(wpa_s->sme.sae_rejected_groups);
2197 wpa_s->sme.sae_rejected_groups = NULL;
2198#ifdef CONFIG_TESTING_OPTIONS
2199 if (wpa_s->extra_sae_rejected_groups) {
2200 int i, *groups = wpa_s->extra_sae_rejected_groups;
2201
2202 for (i = 0; groups[i]; i++) {
2203 wpa_printf(MSG_DEBUG,
2204 "TESTING: Indicate rejection of an extra SAE group %d",
2205 groups[i]);
2206 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2207 groups[i]);
2208 }
2209 }
2210#endif /* CONFIG_TESTING_OPTIONS */
2211#endif /* CONFIG_SAE && CONFIG_SME */
2212}
2213
2214
Hai Shalom60840252021-02-19 19:02:11 -08002215int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2216{
2217 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2218 wpa_msg(wpa_s, MSG_INFO,
2219 "Could not restore permanent MAC address");
2220 return -1;
2221 }
2222 wpa_s->mac_addr_changed = 0;
2223 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2224 wpa_msg(wpa_s, MSG_INFO,
2225 "Could not update MAC address information");
2226 return -1;
2227 }
2228 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2229 return 0;
2230}
2231
2232
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002233static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2234
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002235/**
2236 * wpa_supplicant_associate - Request association
2237 * @wpa_s: Pointer to wpa_supplicant data
2238 * @bss: Scan results for the selected BSS, or %NULL if not available
2239 * @ssid: Configuration data for the selected network
2240 *
2241 * This function is used to request %wpa_supplicant to associate with a BSS.
2242 */
2243void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2244 struct wpa_bss *bss, struct wpa_ssid *ssid)
2245{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002246 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002247 int rand_style;
2248
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002249 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002250 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002251
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002252 /*
2253 * If we are starting a new connection, any previously pending EAPOL
2254 * RX cannot be valid anymore.
2255 */
2256 wpabuf_free(wpa_s->pending_eapol_rx);
2257 wpa_s->pending_eapol_rx = NULL;
2258
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002259 if (ssid->mac_addr == -1)
2260 rand_style = wpa_s->conf->mac_addr;
2261 else
2262 rand_style = ssid->mac_addr;
2263
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002264 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002265 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002266 wmm_ac_clear_saved_tspecs(wpa_s);
2267 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002268 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002269#ifdef CONFIG_TESTING_OPTIONS
2270 wpa_s->testing_resend_assoc = 0;
2271#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002272
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002273 if (wpa_s->last_ssid == ssid) {
2274 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002275 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002276 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2277 wmm_ac_save_tspecs(wpa_s);
2278 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002279 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2280 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002281 }
Hai Shalomc3565922019-10-28 11:58:20 -07002282 } else {
2283#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002284 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002285#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002286 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002287#ifdef CONFIG_SAE
2288 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2289#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002290
2291 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002292 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2293 return;
2294 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002295 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002296 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002297 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002298 }
2299 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002300
2301#ifdef CONFIG_IBSS_RSN
2302 ibss_rsn_deinit(wpa_s->ibss_rsn);
2303 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002304#else /* CONFIG_IBSS_RSN */
2305 if (ssid->mode == WPAS_MODE_IBSS &&
2306 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2307 wpa_msg(wpa_s, MSG_INFO,
2308 "IBSS RSN not supported in the build");
2309 return;
2310 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002311#endif /* CONFIG_IBSS_RSN */
2312
2313 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2314 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2315#ifdef CONFIG_AP
2316 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2317 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2318 "mode");
2319 return;
2320 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002321 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2322 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002323 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2324 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002325 return;
2326 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 wpa_s->current_bss = bss;
2328#else /* CONFIG_AP */
2329 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2330 "the build");
2331#endif /* CONFIG_AP */
2332 return;
2333 }
2334
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002335 if (ssid->mode == WPAS_MODE_MESH) {
2336#ifdef CONFIG_MESH
2337 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2338 wpa_msg(wpa_s, MSG_INFO,
2339 "Driver does not support mesh mode");
2340 return;
2341 }
2342 if (bss)
2343 ssid->frequency = bss->freq;
2344 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2345 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2346 return;
2347 }
2348 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002349#else /* CONFIG_MESH */
2350 wpa_msg(wpa_s, MSG_ERROR,
2351 "mesh mode support not included in the build");
2352#endif /* CONFIG_MESH */
2353 return;
2354 }
2355
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002356 /*
2357 * Set WPA state machine configuration to match the selected network now
2358 * so that the information is available before wpas_start_assoc_cb()
2359 * gets called. This is needed at least for RSN pre-authentication where
2360 * candidate APs are added to a list based on scan result processing
2361 * before completion of the first association.
2362 */
2363 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2364
2365#ifdef CONFIG_DPP
2366 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2367 return;
2368#endif /* CONFIG_DPP */
2369
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002370#ifdef CONFIG_TDLS
2371 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002372 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373#endif /* CONFIG_TDLS */
2374
Hai Shalomc3565922019-10-28 11:58:20 -07002375#ifdef CONFIG_MBO
2376 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2377#endif /* CONFIG_MBO */
2378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002380 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 sme_authenticate(wpa_s, bss, ssid);
2382 return;
2383 }
2384
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002385 if (wpa_s->connect_work) {
2386 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2387 return;
2388 }
2389
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002390 if (radio_work_pending(wpa_s, "connect")) {
2391 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2392 return;
2393 }
2394
Dmitry Shmidt29333592017-01-09 12:27:11 -08002395#ifdef CONFIG_SME
2396 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2397 /* Clear possibly set auth_alg, if any, from last attempt. */
2398 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2399 }
2400#endif /* CONFIG_SME */
2401
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002402 wpas_abort_ongoing_scan(wpa_s);
2403
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002404 cwork = os_zalloc(sizeof(*cwork));
2405 if (cwork == NULL)
2406 return;
2407
2408 cwork->bss = bss;
2409 cwork->ssid = ssid;
2410
2411 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2412 wpas_start_assoc_cb, cwork) < 0) {
2413 os_free(cwork);
2414 }
2415}
2416
2417
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002418static int bss_is_ibss(struct wpa_bss *bss)
2419{
2420 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2421 IEEE80211_CAP_IBSS;
2422}
2423
2424
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002425static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2426 const struct wpa_ssid *ssid)
2427{
2428 enum hostapd_hw_mode hw_mode;
2429 struct hostapd_hw_modes *mode = NULL;
2430 u8 channel;
2431 int i;
2432
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002433 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2434 if (hw_mode == NUM_HOSTAPD_MODES)
2435 return 0;
2436 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2437 if (wpa_s->hw.modes[i].mode == hw_mode) {
2438 mode = &wpa_s->hw.modes[i];
2439 break;
2440 }
2441 }
2442
2443 if (!mode)
2444 return 0;
2445
2446 return mode->vht_capab != 0;
2447}
2448
2449
Hai Shalomc1a21442022-02-04 13:43:00 -08002450static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2451{
2452 int i;
2453
2454 for (i = channel; i < channel + 16; i += 4) {
2455 struct hostapd_channel_data *chan;
2456
2457 chan = hw_get_channel_chan(mode, i, NULL);
2458 if (!chan ||
2459 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2460 return false;
2461 }
2462
2463 return true;
2464}
2465
2466
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002467void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2468 const struct wpa_ssid *ssid,
2469 struct hostapd_freq_params *freq)
2470{
Hai Shalom81f62d82019-07-22 12:10:00 -07002471 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002472 enum hostapd_hw_mode hw_mode;
2473 struct hostapd_hw_modes *mode = NULL;
2474 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2475 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002476 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2477 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2478 6595, 6675, 6755, 6835, 6915, 6995 };
2479 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002480 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2481 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002482 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002483 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002484 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002485 int chwidth, seg0, seg1;
2486 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002487 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002488
2489 freq->freq = ssid->frequency;
2490
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002491 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2492 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2493
2494 if (ssid->mode != WPAS_MODE_IBSS)
2495 break;
2496
2497 /* Don't adjust control freq in case of fixed_freq */
2498 if (ssid->fixed_freq)
2499 break;
2500
2501 if (!bss_is_ibss(bss))
2502 continue;
2503
2504 if (ssid->ssid_len == bss->ssid_len &&
2505 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2506 wpa_printf(MSG_DEBUG,
2507 "IBSS already found in scan results, adjust control freq: %d",
2508 bss->freq);
2509 freq->freq = bss->freq;
2510 obss_scan = 0;
2511 break;
2512 }
2513 }
2514
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002515 /* For IBSS check HT_IBSS flag */
2516 if (ssid->mode == WPAS_MODE_IBSS &&
2517 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2518 return;
2519
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002520 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2521 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2522 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2523 wpa_printf(MSG_DEBUG,
2524 "IBSS: WEP/TKIP detected, do not try to enable HT");
2525 return;
2526 }
2527
2528 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002529 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2530 if (wpa_s->hw.modes[i].mode == hw_mode) {
2531 mode = &wpa_s->hw.modes[i];
2532 break;
2533 }
2534 }
2535
2536 if (!mode)
2537 return;
2538
Hai Shalom60840252021-02-19 19:02:11 -08002539 freq->channel = channel;
2540
Hai Shalomc3565922019-10-28 11:58:20 -07002541 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2542 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002543
Hai Shalomc1a21442022-02-04 13:43:00 -08002544 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2545 * However, HE is mandatory for 6 GHz.
2546 */
2547 is_6ghz = is_6ghz_freq(freq->freq);
2548 if (is_6ghz)
2549 goto skip_to_6ghz;
2550
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002551#ifdef CONFIG_HT_OVERRIDES
2552 if (ssid->disable_ht) {
2553 freq->ht_enabled = 0;
2554 return;
2555 }
2556#endif /* CONFIG_HT_OVERRIDES */
2557
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002558 freq->ht_enabled = ht_supported(mode);
2559 if (!freq->ht_enabled)
2560 return;
2561
Hai Shalomc3565922019-10-28 11:58:20 -07002562 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2563 if (is_24ghz)
2564 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002565#ifdef CONFIG_HE_OVERRIDES
2566 if (is_24ghz && ssid->disable_he)
2567 freq->he_enabled = 0;
2568#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002569
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002570 /* Setup higher BW only for 5 GHz */
2571 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2572 return;
2573
2574 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2575 pri_chan = &mode->channels[chan_idx];
2576 if (pri_chan->chan == channel)
2577 break;
2578 pri_chan = NULL;
2579 }
2580 if (!pri_chan)
2581 return;
2582
2583 /* Check primary channel flags */
2584 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2585 return;
2586
Hai Shalom74f70d42019-02-11 14:42:39 -08002587 freq->channel = pri_chan->chan;
2588
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002589#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002590 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002591#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002592 if (ssid->disable_vht)
2593 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002594#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002595 goto skip_ht40;
2596 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002597#endif /* CONFIG_HT_OVERRIDES */
2598
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002599 /* Check/setup HT40+/HT40- */
2600 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2601 if (ht40plus[j] == channel) {
2602 ht40 = 1;
2603 break;
2604 }
2605 }
2606
2607 /* Find secondary channel */
2608 for (i = 0; i < mode->num_channels; i++) {
2609 sec_chan = &mode->channels[i];
2610 if (sec_chan->chan == channel + ht40 * 4)
2611 break;
2612 sec_chan = NULL;
2613 }
2614 if (!sec_chan)
2615 return;
2616
2617 /* Check secondary channel flags */
2618 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2619 return;
2620
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002621 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002622 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2623 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002624 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002625 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2626 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002627 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002628 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002629
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002630 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002631 struct wpa_scan_results *scan_res;
2632
2633 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2634 if (scan_res == NULL) {
2635 /* Back to HT20 */
2636 freq->sec_channel_offset = 0;
2637 return;
2638 }
2639
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002640 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002641 switch (res) {
2642 case 0:
2643 /* Back to HT20 */
2644 freq->sec_channel_offset = 0;
2645 break;
2646 case 1:
2647 /* Configuration allowed */
2648 break;
2649 case 2:
2650 /* Switch pri/sec channels */
2651 freq->freq = hw_get_freq(mode, sec_chan->chan);
2652 freq->sec_channel_offset = -freq->sec_channel_offset;
2653 freq->channel = sec_chan->chan;
2654 break;
2655 default:
2656 freq->sec_channel_offset = 0;
2657 break;
2658 }
2659
2660 wpa_scan_results_free(scan_res);
2661 }
2662
Hai Shalom74f70d42019-02-11 14:42:39 -08002663#ifdef CONFIG_HT_OVERRIDES
2664skip_ht40:
2665#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002666 wpa_printf(MSG_DEBUG,
2667 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2668 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002669
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002670 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002671 return;
2672
2673 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002674 if (ssid->mode == WPAS_MODE_IBSS &&
2675 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002676 return;
2677
Paul Stewart092955c2017-02-06 09:13:09 -08002678#ifdef CONFIG_VHT_OVERRIDES
2679 if (ssid->disable_vht) {
2680 freq->vht_enabled = 0;
2681 return;
2682 }
2683#endif /* CONFIG_VHT_OVERRIDES */
2684
Hai Shalomc1a21442022-02-04 13:43:00 -08002685skip_to_6ghz:
2686 vht_freq = *freq;
2687
2688 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002689 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002690 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002691 return;
2692
Hai Shalomfdcde762020-04-02 11:19:20 -07002693 /* Enable HE with VHT for 5 GHz */
2694 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002695
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002696 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002697 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2698 if (freq->freq >= bw80[j] &&
2699 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002700 break;
2701 }
2702
Hai Shalomc1a21442022-02-04 13:43:00 -08002703 if (j == ARRAY_SIZE(bw80) ||
2704 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002705 return;
2706
Hai Shalomc1a21442022-02-04 13:43:00 -08002707 /* Back to HT configuration if channel not usable */
2708 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2709 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002710
Hai Shalom81f62d82019-07-22 12:10:00 -07002711 chwidth = CHANWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002712 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002713 seg1 = 0;
2714
Hai Shalomc1a21442022-02-04 13:43:00 -08002715 if ((mode->he_capab[ieee80211_mode].phy_cap[
2716 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2717 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2718 /* In 160 MHz, the initial four 20 MHz channels were validated
2719 * above; check the remaining four 20 MHz channels for the total
2720 * of 160 MHz bandwidth.
2721 */
2722 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2723 return;
2724
2725 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2726 if (freq->freq == bw160[j]) {
2727 chwidth = CHANWIDTH_160MHZ;
2728 seg0 = channel + 14;
2729 break;
2730 }
2731 }
2732 }
2733
Hai Shalom81f62d82019-07-22 12:10:00 -07002734 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002735 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002736 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002737 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002738 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002739 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002740
2741 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2742 NUM_HOSTAPD_MODES)
2743 return;
2744
2745 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002746 struct hostapd_channel_data *chan;
2747
2748 chan = hw_get_channel_chan(mode, i, NULL);
2749 if (!chan)
2750 continue;
2751
2752 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2753 HOSTAPD_CHAN_NO_IR |
2754 HOSTAPD_CHAN_RADAR))
2755 continue;
2756
2757 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002758 chwidth = CHANWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002759 if (!is_6ghz)
2760 vht_caps |=
2761 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2762 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002763 }
2764
Hai Shalom81f62d82019-07-22 12:10:00 -07002765 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002766 break;
2767 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002768 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002769 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002770 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002771 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2772 seg0 = 50;
2773 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002774 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002775 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2776 seg0 = 114;
2777 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002778 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2779 chwidth = CHANWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002780 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002781#ifdef CONFIG_HT_OVERRIDES
2782 if (ssid->disable_ht40)
2783 seg0 = 0;
2784#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002785 }
2786
Hai Shalomfdcde762020-04-02 11:19:20 -07002787#ifdef CONFIG_HE_OVERRIDES
2788 if (ssid->disable_he) {
2789 vht_freq.he_enabled = 0;
2790 freq->he_enabled = 0;
2791 }
2792#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002793 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002794 freq->channel, ssid->enable_edmg,
2795 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002796 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002797 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002798 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002799 chwidth, seg0, seg1, vht_caps,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002800 &mode->he_capab[ieee80211_mode],
2801 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002802 return;
2803
2804 *freq = vht_freq;
2805
2806 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2807 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002808}
2809
2810
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002811#ifdef CONFIG_FILS
2812static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2813 size_t ie_buf_len)
2814{
2815 struct fils_hlp_req *req;
2816 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2817 const u8 *pos;
2818 u8 *buf = ie_buf;
2819
2820 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2821 list) {
2822 rem_len = ie_buf_len - ie_len;
2823 pos = wpabuf_head(req->pkt);
2824 hdr_len = 1 + 2 * ETH_ALEN + 6;
2825 hlp_len = wpabuf_len(req->pkt);
2826
2827 if (rem_len < 2 + hdr_len + hlp_len) {
2828 wpa_printf(MSG_ERROR,
2829 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2830 (unsigned long) rem_len,
2831 (unsigned long) (2 + hdr_len + hlp_len));
2832 break;
2833 }
2834
2835 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2836 /* Element ID */
2837 *buf++ = WLAN_EID_EXTENSION;
2838 /* Length */
2839 *buf++ = len;
2840 /* Element ID Extension */
2841 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2842 /* Destination MAC address */
2843 os_memcpy(buf, req->dst, ETH_ALEN);
2844 buf += ETH_ALEN;
2845 /* Source MAC address */
2846 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2847 buf += ETH_ALEN;
2848 /* LLC/SNAP Header */
2849 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2850 buf += 6;
2851 /* HLP Packet */
2852 os_memcpy(buf, pos, len - hdr_len);
2853 buf += len - hdr_len;
2854 pos += len - hdr_len;
2855
2856 hlp_len -= len - hdr_len;
2857 ie_len += 2 + len;
2858 rem_len -= 2 + len;
2859
2860 while (hlp_len) {
2861 len = (hlp_len > 255) ? 255 : hlp_len;
2862 if (rem_len < 2 + len)
2863 break;
2864 *buf++ = WLAN_EID_FRAGMENT;
2865 *buf++ = len;
2866 os_memcpy(buf, pos, len);
2867 buf += len;
2868 pos += len;
2869
2870 hlp_len -= len;
2871 ie_len += 2 + len;
2872 rem_len -= 2 + len;
2873 }
2874 }
2875
2876 return ie_len;
2877}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002878
2879
2880int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2881{
2882 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2883 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2884 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2885 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2886}
2887
2888
2889int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2890{
2891#ifdef CONFIG_FILS_SK_PFS
2892 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2893 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2894#else /* CONFIG_FILS_SK_PFS */
2895 return 0;
2896#endif /* CONFIG_FILS_SK_PFS */
2897}
2898
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002899#endif /* CONFIG_FILS */
2900
2901
Hai Shalomc1a21442022-02-04 13:43:00 -08002902static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2903 struct wpa_bss *bss,
2904 u8 *wpa_ie, size_t wpa_ie_len,
2905 size_t max_wpa_ie_len)
2906{
2907 struct wpabuf *wfa_ie = NULL;
2908 u8 wfa_capa[1];
2909 size_t wfa_ie_len, buf_len;
2910
2911 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2912 if (wpa_s->enable_dscp_policy_capa)
2913 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2914
2915 if (!wfa_capa[0])
2916 return wpa_ie_len;
2917
2918 /* Wi-Fi Alliance element */
2919 buf_len = 1 + /* Element ID */
2920 1 + /* Length */
2921 3 + /* OUI */
2922 1 + /* OUI Type */
2923 1 + /* Capabilities Length */
2924 sizeof(wfa_capa); /* Capabilities */
2925 wfa_ie = wpabuf_alloc(buf_len);
2926 if (!wfa_ie)
2927 return wpa_ie_len;
2928
2929 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2930 wpabuf_put_u8(wfa_ie, buf_len - 2);
2931 wpabuf_put_be24(wfa_ie, OUI_WFA);
2932 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2933 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2934 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2935
2936 wfa_ie_len = wpabuf_len(wfa_ie);
2937 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2938 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2939 wfa_ie);
2940 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2941 wfa_ie_len);
2942 wpa_ie_len += wfa_ie_len;
2943 }
2944
2945 wpabuf_free(wfa_ie);
2946 return wpa_ie_len;
2947}
2948
2949
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002950static u8 * wpas_populate_assoc_ies(
2951 struct wpa_supplicant *wpa_s,
2952 struct wpa_bss *bss, struct wpa_ssid *ssid,
2953 struct wpa_driver_associate_params *params,
2954 enum wpa_drv_update_connect_params_mask *mask)
2955{
2956 u8 *wpa_ie;
2957 size_t max_wpa_ie_len = 500;
2958 size_t wpa_ie_len;
2959 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002960#ifdef CONFIG_MBO
2961 const u8 *mbo_ie;
2962#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302963#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2964 int pmksa_cached = 0;
2965#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002966#ifdef CONFIG_FILS
2967 const u8 *realm, *username, *rrk;
2968 size_t realm_len, username_len, rrk_len;
2969 u16 next_seq_num;
2970 struct fils_hlp_req *req;
2971
2972 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2973 list) {
2974 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2975 2 + 2 * wpabuf_len(req->pkt) / 255;
2976 }
2977#endif /* CONFIG_FILS */
2978
2979 wpa_ie = os_malloc(max_wpa_ie_len);
2980 if (!wpa_ie) {
2981 wpa_printf(MSG_ERROR,
2982 "Failed to allocate connect IE buffer for %lu bytes",
2983 (unsigned long) max_wpa_ie_len);
2984 return NULL;
2985 }
2986
2987 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2988 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2989 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2990 int try_opportunistic;
2991 const u8 *cache_id = NULL;
2992
2993 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2994 wpa_s->conf->okc :
2995 ssid->proactive_key_caching) &&
2996 (ssid->proto & WPA_PROTO_RSN);
2997#ifdef CONFIG_FILS
2998 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2999 cache_id = wpa_bss_get_fils_cache_id(bss);
3000#endif /* CONFIG_FILS */
3001 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3002 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003003 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003004 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303005#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3006 pmksa_cached = 1;
3007#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003008 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003009 wpa_ie_len = max_wpa_ie_len;
3010 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3011 wpa_ie, &wpa_ie_len)) {
3012 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3013 "key management and encryption suites");
3014 os_free(wpa_ie);
3015 return NULL;
3016 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003017#ifdef CONFIG_HS20
3018 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3019 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3020 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3021 wpa_ie_len = max_wpa_ie_len;
3022 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3023 wpa_ie, &wpa_ie_len)) {
3024 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3025 "key management and encryption suites");
3026 os_free(wpa_ie);
3027 return NULL;
3028 }
3029#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003030 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3031 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3032 /*
3033 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3034 * use non-WPA since the scan results did not indicate that the
3035 * AP is using WPA or WPA2.
3036 */
3037 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3038 wpa_ie_len = 0;
3039 wpa_s->wpa_proto = 0;
3040 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3041 wpa_ie_len = max_wpa_ie_len;
3042 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3043 wpa_ie, &wpa_ie_len)) {
3044 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3045 "key management and encryption suites (no "
3046 "scan results)");
3047 os_free(wpa_ie);
3048 return NULL;
3049 }
3050#ifdef CONFIG_WPS
3051 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3052 struct wpabuf *wps_ie;
3053 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3054 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3055 wpa_ie_len = wpabuf_len(wps_ie);
3056 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3057 } else
3058 wpa_ie_len = 0;
3059 wpabuf_free(wps_ie);
3060 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3061 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3062 params->wps = WPS_MODE_PRIVACY;
3063 else
3064 params->wps = WPS_MODE_OPEN;
3065 wpa_s->wpa_proto = 0;
3066#endif /* CONFIG_WPS */
3067 } else {
3068 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3069 wpa_ie_len = 0;
3070 wpa_s->wpa_proto = 0;
3071 }
3072
3073#ifdef IEEE8021X_EAPOL
3074 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3075 if (ssid->leap) {
3076 if (ssid->non_leap == 0)
3077 algs = WPA_AUTH_ALG_LEAP;
3078 else
3079 algs |= WPA_AUTH_ALG_LEAP;
3080 }
3081 }
3082
3083#ifdef CONFIG_FILS
3084 /* Clear FILS association */
3085 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3086
3087 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3088 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3089 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3090 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003091 &next_seq_num, &rrk, &rrk_len) == 0 &&
3092 (!wpa_s->last_con_fail_realm ||
3093 wpa_s->last_con_fail_realm_len != realm_len ||
3094 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095 algs = WPA_AUTH_ALG_FILS;
3096 params->fils_erp_username = username;
3097 params->fils_erp_username_len = username_len;
3098 params->fils_erp_realm = realm;
3099 params->fils_erp_realm_len = realm_len;
3100 params->fils_erp_next_seq_num = next_seq_num;
3101 params->fils_erp_rrk = rrk;
3102 params->fils_erp_rrk_len = rrk_len;
3103
3104 if (mask)
3105 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303106 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3107 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3108 pmksa_cached) {
3109 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003110 }
3111#endif /* CONFIG_FILS */
3112#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003113#ifdef CONFIG_SAE
3114 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3115 algs = WPA_AUTH_ALG_SAE;
3116#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003117
3118 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3119 if (ssid->auth_alg) {
3120 algs = ssid->auth_alg;
3121 wpa_dbg(wpa_s, MSG_DEBUG,
3122 "Overriding auth_alg selection: 0x%x", algs);
3123 }
3124
Hai Shalom5f92bc92019-04-18 11:54:11 -07003125#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303126 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003127 wpa_dbg(wpa_s, MSG_DEBUG,
3128 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3129 algs = WPA_AUTH_ALG_OPEN;
3130 }
3131#endif /* CONFIG_SAE */
3132
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003133#ifdef CONFIG_P2P
3134 if (wpa_s->global->p2p) {
3135 u8 *pos;
3136 size_t len;
3137 int res;
3138 pos = wpa_ie + wpa_ie_len;
3139 len = max_wpa_ie_len - wpa_ie_len;
3140 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3141 ssid->p2p_group);
3142 if (res >= 0)
3143 wpa_ie_len += res;
3144 }
3145
3146 wpa_s->cross_connect_disallowed = 0;
3147 if (bss) {
3148 struct wpabuf *p2p;
3149 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3150 if (p2p) {
3151 wpa_s->cross_connect_disallowed =
3152 p2p_get_cross_connect_disallowed(p2p);
3153 wpabuf_free(p2p);
3154 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3155 "connection",
3156 wpa_s->cross_connect_disallowed ?
3157 "disallows" : "allows");
3158 }
3159 }
3160
3161 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3162#endif /* CONFIG_P2P */
3163
3164 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003165 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003166 wpa_ie + wpa_ie_len,
3167 max_wpa_ie_len -
3168 wpa_ie_len);
3169 }
3170
3171 /*
3172 * Workaround: Add Extended Capabilities element only if the AP
3173 * included this element in Beacon/Probe Response frames. Some older
3174 * APs seem to have interoperability issues if this element is
3175 * included, so while the standard may require us to include the
3176 * element in all cases, it is justifiable to skip it to avoid
3177 * interoperability issues.
3178 */
3179 if (ssid->p2p_group)
3180 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3181 else
3182 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3183
3184 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3185 u8 ext_capab[18];
3186 int ext_capab_len;
3187 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3188 sizeof(ext_capab));
3189 if (ext_capab_len > 0 &&
3190 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3191 u8 *pos = wpa_ie;
3192 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3193 pos += 2 + pos[1];
3194 os_memmove(pos + ext_capab_len, pos,
3195 wpa_ie_len - (pos - wpa_ie));
3196 wpa_ie_len += ext_capab_len;
3197 os_memcpy(pos, ext_capab, ext_capab_len);
3198 }
3199 }
3200
3201#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003202 if (is_hs20_network(wpa_s, ssid, bss)
3203#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3204 && is_hs20_config(wpa_s)
3205#endif /* ANDROID */
3206 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003207 struct wpabuf *hs20;
3208
Roshan Pius3a1667e2018-07-03 15:17:14 -07003209 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003210 if (hs20) {
3211 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3212 size_t len;
3213
Hai Shalom74f70d42019-02-11 14:42:39 -08003214 wpas_hs20_add_indication(hs20, pps_mo_id,
3215 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003216 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003217 len = max_wpa_ie_len - wpa_ie_len;
3218 if (wpabuf_len(hs20) <= len) {
3219 os_memcpy(wpa_ie + wpa_ie_len,
3220 wpabuf_head(hs20), wpabuf_len(hs20));
3221 wpa_ie_len += wpabuf_len(hs20);
3222 }
3223 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003224 }
3225 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003226 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003227#endif /* CONFIG_HS20 */
3228
3229 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3230 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3231 size_t len;
3232
3233 len = max_wpa_ie_len - wpa_ie_len;
3234 if (wpabuf_len(buf) <= len) {
3235 os_memcpy(wpa_ie + wpa_ie_len,
3236 wpabuf_head(buf), wpabuf_len(buf));
3237 wpa_ie_len += wpabuf_len(buf);
3238 }
3239 }
3240
3241#ifdef CONFIG_FST
3242 if (wpa_s->fst_ies) {
3243 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3244
3245 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3246 os_memcpy(wpa_ie + wpa_ie_len,
3247 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3248 wpa_ie_len += fst_ies_len;
3249 }
3250 }
3251#endif /* CONFIG_FST */
3252
3253#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003254 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003255 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003256 int len;
3257
3258 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003259 max_wpa_ie_len - wpa_ie_len,
3260 !!mbo_attr_from_mbo_ie(mbo_ie,
3261 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003262 if (len >= 0)
3263 wpa_ie_len += len;
3264 }
3265#endif /* CONFIG_MBO */
3266
3267#ifdef CONFIG_FILS
3268 if (algs == WPA_AUTH_ALG_FILS) {
3269 size_t len;
3270
3271 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3272 max_wpa_ie_len - wpa_ie_len);
3273 wpa_ie_len += len;
3274 }
3275#endif /* CONFIG_FILS */
3276
3277#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003278#ifdef CONFIG_TESTING_OPTIONS
3279 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3280 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3281 } else
3282#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003283 if (algs == WPA_AUTH_ALG_OPEN &&
3284 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3285 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003286 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287
Roshan Pius3a1667e2018-07-03 15:17:14 -07003288 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003290 } else if (wpa_s->assoc_status_code ==
3291 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003292 if (wpa_s->last_owe_group == 19)
3293 group = 20;
3294 else if (wpa_s->last_owe_group == 20)
3295 group = 21;
3296 else
3297 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003298 } else {
3299 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003300 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003301
Roshan Pius3a1667e2018-07-03 15:17:14 -07003302 wpa_s->last_owe_group = group;
3303 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003304 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3305 if (owe_ie &&
3306 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3307 os_memcpy(wpa_ie + wpa_ie_len,
3308 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3309 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003310 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003311 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312 }
3313#endif /* CONFIG_OWE */
3314
Hai Shalom021b0b52019-04-10 11:17:58 -07003315#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003316 if (DPP_VERSION > 1 &&
3317 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003318 ssid->dpp_netaccesskey &&
3319 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003320 struct rsn_pmksa_cache_entry *pmksa;
3321
3322 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3323 if (!pmksa || !pmksa->dpp_pfs)
3324 goto pfs_fail;
3325
Hai Shalom021b0b52019-04-10 11:17:58 -07003326 dpp_pfs_free(wpa_s->dpp_pfs);
3327 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3328 ssid->dpp_netaccesskey_len);
3329 if (!wpa_s->dpp_pfs) {
3330 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3331 /* Try to continue without PFS */
3332 goto pfs_fail;
3333 }
3334 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3335 max_wpa_ie_len - wpa_ie_len) {
3336 os_memcpy(wpa_ie + wpa_ie_len,
3337 wpabuf_head(wpa_s->dpp_pfs->ie),
3338 wpabuf_len(wpa_s->dpp_pfs->ie));
3339 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3340 }
3341 }
3342pfs_fail:
3343#endif /* CONFIG_DPP2 */
3344
Roshan Pius3a1667e2018-07-03 15:17:14 -07003345#ifdef CONFIG_IEEE80211R
3346 /*
3347 * Add MDIE under these conditions: the network profile allows FT,
3348 * the AP supports FT, and the mobility domain ID matches.
3349 */
3350 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3351 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3352
3353 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3354 size_t len = 0;
3355 const u8 *md = mdie + 2;
3356 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3357
3358 if (os_memcmp(md, wpa_md,
3359 MOBILITY_DOMAIN_ID_LEN) == 0) {
3360 /* Add mobility domain IE */
3361 len = wpa_ft_add_mdie(
3362 wpa_s->wpa, wpa_ie + wpa_ie_len,
3363 max_wpa_ie_len - wpa_ie_len, mdie);
3364 wpa_ie_len += len;
3365 }
3366#ifdef CONFIG_SME
3367 if (len > 0 && wpa_s->sme.ft_used &&
3368 wpa_sm_has_ptk(wpa_s->wpa)) {
3369 wpa_dbg(wpa_s, MSG_DEBUG,
3370 "SME: Trying to use FT over-the-air");
3371 algs |= WPA_AUTH_ALG_FT;
3372 }
3373#endif /* CONFIG_SME */
3374 }
3375 }
3376#endif /* CONFIG_IEEE80211R */
3377
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003378#ifdef CONFIG_TESTING_OPTIONS
3379 if (wpa_s->rsnxe_override_assoc &&
3380 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3381 max_wpa_ie_len - wpa_ie_len) {
3382 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3383 os_memcpy(wpa_ie + wpa_ie_len,
3384 wpabuf_head(wpa_s->rsnxe_override_assoc),
3385 wpabuf_len(wpa_s->rsnxe_override_assoc));
3386 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3387 } else
3388#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003389 if (wpa_s->rsnxe_len > 0 &&
3390 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3391 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3392 wpa_ie_len += wpa_s->rsnxe_len;
3393 }
3394
Hai Shalomc1a21442022-02-04 13:43:00 -08003395#ifdef CONFIG_TESTING_OPTIONS
3396 if (wpa_s->disable_mscs_support)
3397 goto mscs_end;
3398#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003399 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3400 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003401 struct wpabuf *mscs_ie;
3402 size_t mscs_ie_len, buf_len;
3403
Hai Shalom899fcc72020-10-19 14:38:18 -07003404 buf_len = 3 + /* MSCS descriptor IE header */
3405 1 + /* Request type */
3406 2 + /* User priority control */
3407 4 + /* Stream timeout */
3408 3 + /* TCLAS Mask IE header */
3409 wpa_s->robust_av.frame_classifier_len;
3410 mscs_ie = wpabuf_alloc(buf_len);
3411 if (!mscs_ie) {
3412 wpa_printf(MSG_INFO,
3413 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003414 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003415 }
3416
3417 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3418 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3419 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3420 mscs_ie_len = wpabuf_len(mscs_ie);
3421 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3422 mscs_ie_len);
3423 wpa_ie_len += mscs_ie_len;
3424 }
3425
3426 wpabuf_free(mscs_ie);
3427 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003428mscs_end:
3429
3430 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3431 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003432
Hai Shalom74f70d42019-02-11 14:42:39 -08003433 if (ssid->multi_ap_backhaul_sta) {
3434 size_t multi_ap_ie_len;
3435
3436 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3437 max_wpa_ie_len - wpa_ie_len,
3438 MULTI_AP_BACKHAUL_STA);
3439 if (multi_ap_ie_len == 0) {
3440 wpa_printf(MSG_ERROR,
3441 "Multi-AP: Failed to build Multi-AP IE");
3442 os_free(wpa_ie);
3443 return NULL;
3444 }
3445 wpa_ie_len += multi_ap_ie_len;
3446 }
3447
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003448 params->wpa_ie = wpa_ie;
3449 params->wpa_ie_len = wpa_ie_len;
3450 params->auth_alg = algs;
3451 if (mask)
3452 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3453
3454 return wpa_ie;
3455}
3456
3457
Hai Shalomc3565922019-10-28 11:58:20 -07003458#ifdef CONFIG_OWE
3459static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3460{
3461 struct wpa_driver_associate_params params;
3462 u8 *wpa_ie;
3463
3464 os_memset(&params, 0, sizeof(params));
3465 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3466 wpa_s->current_ssid, &params, NULL);
3467 if (!wpa_ie)
3468 return;
3469
3470 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3471 os_free(wpa_ie);
3472}
3473#endif /* CONFIG_OWE */
3474
3475
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003476#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3477static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3478{
3479 struct wpa_driver_associate_params params;
3480 enum wpa_drv_update_connect_params_mask mask = 0;
3481 u8 *wpa_ie;
3482
3483 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3484 return; /* nothing to do */
3485
3486 os_memset(&params, 0, sizeof(params));
3487 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3488 wpa_s->current_ssid, &params, &mask);
3489 if (!wpa_ie)
3490 return;
3491
Hai Shalomc1a21442022-02-04 13:43:00 -08003492 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3493 wpa_s->auth_alg = params.auth_alg;
3494 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003495 }
3496
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003497 os_free(wpa_ie);
3498}
3499#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3500
3501
Hai Shalomc3565922019-10-28 11:58:20 -07003502static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3503{
3504 if (!edmg_ie || edmg_ie[1] < 6)
3505 return 0;
3506 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3507}
3508
3509
3510static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3511{
3512 if (!edmg_ie || edmg_ie[1] < 6)
3513 return 0;
3514 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3515}
3516
3517
3518/* Returns the intersection of two EDMG configurations.
3519 * Note: The current implementation is limited to CB2 only (CB1 included),
3520 * i.e., the implementation supports up to 2 contiguous channels.
3521 * For supporting non-contiguous (aggregated) channels and for supporting
3522 * CB3 and above, this function will need to be extended.
3523 */
3524static struct ieee80211_edmg_config
3525get_edmg_intersection(struct ieee80211_edmg_config a,
3526 struct ieee80211_edmg_config b,
3527 u8 primary_channel)
3528{
3529 struct ieee80211_edmg_config result;
3530 int i, contiguous = 0;
3531 int max_contiguous = 0;
3532
3533 result.channels = b.channels & a.channels;
3534 if (!result.channels) {
3535 wpa_printf(MSG_DEBUG,
3536 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3537 a.channels, b.channels);
3538 goto fail;
3539 }
3540
3541 if (!(result.channels & BIT(primary_channel - 1))) {
3542 wpa_printf(MSG_DEBUG,
3543 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3544 primary_channel, result.channels);
3545 goto fail;
3546 }
3547
3548 /* Find max contiguous channels */
3549 for (i = 0; i < 6; i++) {
3550 if (result.channels & BIT(i))
3551 contiguous++;
3552 else
3553 contiguous = 0;
3554
3555 if (contiguous > max_contiguous)
3556 max_contiguous = contiguous;
3557 }
3558
3559 /* Assuming AP and STA supports ONLY contiguous channels,
3560 * bw configuration can have value between 4-7.
3561 */
3562 if ((b.bw_config < a.bw_config))
3563 result.bw_config = b.bw_config;
3564 else
3565 result.bw_config = a.bw_config;
3566
3567 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3568 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3569 wpa_printf(MSG_DEBUG,
3570 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3571 max_contiguous);
3572 goto fail;
3573 }
3574
3575 return result;
3576
3577fail:
3578 result.channels = 0;
3579 result.bw_config = 0;
3580 return result;
3581}
3582
3583
3584static struct ieee80211_edmg_config
3585get_supported_edmg(struct wpa_supplicant *wpa_s,
3586 struct hostapd_freq_params *freq,
3587 struct ieee80211_edmg_config request_edmg)
3588{
3589 enum hostapd_hw_mode hw_mode;
3590 struct hostapd_hw_modes *mode = NULL;
3591 u8 primary_channel;
3592
3593 if (!wpa_s->hw.modes)
3594 goto fail;
3595
3596 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3597 if (hw_mode == NUM_HOSTAPD_MODES)
3598 goto fail;
3599
Hai Shalom60840252021-02-19 19:02:11 -08003600 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003601 if (!mode)
3602 goto fail;
3603
3604 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3605
3606fail:
3607 request_edmg.channels = 0;
3608 request_edmg.bw_config = 0;
3609 return request_edmg;
3610}
3611
3612
Hai Shalom021b0b52019-04-10 11:17:58 -07003613#ifdef CONFIG_MBO
3614void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3615{
3616 struct wpa_driver_associate_params params;
3617 u8 *wpa_ie;
3618
3619 /*
3620 * Update MBO connect params only in case of change of MBO attributes
3621 * when connected, if the AP support MBO.
3622 */
3623
3624 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3625 !wpa_s->current_bss ||
3626 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3627 return;
3628
3629 os_memset(&params, 0, sizeof(params));
3630 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3631 wpa_s->current_ssid, &params, NULL);
3632 if (!wpa_ie)
3633 return;
3634
3635 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3636 os_free(wpa_ie);
3637}
3638#endif /* CONFIG_MBO */
3639
3640
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003641static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3642{
3643 struct wpa_connect_work *cwork = work->ctx;
3644 struct wpa_bss *bss = cwork->bss;
3645 struct wpa_ssid *ssid = cwork->ssid;
3646 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003647 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003648 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003649 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003650 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003651 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003652#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003653 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003654#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003655 int assoc_failed = 0;
3656 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003657 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003658#ifdef CONFIG_HT_OVERRIDES
3659 struct ieee80211_ht_capabilities htcaps;
3660 struct ieee80211_ht_capabilities htcaps_mask;
3661#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003662#ifdef CONFIG_VHT_OVERRIDES
3663 struct ieee80211_vht_capabilities vhtcaps;
3664 struct ieee80211_vht_capabilities vhtcaps_mask;
3665#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003666
Hai Shalomc1a21442022-02-04 13:43:00 -08003667 wpa_s->roam_in_progress = false;
3668#ifdef CONFIG_WNM
3669 wpa_s->bss_trans_mgmt_in_progress = false;
3670#endif /* CONFIG_WNM */
3671
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003672 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003673 if (work->started) {
3674 wpa_s->connect_work = NULL;
3675
3676 /* cancel possible auth. timeout */
3677 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3678 NULL);
3679 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003680 wpas_connect_work_free(cwork);
3681 return;
3682 }
3683
3684 wpa_s->connect_work = work;
3685
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003686 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3687 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003688 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3689 wpas_connect_work_done(wpa_s);
3690 return;
3691 }
3692
Dmitry Shmidte4663042016-04-04 10:07:49 -07003693 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003694 os_memset(&params, 0, sizeof(params));
3695 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003696 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003697
3698 /* Starting new association, so clear the possibly used WPA IE from the
3699 * previous association. */
3700 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3701 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3702 wpa_s->rsnxe_len = 0;
3703 wpa_s->mscs_setup_done = false;
3704
3705 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3706 if (!wpa_ie) {
3707 wpas_connect_work_done(wpa_s);
3708 return;
3709 }
3710
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003711 if (bss &&
3712 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003713#ifdef CONFIG_IEEE80211R
3714 const u8 *ie, *md = NULL;
3715#endif /* CONFIG_IEEE80211R */
3716 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3717 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3718 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3719 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3720 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3721 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3722 if (bssid_changed)
3723 wpas_notify_bssid_changed(wpa_s);
3724#ifdef CONFIG_IEEE80211R
3725 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3726 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3727 md = ie + 2;
3728 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3729 if (md) {
3730 /* Prepare for the next transition */
3731 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3732 }
3733#endif /* CONFIG_IEEE80211R */
3734#ifdef CONFIG_WPS
3735 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3736 wpa_s->conf->ap_scan == 2 &&
3737 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3738 /* Use ap_scan==1 style network selection to find the network
3739 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003740 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003741 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003742 wpa_s->reassociate = 1;
3743 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003744 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003745 return;
3746#endif /* CONFIG_WPS */
3747 } else {
3748 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3749 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003750 if (bss)
3751 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3752 else
3753 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003755 if (!wpa_s->pno)
3756 wpa_supplicant_cancel_sched_scan(wpa_s);
3757
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 wpa_supplicant_cancel_scan(wpa_s);
3759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003760 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3761 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003762 cipher_pairwise = wpa_s->pairwise_cipher;
3763 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003764 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3766 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3767 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3768 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003769#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003770 if (wpa_set_wep_keys(wpa_s, ssid)) {
3771 use_crypt = 1;
3772 wep_keys_set = 1;
3773 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003774#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003775 }
3776 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3777 use_crypt = 0;
3778
3779#ifdef IEEE8021X_EAPOL
3780 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3781 if ((ssid->eapol_flags &
3782 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3783 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3784 !wep_keys_set) {
3785 use_crypt = 0;
3786 } else {
3787 /* Assume that dynamic WEP-104 keys will be used and
3788 * set cipher suites in order for drivers to expect
3789 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003790 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003791 }
3792 }
3793#endif /* IEEE8021X_EAPOL */
3794
3795 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3796 /* Set the key before (and later after) association */
3797 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3798 }
3799
3800 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3801 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003802 params.ssid = bss->ssid;
3803 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003804 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3805 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003806 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3807 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003808 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003809 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003810 ssid->bssid_set,
3811 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003812 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003813 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003814 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003815 params.bssid_hint = bss->bssid;
3816 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003817 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003819 if (ssid->bssid_hint_set)
3820 params.bssid_hint = ssid->bssid_hint;
3821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822 params.ssid = ssid->ssid;
3823 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003824 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003826
3827 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3828 wpa_s->conf->ap_scan == 2) {
3829 params.bssid = ssid->bssid;
3830 params.fixed_bssid = 1;
3831 }
3832
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003833 /* Initial frequency for IBSS/mesh */
3834 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003835 ssid->frequency > 0 && params.freq.freq == 0)
3836 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003837
3838 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003839 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003840 if (ssid->beacon_int)
3841 params.beacon_int = ssid->beacon_int;
3842 else
3843 params.beacon_int = wpa_s->conf->beacon_int;
3844 }
3845
Hai Shalomc3565922019-10-28 11:58:20 -07003846 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003847 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3848 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003849 else
3850 edmg_ie_oper = NULL;
3851
3852 if (edmg_ie_oper) {
3853 params.freq.edmg.channels =
3854 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3855 params.freq.edmg.bw_config =
3856 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3857 wpa_printf(MSG_DEBUG,
3858 "AP supports EDMG channels 0x%x, bw_config %d",
3859 params.freq.edmg.channels,
3860 params.freq.edmg.bw_config);
3861
3862 /* User may ask for specific EDMG channel for EDMG connection
3863 * (must be supported by AP)
3864 */
3865 if (ssid->edmg_channel) {
3866 struct ieee80211_edmg_config configured_edmg;
3867 enum hostapd_hw_mode hw_mode;
3868 u8 primary_channel;
3869
3870 hw_mode = ieee80211_freq_to_chan(bss->freq,
3871 &primary_channel);
3872 if (hw_mode == NUM_HOSTAPD_MODES)
3873 goto edmg_fail;
3874
3875 hostapd_encode_edmg_chan(ssid->enable_edmg,
3876 ssid->edmg_channel,
3877 primary_channel,
3878 &configured_edmg);
3879
3880 if (ieee802_edmg_is_allowed(params.freq.edmg,
3881 configured_edmg)) {
3882 params.freq.edmg = configured_edmg;
3883 wpa_printf(MSG_DEBUG,
3884 "Use EDMG channel %d for connection",
3885 ssid->edmg_channel);
3886 } else {
3887 edmg_fail:
3888 params.freq.edmg.channels = 0;
3889 params.freq.edmg.bw_config = 0;
3890 wpa_printf(MSG_WARNING,
3891 "EDMG channel %d not supported by AP, fallback to DMG",
3892 ssid->edmg_channel);
3893 }
3894 }
3895
3896 if (params.freq.edmg.channels) {
3897 wpa_printf(MSG_DEBUG,
3898 "EDMG before: channels 0x%x, bw_config %d",
3899 params.freq.edmg.channels,
3900 params.freq.edmg.bw_config);
3901 params.freq.edmg = get_supported_edmg(wpa_s,
3902 &params.freq,
3903 params.freq.edmg);
3904 wpa_printf(MSG_DEBUG,
3905 "EDMG after: channels 0x%x, bw_config %d",
3906 params.freq.edmg.channels,
3907 params.freq.edmg.bw_config);
3908 }
3909 }
3910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003911 params.pairwise_suite = cipher_pairwise;
3912 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003913 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003914 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003915 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003916 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003918 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003919#ifdef CONFIG_WEP
3920 {
3921 int i;
3922
3923 for (i = 0; i < NUM_WEP_KEYS; i++) {
3924 if (ssid->wep_key_len[i])
3925 params.wep_key[i] = ssid->wep_key[i];
3926 params.wep_key_len[i] = ssid->wep_key_len[i];
3927 }
3928 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003930#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931
Hai Shalom74f70d42019-02-11 14:42:39 -08003932 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303933 (
3934#ifdef CONFIG_DRIVER_NL80211_BRCM
3935 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3936#else
3937 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3938#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003939 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 params.passphrase = ssid->passphrase;
3941 if (ssid->psk_set)
3942 params.psk = ssid->psk;
3943 }
3944
Hai Shalom74f70d42019-02-11 14:42:39 -08003945 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3946 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3947 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3948 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3949 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003950 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003951
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003952 if (wpa_s->conf->key_mgmt_offload) {
3953 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3954 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003955 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3956 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003957 params.req_key_mgmt_offload =
3958 ssid->proactive_key_caching < 0 ?
3959 wpa_s->conf->okc : ssid->proactive_key_caching;
3960 else
3961 params.req_key_mgmt_offload = 1;
3962
Vinayak Yadawad14709082022-03-17 14:25:11 +05303963 if ((
3964#ifdef CONFIG_DRIVER_NL80211_BRCM
3965 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3966#else
3967 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3968#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003969 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3970 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3971 ssid->psk_set)
3972 params.psk = ssid->psk;
3973 }
3974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003975 params.drop_unencrypted = use_crypt;
3976
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003977 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003978 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003979 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3980 struct wpa_ie_data ie;
3981 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3982 ie.capabilities &
3983 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3984 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3985 "MFP: require MFP");
3986 params.mgmt_frame_protection =
3987 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003988#ifdef CONFIG_OWE
3989 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3990 !ssid->owe_only) {
3991 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3992#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993 }
3994 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003996 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003998 if (wpa_s->p2pdev->set_sta_uapsd)
3999 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000 else
4001 params.uapsd = -1;
4002
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004003#ifdef CONFIG_HT_OVERRIDES
4004 os_memset(&htcaps, 0, sizeof(htcaps));
4005 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4006 params.htcaps = (u8 *) &htcaps;
4007 params.htcaps_mask = (u8 *) &htcaps_mask;
4008 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4009#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004010#ifdef CONFIG_VHT_OVERRIDES
4011 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4012 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4013 params.vhtcaps = &vhtcaps;
4014 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004015 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004016#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004017#ifdef CONFIG_HE_OVERRIDES
4018 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4019#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004020
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004021#ifdef CONFIG_P2P
4022 /*
4023 * If multi-channel concurrency is not supported, check for any
4024 * frequency conflict. In case of any frequency conflict, remove the
4025 * least prioritized connection.
4026 */
4027 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004028 int freq, num;
4029 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004030 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004031 wpa_printf(MSG_DEBUG,
4032 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004033 freq, params.freq.freq);
4034 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004035 wpa_s, params.freq.freq, ssid) < 0) {
4036 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004037 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004038 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004039 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004040 }
4041 }
4042#endif /* CONFIG_P2P */
4043
Dmitry Shmidte4663042016-04-04 10:07:49 -07004044 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
4045 wpa_s->current_ssid)
4046 params.prev_bssid = prev_bssid;
4047
Hai Shalom60840252021-02-19 19:02:11 -08004048#ifdef CONFIG_SAE
4049 params.sae_pwe = wpa_s->conf->sae_pwe;
4050#endif /* CONFIG_SAE */
4051
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004052 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004053 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004054 if (ret < 0) {
4055 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4056 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004057 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004058 /*
4059 * The driver is known to mean what is saying, so we
4060 * can stop right here; the association will not
4061 * succeed.
4062 */
4063 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004064 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004065 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004066 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004067 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4068 return;
4069 }
4070 /* try to continue anyway; new association will be tried again
4071 * after timeout */
4072 assoc_failed = 1;
4073 }
4074
4075 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4076 /* Set the key after the association just in case association
4077 * cleared the previously configured key. */
4078 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4079 /* No need to timeout authentication since there is no key
4080 * management. */
4081 wpa_supplicant_cancel_auth_timeout(wpa_s);
4082 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4083#ifdef CONFIG_IBSS_RSN
4084 } else if (ssid->mode == WPAS_MODE_IBSS &&
4085 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4086 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4087 /*
4088 * RSN IBSS authentication is per-STA and we can disable the
4089 * per-BSSID authentication.
4090 */
4091 wpa_supplicant_cancel_auth_timeout(wpa_s);
4092#endif /* CONFIG_IBSS_RSN */
4093 } else {
4094 /* Timeout for IEEE 802.11 authentication and association */
4095 int timeout = 60;
4096
4097 if (assoc_failed) {
4098 /* give IBSS a bit more time */
4099 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4100 } else if (wpa_s->conf->ap_scan == 1) {
4101 /* give IBSS a bit more time */
4102 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4103 }
4104 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4105 }
4106
Hai Shalomfdcde762020-04-02 11:19:20 -07004107#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004108 if (wep_keys_set &&
4109 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 /* Set static WEP keys again */
4111 wpa_set_wep_keys(wpa_s, ssid);
4112 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004113#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114
4115 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
4116 /*
4117 * Do not allow EAP session resumption between different
4118 * network configurations.
4119 */
4120 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4121 }
4122 old_ssid = wpa_s->current_ssid;
4123 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004124
4125 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004126 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004127#ifdef CONFIG_HS20
4128 hs20_configure_frame_filters(wpa_s);
4129#endif /* CONFIG_HS20 */
4130 }
4131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4133 wpa_supplicant_initiate_eapol(wpa_s);
4134 if (old_ssid != wpa_s->current_ssid)
4135 wpas_notify_network_changed(wpa_s);
4136}
4137
4138
4139static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4140 const u8 *addr)
4141{
4142 struct wpa_ssid *old_ssid;
4143
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004144 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004145 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004147 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148 wpa_sm_set_config(wpa_s->wpa, NULL);
4149 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4150 if (old_ssid != wpa_s->current_ssid)
4151 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004152
4153 wpas_scs_deinit(wpa_s);
4154 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4156}
4157
4158
4159/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4161 * @wpa_s: Pointer to wpa_supplicant data
4162 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4163 *
4164 * This function is used to request %wpa_supplicant to deauthenticate from the
4165 * current AP.
4166 */
4167void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004168 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004169{
4170 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004171 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004172 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004174 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004175 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004176 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004177 reason_code, reason2str(reason_code),
4178 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004179
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004180 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4181 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4182 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004183 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004184 else if (!is_zero_ether_addr(wpa_s->bssid))
4185 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004186 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4187 /*
4188 * When using driver-based BSS selection, we may not know the
4189 * BSSID with which we are currently trying to associate. We
4190 * need to notify the driver of this disconnection even in such
4191 * a case, so use the all zeros address here.
4192 */
4193 addr = wpa_s->bssid;
4194 zero_addr = 1;
4195 }
4196
Hai Shalom74f70d42019-02-11 14:42:39 -08004197 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4198 wpa_s->enabled_4addr_mode = 0;
4199
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004200#ifdef CONFIG_TDLS
4201 wpa_tdls_teardown_peers(wpa_s->wpa);
4202#endif /* CONFIG_TDLS */
4203
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004204#ifdef CONFIG_MESH
4205 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004206 struct mesh_conf *mconf;
4207
4208 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004209 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4210 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004211 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4212 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004213 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004214 }
4215#endif /* CONFIG_MESH */
4216
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004217 if (addr) {
4218 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004219 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004220 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004221 event.deauth_info.locally_generated = 1;
4222 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004223 if (zero_addr)
4224 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225 }
4226
4227 wpa_supplicant_clear_connection(wpa_s, addr);
4228}
4229
Hai Shalomfdcde762020-04-02 11:19:20 -07004230
4231void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4232{
4233 wpa_s->own_reconnect_req = 1;
4234 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4235
4236}
4237
4238
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004239static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4240 struct wpa_ssid *ssid)
4241{
4242 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4243 return;
4244
4245 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004246 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004247 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4248 wpas_notify_network_enabled_changed(wpa_s, ssid);
4249
4250 /*
4251 * Try to reassociate since there is no current configuration and a new
4252 * network was made available.
4253 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004254 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004255 wpa_s->reassociate = 1;
4256}
4257
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004258
Roshan Pius950bec92016-07-19 09:49:24 -07004259/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004260 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004261 * @wpa_s: wpa_supplicant structure for a network interface
4262 * Returns: The new network configuration or %NULL if operation failed
4263 *
4264 * This function performs the following operations:
4265 * 1. Adds a new network.
4266 * 2. Send network addition notification.
4267 * 3. Marks the network disabled.
4268 * 4. Set network default parameters.
4269 */
4270struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4271{
4272 struct wpa_ssid *ssid;
4273
4274 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004275 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004276 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004277 wpas_notify_network_added(wpa_s, ssid);
4278 ssid->disabled = 1;
4279 wpa_config_set_network_defaults(ssid);
4280
4281 return ssid;
4282}
4283
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004284
Roshan Pius950bec92016-07-19 09:49:24 -07004285/**
4286 * wpa_supplicant_remove_network - Remove a configured network based on id
4287 * @wpa_s: wpa_supplicant structure for a network interface
4288 * @id: Unique network id to search for
4289 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4290 * could not be removed
4291 *
4292 * This function performs the following operations:
4293 * 1. Removes the network.
4294 * 2. Send network removal notification.
4295 * 3. Update internal state machines.
4296 * 4. Stop any running sched scans.
4297 */
4298int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4299{
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004300 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004301 int was_disabled;
4302
4303 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004304 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004305 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004306 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004307
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004308 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004309#ifdef CONFIG_SME
4310 wpa_s->sme.prev_bssid_set = 0;
4311#endif /* CONFIG_SME */
4312 /*
4313 * Invalidate the EAP session cache if the current or
4314 * previously used network is removed.
4315 */
4316 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4317 }
4318
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004319 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004320 wpa_sm_set_config(wpa_s->wpa, NULL);
4321 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4322
4323 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4324 wpa_s->own_disconnect_req = 1;
4325 wpa_supplicant_deauthenticate(wpa_s,
4326 WLAN_REASON_DEAUTH_LEAVING);
4327 }
4328
4329 was_disabled = ssid->disabled;
4330
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004331 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004332 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004333
4334 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004335 wpa_printf(MSG_DEBUG,
4336 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004337 wpa_supplicant_cancel_sched_scan(wpa_s);
4338 wpa_supplicant_req_scan(wpa_s, 0, 0);
4339 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004340
Roshan Pius950bec92016-07-19 09:49:24 -07004341 return 0;
4342}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004346 * wpa_supplicant_remove_all_networks - Remove all configured networks
4347 * @wpa_s: wpa_supplicant structure for a network interface
4348 * Returns: 0 on success (errors are currently ignored)
4349 *
4350 * This function performs the following operations:
4351 * 1. Remove all networks.
4352 * 2. Send network removal notifications.
4353 * 3. Update internal state machines.
4354 * 4. Stop any running sched scans.
4355 */
4356int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4357{
4358 struct wpa_ssid *ssid;
4359
4360 if (wpa_s->sched_scanning)
4361 wpa_supplicant_cancel_sched_scan(wpa_s);
4362
4363 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4364 if (wpa_s->current_ssid) {
4365#ifdef CONFIG_SME
4366 wpa_s->sme.prev_bssid_set = 0;
4367#endif /* CONFIG_SME */
4368 wpa_sm_set_config(wpa_s->wpa, NULL);
4369 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4370 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4371 wpa_s->own_disconnect_req = 1;
4372 wpa_supplicant_deauthenticate(
4373 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4374 }
4375 ssid = wpa_s->conf->ssid;
4376 while (ssid) {
4377 struct wpa_ssid *remove_ssid = ssid;
4378 int id;
4379
4380 id = ssid->id;
4381 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004382 wpas_notify_network_removed(wpa_s, remove_ssid);
4383 wpa_config_remove_network(wpa_s->conf, id);
4384 }
4385 return 0;
4386}
4387
4388
4389/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004390 * wpa_supplicant_enable_network - Mark a configured network as enabled
4391 * @wpa_s: wpa_supplicant structure for a network interface
4392 * @ssid: wpa_ssid structure for a configured network or %NULL
4393 *
4394 * Enables the specified network or all networks if no network specified.
4395 */
4396void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4397 struct wpa_ssid *ssid)
4398{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004399 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004400 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4401 wpa_supplicant_enable_one_network(wpa_s, ssid);
4402 } else
4403 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004405 if (wpa_s->reassociate && !wpa_s->disconnected &&
4406 (!wpa_s->current_ssid ||
4407 wpa_s->wpa_state == WPA_DISCONNECTED ||
4408 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004409 if (wpa_s->sched_scanning) {
4410 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4411 "new network to scan filters");
4412 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004413 }
4414
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004415 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4416 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004417 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004418 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004419 }
4420}
4421
4422
4423/**
4424 * wpa_supplicant_disable_network - Mark a configured network as disabled
4425 * @wpa_s: wpa_supplicant structure for a network interface
4426 * @ssid: wpa_ssid structure for a configured network or %NULL
4427 *
4428 * Disables the specified network or all networks if no network specified.
4429 */
4430void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4431 struct wpa_ssid *ssid)
4432{
4433 struct wpa_ssid *other_ssid;
4434 int was_disabled;
4435
4436 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004437 if (wpa_s->sched_scanning)
4438 wpa_supplicant_cancel_sched_scan(wpa_s);
4439
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004440 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4441 other_ssid = other_ssid->next) {
4442 was_disabled = other_ssid->disabled;
4443 if (was_disabled == 2)
4444 continue; /* do not change persistent P2P group
4445 * data */
4446
4447 other_ssid->disabled = 1;
4448
4449 if (was_disabled != other_ssid->disabled)
4450 wpas_notify_network_enabled_changed(
4451 wpa_s, other_ssid);
4452 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004453 if (wpa_s->current_ssid) {
4454 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4455 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004456 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004458 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004459 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004460 if (ssid == wpa_s->current_ssid) {
4461 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4462 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004463 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004465 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004466
4467 was_disabled = ssid->disabled;
4468
4469 ssid->disabled = 1;
4470
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004471 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004473 if (wpa_s->sched_scanning) {
4474 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4475 "to remove network from filters");
4476 wpa_supplicant_cancel_sched_scan(wpa_s);
4477 wpa_supplicant_req_scan(wpa_s, 0, 0);
4478 }
4479 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004480 }
4481}
4482
4483
4484/**
4485 * wpa_supplicant_select_network - Attempt association with a network
4486 * @wpa_s: wpa_supplicant structure for a network interface
4487 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4488 */
4489void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4490 struct wpa_ssid *ssid)
4491{
4492
4493 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004494 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004495
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004496 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004497 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4498 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004499 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004501 disconnected = 1;
4502 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004504 if (ssid)
4505 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507 /*
4508 * Mark all other networks disabled or mark all networks enabled if no
4509 * network specified.
4510 */
4511 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4512 other_ssid = other_ssid->next) {
4513 int was_disabled = other_ssid->disabled;
4514 if (was_disabled == 2)
4515 continue; /* do not change persistent P2P group data */
4516
4517 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004518 if (was_disabled && !other_ssid->disabled)
4519 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004520
4521 if (was_disabled != other_ssid->disabled)
4522 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4523 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004524
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004525 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4526 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004527 /* We are already associated with the selected network */
4528 wpa_printf(MSG_DEBUG, "Already associated with the "
4529 "selected network - do nothing");
4530 return;
4531 }
4532
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004533 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004534 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004535 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004536 wpa_s->connect_without_scan =
4537 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004538
4539 /*
4540 * Don't optimize next scan freqs since a new ESS has been
4541 * selected.
4542 */
4543 os_free(wpa_s->next_scan_freqs);
4544 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004545 } else {
4546 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004547 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004549 wpa_s->disconnected = 0;
4550 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004551 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004552 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004553 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004554 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004555 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4556 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004557
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004558 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004559 wpa_supplicant_fast_associate(wpa_s) != 1) {
4560 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004561 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004562 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004563 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004564
4565 if (ssid)
4566 wpas_notify_network_selected(wpa_s, ssid);
4567}
4568
4569
4570/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004571 * wpas_remove_cred - Remove the specified credential and all the network
4572 * entries created based on the removed credential
4573 * @wpa_s: wpa_supplicant structure for a network interface
4574 * @cred: The credential to remove
4575 * Returns: 0 on success, -1 on failure
4576 */
4577int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4578{
4579 struct wpa_ssid *ssid, *next;
4580 int id;
4581
4582 if (!cred) {
4583 wpa_printf(MSG_DEBUG, "Could not find cred");
4584 return -1;
4585 }
4586
4587 id = cred->id;
4588 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4589 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4590 return -1;
4591 }
4592
4593 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4594
4595 /* Remove any network entry created based on the removed credential */
4596 ssid = wpa_s->conf->ssid;
4597 while (ssid) {
4598 next = ssid->next;
4599
4600 if (ssid->parent_cred == cred) {
4601 wpa_printf(MSG_DEBUG,
4602 "Remove network id %d since it used the removed credential",
4603 ssid->id);
4604 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4605 -1) {
4606 wpa_printf(MSG_DEBUG,
4607 "Could not find network id=%d",
4608 ssid->id);
4609 }
4610 }
4611
4612 ssid = next;
4613 }
4614
4615 return 0;
4616}
4617
4618
4619/**
4620 * wpas_remove_cred - Remove all the Interworking credentials
4621 * @wpa_s: wpa_supplicant structure for a network interface
4622 * Returns: 0 on success, -1 on failure
4623 */
4624int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4625{
4626 int res, ret = 0;
4627 struct wpa_cred *cred, *prev;
4628
4629 cred = wpa_s->conf->cred;
4630 while (cred) {
4631 prev = cred;
4632 cred = cred->next;
4633 res = wpas_remove_cred(wpa_s, prev);
4634 if (res < 0) {
4635 wpa_printf(MSG_DEBUG,
4636 "Removal of all credentials failed - failed to remove credential id=%d",
4637 prev->id);
4638 ret = -1;
4639 }
4640 }
4641
4642 return ret;
4643}
4644
4645
4646/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004647 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4648 * @wpa_s: wpa_supplicant structure for a network interface
4649 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4650 * @pkcs11_module_path: PKCS #11 module path or NULL
4651 * Returns: 0 on success; -1 on failure
4652 *
4653 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4654 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4655 * module path fails the paths will be reset to the default value (NULL).
4656 */
4657int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4658 const char *pkcs11_engine_path,
4659 const char *pkcs11_module_path)
4660{
4661 char *pkcs11_engine_path_copy = NULL;
4662 char *pkcs11_module_path_copy = NULL;
4663
4664 if (pkcs11_engine_path != NULL) {
4665 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4666 if (pkcs11_engine_path_copy == NULL)
4667 return -1;
4668 }
4669 if (pkcs11_module_path != NULL) {
4670 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004671 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004672 os_free(pkcs11_engine_path_copy);
4673 return -1;
4674 }
4675 }
4676
4677 os_free(wpa_s->conf->pkcs11_engine_path);
4678 os_free(wpa_s->conf->pkcs11_module_path);
4679 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4680 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4681
4682 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4683 eapol_sm_deinit(wpa_s->eapol);
4684 wpa_s->eapol = NULL;
4685 if (wpa_supplicant_init_eapol(wpa_s)) {
4686 /* Error -> Reset paths to the default value (NULL) once. */
4687 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4688 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4689 NULL);
4690
4691 return -1;
4692 }
4693 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4694
4695 return 0;
4696}
4697
4698
4699/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004700 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4701 * @wpa_s: wpa_supplicant structure for a network interface
4702 * @ap_scan: AP scan mode
4703 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4704 *
4705 */
4706int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4707{
4708
4709 int old_ap_scan;
4710
4711 if (ap_scan < 0 || ap_scan > 2)
4712 return -1;
4713
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004714 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4715 wpa_printf(MSG_INFO,
4716 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4717 }
4718
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004719#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004720 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4721 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4722 wpa_s->wpa_state < WPA_COMPLETED) {
4723 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4724 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004725 return 0;
4726 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004727#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004728
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004729 old_ap_scan = wpa_s->conf->ap_scan;
4730 wpa_s->conf->ap_scan = ap_scan;
4731
4732 if (old_ap_scan != wpa_s->conf->ap_scan)
4733 wpas_notify_ap_scan_changed(wpa_s);
4734
4735 return 0;
4736}
4737
4738
4739/**
4740 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4741 * @wpa_s: wpa_supplicant structure for a network interface
4742 * @expire_age: Expiration age in seconds
4743 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4744 *
4745 */
4746int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4747 unsigned int bss_expire_age)
4748{
4749 if (bss_expire_age < 10) {
4750 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4751 bss_expire_age);
4752 return -1;
4753 }
4754 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4755 bss_expire_age);
4756 wpa_s->conf->bss_expiration_age = bss_expire_age;
4757
4758 return 0;
4759}
4760
4761
4762/**
4763 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4764 * @wpa_s: wpa_supplicant structure for a network interface
4765 * @expire_count: number of scans after which an unseen BSS is reclaimed
4766 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4767 *
4768 */
4769int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4770 unsigned int bss_expire_count)
4771{
4772 if (bss_expire_count < 1) {
4773 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4774 bss_expire_count);
4775 return -1;
4776 }
4777 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4778 bss_expire_count);
4779 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4780
4781 return 0;
4782}
4783
4784
4785/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004786 * wpa_supplicant_set_scan_interval - Set scan interval
4787 * @wpa_s: wpa_supplicant structure for a network interface
4788 * @scan_interval: scan interval in seconds
4789 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4790 *
4791 */
4792int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4793 int scan_interval)
4794{
4795 if (scan_interval < 0) {
4796 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4797 scan_interval);
4798 return -1;
4799 }
4800 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4801 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004802 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004803
4804 return 0;
4805}
4806
4807
4808/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 * wpa_supplicant_set_debug_params - Set global debug params
4810 * @global: wpa_global structure
4811 * @debug_level: debug level
4812 * @debug_timestamp: determines if show timestamp in debug data
4813 * @debug_show_keys: determines if show keys in debug data
4814 * Returns: 0 if succeed or -1 if debug_level has wrong value
4815 */
4816int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4817 int debug_timestamp, int debug_show_keys)
4818{
4819
4820 int old_level, old_timestamp, old_show_keys;
4821
4822 /* check for allowed debuglevels */
4823 if (debug_level != MSG_EXCESSIVE &&
4824 debug_level != MSG_MSGDUMP &&
4825 debug_level != MSG_DEBUG &&
4826 debug_level != MSG_INFO &&
4827 debug_level != MSG_WARNING &&
4828 debug_level != MSG_ERROR)
4829 return -1;
4830
4831 old_level = wpa_debug_level;
4832 old_timestamp = wpa_debug_timestamp;
4833 old_show_keys = wpa_debug_show_keys;
4834
4835 wpa_debug_level = debug_level;
4836 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4837 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4838
4839 if (wpa_debug_level != old_level)
4840 wpas_notify_debug_level_changed(global);
4841 if (wpa_debug_timestamp != old_timestamp)
4842 wpas_notify_debug_timestamp_changed(global);
4843 if (wpa_debug_show_keys != old_show_keys)
4844 wpas_notify_debug_show_keys_changed(global);
4845
4846 return 0;
4847}
4848
4849
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004850#ifdef CONFIG_OWE
4851static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4852 const u8 *entry_ssid, size_t entry_ssid_len)
4853{
4854 const u8 *owe, *pos, *end;
4855 u8 ssid_len;
4856 struct wpa_bss *bss;
4857
4858 /* Check network profile SSID aganst the SSID in the
4859 * OWE Transition Mode element. */
4860
4861 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4862 if (!bss)
4863 return 0;
4864
4865 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4866 if (!owe)
4867 return 0;
4868
4869 pos = owe + 6;
4870 end = owe + 2 + owe[1];
4871
4872 if (end - pos < ETH_ALEN + 1)
4873 return 0;
4874 pos += ETH_ALEN;
4875 ssid_len = *pos++;
4876 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4877 return 0;
4878
4879 return entry_ssid_len == ssid_len &&
4880 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4881}
4882#endif /* CONFIG_OWE */
4883
4884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885/**
4886 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4887 * @wpa_s: Pointer to wpa_supplicant data
4888 * Returns: A pointer to the current network structure or %NULL on failure
4889 */
4890struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4891{
4892 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004893 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004894 int res;
4895 size_t ssid_len;
4896 u8 bssid[ETH_ALEN];
4897 int wired;
4898
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004899 res = wpa_drv_get_ssid(wpa_s, ssid);
4900 if (res < 0) {
4901 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4902 "driver");
4903 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004904 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004905 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004906
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004907 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4909 "driver");
4910 return NULL;
4911 }
4912
4913 wired = wpa_s->conf->ap_scan == 0 &&
4914 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4915
4916 entry = wpa_s->conf->ssid;
4917 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004918 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004920 (!entry->ssid ||
4921 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4922 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923 (!entry->bssid_set ||
4924 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4925 return entry;
4926#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004927 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004928 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4929 (entry->ssid == NULL || entry->ssid_len == 0) &&
4930 (!entry->bssid_set ||
4931 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4932 return entry;
4933#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004934
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004935#ifdef CONFIG_OWE
4936 if (!wpas_network_disabled(wpa_s, entry) &&
4937 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4938 entry->ssid_len) &&
4939 (!entry->bssid_set ||
4940 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4941 return entry;
4942#endif /* CONFIG_OWE */
4943
Dmitry Shmidt04949592012-07-19 12:16:46 -07004944 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004945 entry->ssid_len == 0 &&
4946 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4947 return entry;
4948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004949 entry = entry->next;
4950 }
4951
4952 return NULL;
4953}
4954
4955
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004956static int select_driver(struct wpa_supplicant *wpa_s, int i)
4957{
4958 struct wpa_global *global = wpa_s->global;
4959
4960 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004961 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004962 if (global->drv_priv[i] == NULL) {
4963 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4964 "'%s'", wpa_drivers[i]->name);
4965 return -1;
4966 }
4967 }
4968
4969 wpa_s->driver = wpa_drivers[i];
4970 wpa_s->global_drv_priv = global->drv_priv[i];
4971
4972 return 0;
4973}
4974
4975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004976static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4977 const char *name)
4978{
4979 int i;
4980 size_t len;
4981 const char *pos, *driver = name;
4982
4983 if (wpa_s == NULL)
4984 return -1;
4985
4986 if (wpa_drivers[0] == NULL) {
4987 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4988 "wpa_supplicant");
4989 return -1;
4990 }
4991
4992 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004993 /* Default to first successful driver in the list */
4994 for (i = 0; wpa_drivers[i]; i++) {
4995 if (select_driver(wpa_s, i) == 0)
4996 return 0;
4997 }
4998 /* Drivers have each reported failure, so no wpa_msg() here. */
4999 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005000 }
5001
5002 do {
5003 pos = os_strchr(driver, ',');
5004 if (pos)
5005 len = pos - driver;
5006 else
5007 len = os_strlen(driver);
5008
5009 for (i = 0; wpa_drivers[i]; i++) {
5010 if (os_strlen(wpa_drivers[i]->name) == len &&
5011 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005012 0) {
5013 /* First driver that succeeds wins */
5014 if (select_driver(wpa_s, i) == 0)
5015 return 0;
5016 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005017 }
5018
5019 driver = pos + 1;
5020 } while (pos);
5021
5022 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5023 return -1;
5024}
5025
5026
5027/**
5028 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5029 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5030 * with struct wpa_driver_ops::init()
5031 * @src_addr: Source address of the EAPOL frame
5032 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5033 * @len: Length of the EAPOL data
5034 *
5035 * This function is called for each received EAPOL frame. Most driver
5036 * interfaces rely on more generic OS mechanism for receiving frames through
5037 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5038 * take care of received EAPOL frames and deliver them to the core supplicant
5039 * code by calling this function.
5040 */
5041void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
5042 const u8 *buf, size_t len)
5043{
5044 struct wpa_supplicant *wpa_s = ctx;
5045
5046 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
5047 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5048
Hai Shalomc1a21442022-02-04 13:43:00 -08005049 if (wpa_s->own_disconnect_req) {
5050 wpa_printf(MSG_DEBUG,
5051 "Drop received EAPOL frame as we are disconnecting");
5052 return;
5053 }
5054
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005055#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005056 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5057 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005058 if (wpa_s->ignore_auth_resp) {
5059 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5060 return;
5061 }
5062#endif /* CONFIG_TESTING_OPTIONS */
5063
Jouni Malinena05074c2012-12-21 21:35:35 +02005064 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5065 (wpa_s->last_eapol_matches_bssid &&
5066#ifdef CONFIG_AP
5067 !wpa_s->ap_iface &&
5068#endif /* CONFIG_AP */
5069 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005070 /*
5071 * There is possible race condition between receiving the
5072 * association event and the EAPOL frame since they are coming
5073 * through different paths from the driver. In order to avoid
5074 * issues in trying to process the EAPOL frame before receiving
5075 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005076 * the association event is received. This may also be needed in
5077 * driver-based roaming case, so also use src_addr != BSSID as a
5078 * trigger if we have previously confirmed that the
5079 * Authenticator uses BSSID as the src_addr (which is not the
5080 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081 */
5082 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005083 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5084 wpa_supplicant_state_txt(wpa_s->wpa_state),
5085 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005086 wpabuf_free(wpa_s->pending_eapol_rx);
5087 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5088 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005089 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005090 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5091 ETH_ALEN);
5092 }
5093 return;
5094 }
5095
Jouni Malinena05074c2012-12-21 21:35:35 +02005096 wpa_s->last_eapol_matches_bssid =
5097 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5098
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005099#ifdef CONFIG_AP
5100 if (wpa_s->ap_iface) {
5101 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
5102 return;
5103 }
5104#endif /* CONFIG_AP */
5105
5106 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5107 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5108 "no key management is configured");
5109 return;
5110 }
5111
5112 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005113 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5115 wpa_s->wpa_state != WPA_COMPLETED) &&
5116 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005117 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005118 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005119 int timeout = 10;
5120
5121 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5122 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5123 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5124 /* Use longer timeout for IEEE 802.1X/EAP */
5125 timeout = 70;
5126 }
5127
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005128#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005129 if (wpa_s->current_ssid && wpa_s->current_bss &&
5130 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5131 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5132 /*
5133 * Use shorter timeout if going through WPS AP iteration
5134 * for PIN config method with an AP that does not
5135 * advertise Selected Registrar.
5136 */
5137 struct wpabuf *wps_ie;
5138
5139 wps_ie = wpa_bss_get_vendor_ie_multi(
5140 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5141 if (wps_ie &&
5142 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5143 timeout = 10;
5144 wpabuf_free(wps_ie);
5145 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005146#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005147
5148 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005149 }
5150 wpa_s->eapol_received++;
5151
5152 if (wpa_s->countermeasures) {
5153 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5154 "EAPOL packet");
5155 return;
5156 }
5157
5158#ifdef CONFIG_IBSS_RSN
5159 if (wpa_s->current_ssid &&
5160 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
5161 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
5162 return;
5163 }
5164#endif /* CONFIG_IBSS_RSN */
5165
5166 /* Source address of the incoming EAPOL frame could be compared to the
5167 * current BSSID. However, it is possible that a centralized
5168 * Authenticator could be using another MAC address than the BSSID of
5169 * an AP, so just allow any address to be used for now. The replies are
5170 * still sent to the current BSSID (if available), though. */
5171
5172 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5173 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005174 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5175 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005176 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
5177 return;
5178 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005179 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005180 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
5181 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5182 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005183 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005184 * handshake processing which would normally set portValid. We
5185 * need this to allow the EAPOL state machines to be completed
5186 * without going through EAPOL-Key handshake.
5187 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005188 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189 }
5190}
5191
5192
Hai Shalomb755a2a2020-04-23 21:49:02 -07005193static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5194{
5195 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5196 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5197}
5198
5199
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005200int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005201{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005202 if ((!wpa_s->p2p_mgmt ||
5203 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5204 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005205 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005206 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5207 wpa_drv_get_mac_addr(wpa_s),
5208 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005209 wpas_eapol_needs_l2_packet(wpa_s) ?
5210 wpa_supplicant_rx_eapol : NULL,
5211 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005212 if (wpa_s->l2 == NULL)
5213 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005214
5215 if (l2_packet_set_packet_filter(wpa_s->l2,
5216 L2_PACKET_FILTER_PKTTYPE))
5217 wpa_dbg(wpa_s, MSG_DEBUG,
5218 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005219
5220 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5221 wpa_msg(wpa_s, MSG_ERROR,
5222 "Failed to get own L2 address");
5223 return -1;
5224 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005225 } else {
5226 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5227 if (addr)
5228 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5229 }
5230
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005231 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005232 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005233
Hai Shalomc3565922019-10-28 11:58:20 -07005234#ifdef CONFIG_FST
5235 if (wpa_s->fst)
5236 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5237#endif /* CONFIG_FST */
5238
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005239 return 0;
5240}
5241
5242
Dmitry Shmidt04949592012-07-19 12:16:46 -07005243static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5244 const u8 *buf, size_t len)
5245{
5246 struct wpa_supplicant *wpa_s = ctx;
5247 const struct l2_ethhdr *eth;
5248
5249 if (len < sizeof(*eth))
5250 return;
5251 eth = (const struct l2_ethhdr *) buf;
5252
5253 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5254 !(eth->h_dest[0] & 0x01)) {
5255 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5256 " (bridge - not for this interface - ignore)",
5257 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5258 return;
5259 }
5260
5261 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5262 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5263 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5264 len - sizeof(*eth));
5265}
5266
5267
Hai Shalom899fcc72020-10-19 14:38:18 -07005268int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5269 const char *bridge_ifname)
5270{
5271 if (wpa_s->wpa_state > WPA_SCANNING)
5272 return -EBUSY;
5273
5274 if (bridge_ifname &&
5275 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5276 return -EINVAL;
5277
5278 if (!bridge_ifname)
5279 bridge_ifname = "";
5280
5281 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5282 return 0;
5283
5284 if (wpa_s->l2_br) {
5285 l2_packet_deinit(wpa_s->l2_br);
5286 wpa_s->l2_br = NULL;
5287 }
5288
5289 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5290 sizeof(wpa_s->bridge_ifname));
5291
5292 if (wpa_s->bridge_ifname[0]) {
5293 wpa_dbg(wpa_s, MSG_DEBUG,
5294 "Receiving packets from bridge interface '%s'",
5295 wpa_s->bridge_ifname);
5296 wpa_s->l2_br = l2_packet_init_bridge(
5297 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5298 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5299 if (!wpa_s->l2_br) {
5300 wpa_msg(wpa_s, MSG_ERROR,
5301 "Failed to open l2_packet connection for the bridge interface '%s'",
5302 wpa_s->bridge_ifname);
5303 goto fail;
5304 }
5305 }
5306
5307#ifdef CONFIG_TDLS
5308 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5309 goto fail;
5310#endif /* CONFIG_TDLS */
5311
5312 return 0;
5313fail:
5314 wpa_s->bridge_ifname[0] = 0;
5315 if (wpa_s->l2_br) {
5316 l2_packet_deinit(wpa_s->l2_br);
5317 wpa_s->l2_br = NULL;
5318 }
5319#ifdef CONFIG_TDLS
5320 if (!wpa_s->p2p_mgmt)
5321 wpa_tdls_init(wpa_s->wpa);
5322#endif /* CONFIG_TDLS */
5323 return -EIO;
5324}
5325
5326
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005327/**
5328 * wpa_supplicant_driver_init - Initialize driver interface parameters
5329 * @wpa_s: Pointer to wpa_supplicant data
5330 * Returns: 0 on success, -1 on failure
5331 *
5332 * This function is called to initialize driver interface parameters.
5333 * wpa_drv_init() must have been called before this function to initialize the
5334 * driver interface.
5335 */
5336int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5337{
5338 static int interface_count = 0;
5339
5340 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5341 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005342
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005343 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5344 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005345 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005346 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5347
Hai Shalomb755a2a2020-04-23 21:49:02 -07005348 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005349 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5350 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005351 wpa_s->l2_br = l2_packet_init_bridge(
5352 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5353 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005354 if (wpa_s->l2_br == NULL) {
5355 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5356 "connection for the bridge interface '%s'",
5357 wpa_s->bridge_ifname);
5358 return -1;
5359 }
5360 }
5361
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005362 if (wpa_s->conf->ap_scan == 2 &&
5363 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5364 wpa_printf(MSG_INFO,
5365 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5366 }
5367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005368 wpa_clear_keys(wpa_s, NULL);
5369
5370 /* Make sure that TKIP countermeasures are not left enabled (could
5371 * happen if wpa_supplicant is killed during countermeasures. */
5372 wpa_drv_set_countermeasures(wpa_s, 0);
5373
5374 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5375 wpa_drv_flush_pmkid(wpa_s);
5376
5377 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005378 wpa_s->prev_scan_wildcard = 0;
5379
Dmitry Shmidt04949592012-07-19 12:16:46 -07005380 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005381 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5382 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5383 interface_count = 0;
5384 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005385#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005386 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005387 wpa_supplicant_delayed_sched_scan(wpa_s,
5388 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005389 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005390 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005391 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005392#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005393 interface_count++;
5394 } else
5395 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5396
5397 return 0;
5398}
5399
5400
5401static int wpa_supplicant_daemon(const char *pid_file)
5402{
5403 wpa_printf(MSG_DEBUG, "Daemonize..");
5404 return os_daemonize(pid_file);
5405}
5406
5407
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005408static struct wpa_supplicant *
5409wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005410{
5411 struct wpa_supplicant *wpa_s;
5412
5413 wpa_s = os_zalloc(sizeof(*wpa_s));
5414 if (wpa_s == NULL)
5415 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005416 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005417 wpa_s->scan_interval = 5;
5418 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005419 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005420 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005421 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005422 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005423
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005424 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005425 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005426#ifdef CONFIG_TESTING_OPTIONS
5427 dl_list_init(&wpa_s->drv_signal_override);
5428#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005429 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431 return wpa_s;
5432}
5433
5434
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005435#ifdef CONFIG_HT_OVERRIDES
5436
5437static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5438 struct ieee80211_ht_capabilities *htcaps,
5439 struct ieee80211_ht_capabilities *htcaps_mask,
5440 const char *ht_mcs)
5441{
5442 /* parse ht_mcs into hex array */
5443 int i;
5444 const char *tmp = ht_mcs;
5445 char *end = NULL;
5446
5447 /* If ht_mcs is null, do not set anything */
5448 if (!ht_mcs)
5449 return 0;
5450
5451 /* This is what we are setting in the kernel */
5452 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5453
5454 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5455
5456 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005457 long v;
5458
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005459 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005460 v = strtol(tmp, &end, 16);
5461
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005462 if (errno == 0) {
5463 wpa_msg(wpa_s, MSG_DEBUG,
5464 "htcap value[%i]: %ld end: %p tmp: %p",
5465 i, v, end, tmp);
5466 if (end == tmp)
5467 break;
5468
5469 htcaps->supported_mcs_set[i] = v;
5470 tmp = end;
5471 } else {
5472 wpa_msg(wpa_s, MSG_ERROR,
5473 "Failed to parse ht-mcs: %s, error: %s\n",
5474 ht_mcs, strerror(errno));
5475 return -1;
5476 }
5477 }
5478
5479 /*
5480 * If we were able to parse any values, then set mask for the MCS set.
5481 */
5482 if (i) {
5483 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5484 IEEE80211_HT_MCS_MASK_LEN - 1);
5485 /* skip the 3 reserved bits */
5486 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5487 0x1f;
5488 }
5489
5490 return 0;
5491}
5492
5493
5494static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5495 struct ieee80211_ht_capabilities *htcaps,
5496 struct ieee80211_ht_capabilities *htcaps_mask,
5497 int disabled)
5498{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005499 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005500
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005501 if (disabled == -1)
5502 return 0;
5503
Hai Shalom74f70d42019-02-11 14:42:39 -08005504 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5505
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005506 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5507 htcaps_mask->ht_capabilities_info |= msk;
5508 if (disabled)
5509 htcaps->ht_capabilities_info &= msk;
5510 else
5511 htcaps->ht_capabilities_info |= msk;
5512
5513 return 0;
5514}
5515
5516
5517static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5518 struct ieee80211_ht_capabilities *htcaps,
5519 struct ieee80211_ht_capabilities *htcaps_mask,
5520 int factor)
5521{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005522 if (factor == -1)
5523 return 0;
5524
Hai Shalom74f70d42019-02-11 14:42:39 -08005525 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5526
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005527 if (factor < 0 || factor > 3) {
5528 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5529 "Must be 0-3 or -1", factor);
5530 return -EINVAL;
5531 }
5532
5533 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5534 htcaps->a_mpdu_params &= ~0x3;
5535 htcaps->a_mpdu_params |= factor & 0x3;
5536
5537 return 0;
5538}
5539
5540
5541static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5542 struct ieee80211_ht_capabilities *htcaps,
5543 struct ieee80211_ht_capabilities *htcaps_mask,
5544 int density)
5545{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005546 if (density == -1)
5547 return 0;
5548
Hai Shalom74f70d42019-02-11 14:42:39 -08005549 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5550
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005551 if (density < 0 || density > 7) {
5552 wpa_msg(wpa_s, MSG_ERROR,
5553 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5554 density);
5555 return -EINVAL;
5556 }
5557
5558 htcaps_mask->a_mpdu_params |= 0x1C;
5559 htcaps->a_mpdu_params &= ~(0x1C);
5560 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5561
5562 return 0;
5563}
5564
5565
5566static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5567 struct ieee80211_ht_capabilities *htcaps,
5568 struct ieee80211_ht_capabilities *htcaps_mask,
5569 int disabled)
5570{
Hai Shalom74f70d42019-02-11 14:42:39 -08005571 if (disabled)
5572 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005573
Paul Stewart092955c2017-02-06 09:13:09 -08005574 set_disable_ht40(htcaps, disabled);
5575 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005576
5577 return 0;
5578}
5579
5580
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005581static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5582 struct ieee80211_ht_capabilities *htcaps,
5583 struct ieee80211_ht_capabilities *htcaps_mask,
5584 int disabled)
5585{
5586 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005587 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5588 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005589
Hai Shalom74f70d42019-02-11 14:42:39 -08005590 if (disabled)
5591 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005592
5593 if (disabled)
5594 htcaps->ht_capabilities_info &= ~msk;
5595 else
5596 htcaps->ht_capabilities_info |= msk;
5597
5598 htcaps_mask->ht_capabilities_info |= msk;
5599
5600 return 0;
5601}
5602
5603
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005604static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5605 struct ieee80211_ht_capabilities *htcaps,
5606 struct ieee80211_ht_capabilities *htcaps_mask,
5607 int disabled)
5608{
5609 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005610 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005611
Hai Shalom74f70d42019-02-11 14:42:39 -08005612 if (disabled)
5613 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005614
5615 if (disabled)
5616 htcaps->ht_capabilities_info &= ~msk;
5617 else
5618 htcaps->ht_capabilities_info |= msk;
5619
5620 htcaps_mask->ht_capabilities_info |= msk;
5621
5622 return 0;
5623}
5624
5625
Hai Shalom74f70d42019-02-11 14:42:39 -08005626static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5627 struct ieee80211_ht_capabilities *htcaps,
5628 struct ieee80211_ht_capabilities *htcaps_mask,
5629 int tx_stbc)
5630{
5631 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5632
5633 if (tx_stbc == -1)
5634 return 0;
5635
5636 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5637
5638 if (tx_stbc < 0 || tx_stbc > 1) {
5639 wpa_msg(wpa_s, MSG_ERROR,
5640 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5641 return -EINVAL;
5642 }
5643
5644 htcaps_mask->ht_capabilities_info |= msk;
5645 htcaps->ht_capabilities_info &= ~msk;
5646 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5647
5648 return 0;
5649}
5650
5651
5652static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5653 struct ieee80211_ht_capabilities *htcaps,
5654 struct ieee80211_ht_capabilities *htcaps_mask,
5655 int rx_stbc)
5656{
5657 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5658
5659 if (rx_stbc == -1)
5660 return 0;
5661
5662 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5663
5664 if (rx_stbc < 0 || rx_stbc > 3) {
5665 wpa_msg(wpa_s, MSG_ERROR,
5666 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5667 return -EINVAL;
5668 }
5669
5670 htcaps_mask->ht_capabilities_info |= msk;
5671 htcaps->ht_capabilities_info &= ~msk;
5672 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5673
5674 return 0;
5675}
5676
5677
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005678void wpa_supplicant_apply_ht_overrides(
5679 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5680 struct wpa_driver_associate_params *params)
5681{
5682 struct ieee80211_ht_capabilities *htcaps;
5683 struct ieee80211_ht_capabilities *htcaps_mask;
5684
5685 if (!ssid)
5686 return;
5687
5688 params->disable_ht = ssid->disable_ht;
5689 if (!params->htcaps || !params->htcaps_mask)
5690 return;
5691
5692 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5693 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5694 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5695 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5696 ssid->disable_max_amsdu);
5697 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5698 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5699 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005700 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005701 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005702 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5703 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005704
5705 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005706 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005707 htcaps->ht_capabilities_info |= bit;
5708 htcaps_mask->ht_capabilities_info |= bit;
5709 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005710}
5711
5712#endif /* CONFIG_HT_OVERRIDES */
5713
5714
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005715#ifdef CONFIG_VHT_OVERRIDES
5716void wpa_supplicant_apply_vht_overrides(
5717 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5718 struct wpa_driver_associate_params *params)
5719{
5720 struct ieee80211_vht_capabilities *vhtcaps;
5721 struct ieee80211_vht_capabilities *vhtcaps_mask;
5722
5723 if (!ssid)
5724 return;
5725
5726 params->disable_vht = ssid->disable_vht;
5727
5728 vhtcaps = (void *) params->vhtcaps;
5729 vhtcaps_mask = (void *) params->vhtcaps_mask;
5730
5731 if (!vhtcaps || !vhtcaps_mask)
5732 return;
5733
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005734 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5735 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005736
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005737#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005738 if (ssid->disable_sgi) {
5739 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5740 VHT_CAP_SHORT_GI_160);
5741 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5742 VHT_CAP_SHORT_GI_160);
5743 wpa_msg(wpa_s, MSG_DEBUG,
5744 "disable-sgi override specified, vht-caps: 0x%x",
5745 vhtcaps->vht_capabilities_info);
5746 }
5747
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005748 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005749 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5750 int max_ampdu;
5751
5752 max_ampdu = (ssid->vht_capa &
5753 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5754 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005755
5756 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5757 wpa_set_ampdu_factor(wpa_s,
5758 (void *) params->htcaps,
5759 (void *) params->htcaps_mask,
5760 max_ampdu);
5761 }
5762#endif /* CONFIG_HT_OVERRIDES */
5763
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005764#define OVERRIDE_MCS(i) \
5765 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5766 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005767 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005768 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005769 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5770 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005771 } \
5772 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5773 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005774 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005775 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005776 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5777 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005778 }
5779
5780 OVERRIDE_MCS(1);
5781 OVERRIDE_MCS(2);
5782 OVERRIDE_MCS(3);
5783 OVERRIDE_MCS(4);
5784 OVERRIDE_MCS(5);
5785 OVERRIDE_MCS(6);
5786 OVERRIDE_MCS(7);
5787 OVERRIDE_MCS(8);
5788}
5789#endif /* CONFIG_VHT_OVERRIDES */
5790
5791
Hai Shalomfdcde762020-04-02 11:19:20 -07005792#ifdef CONFIG_HE_OVERRIDES
5793void wpa_supplicant_apply_he_overrides(
5794 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5795 struct wpa_driver_associate_params *params)
5796{
5797 if (!ssid)
5798 return;
5799
5800 params->disable_he = ssid->disable_he;
5801}
5802#endif /* CONFIG_HE_OVERRIDES */
5803
5804
Dmitry Shmidt04949592012-07-19 12:16:46 -07005805static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5806{
5807#ifdef PCSC_FUNCS
5808 size_t len;
5809
5810 if (!wpa_s->conf->pcsc_reader)
5811 return 0;
5812
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005813 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005814 if (!wpa_s->scard)
5815 return 1;
5816
5817 if (wpa_s->conf->pcsc_pin &&
5818 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5819 scard_deinit(wpa_s->scard);
5820 wpa_s->scard = NULL;
5821 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5822 return -1;
5823 }
5824
5825 len = sizeof(wpa_s->imsi) - 1;
5826 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5827 scard_deinit(wpa_s->scard);
5828 wpa_s->scard = NULL;
5829 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5830 return -1;
5831 }
5832 wpa_s->imsi[len] = '\0';
5833
5834 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5835
5836 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5837 wpa_s->imsi, wpa_s->mnc_len);
5838
5839 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5840 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5841#endif /* PCSC_FUNCS */
5842
5843 return 0;
5844}
5845
5846
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005847int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5848{
5849 char *val, *pos;
5850
5851 ext_password_deinit(wpa_s->ext_pw);
5852 wpa_s->ext_pw = NULL;
5853 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5854
5855 if (!wpa_s->conf->ext_password_backend)
5856 return 0;
5857
5858 val = os_strdup(wpa_s->conf->ext_password_backend);
5859 if (val == NULL)
5860 return -1;
5861 pos = os_strchr(val, ':');
5862 if (pos)
5863 *pos++ = '\0';
5864
5865 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5866
5867 wpa_s->ext_pw = ext_password_init(val, pos);
5868 os_free(val);
5869 if (wpa_s->ext_pw == NULL) {
5870 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5871 return -1;
5872 }
5873 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5874
5875 return 0;
5876}
5877
5878
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005879#ifdef CONFIG_FST
5880
5881static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5882{
5883 struct wpa_supplicant *wpa_s = ctx;
5884
5885 return (is_zero_ether_addr(wpa_s->bssid) ||
5886 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5887}
5888
5889
5890static void wpas_fst_get_channel_info_cb(void *ctx,
5891 enum hostapd_hw_mode *hw_mode,
5892 u8 *channel)
5893{
5894 struct wpa_supplicant *wpa_s = ctx;
5895
5896 if (wpa_s->current_bss) {
5897 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5898 channel);
5899 } else if (wpa_s->hw.num_modes) {
5900 *hw_mode = wpa_s->hw.modes[0].mode;
5901 } else {
5902 WPA_ASSERT(0);
5903 *hw_mode = 0;
5904 }
5905}
5906
5907
5908static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5909{
5910 struct wpa_supplicant *wpa_s = ctx;
5911
5912 *modes = wpa_s->hw.modes;
5913 return wpa_s->hw.num_modes;
5914}
5915
5916
5917static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5918{
5919 struct wpa_supplicant *wpa_s = ctx;
5920
5921 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5922 wpa_s->fst_ies = fst_ies;
5923}
5924
5925
5926static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5927{
5928 struct wpa_supplicant *wpa_s = ctx;
5929
Paul Stewart092955c2017-02-06 09:13:09 -08005930 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5931 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5932 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5933 return -1;
5934 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005935 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005936 wpa_s->own_addr, wpa_s->bssid,
5937 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005938 0);
5939}
5940
5941
5942static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5943{
5944 struct wpa_supplicant *wpa_s = ctx;
5945
5946 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5947 return wpa_s->received_mb_ies;
5948}
5949
5950
5951static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5952 const u8 *buf, size_t size)
5953{
5954 struct wpa_supplicant *wpa_s = ctx;
5955 struct mb_ies_info info;
5956
5957 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5958
5959 if (!mb_ies_info_by_ies(&info, buf, size)) {
5960 wpabuf_free(wpa_s->received_mb_ies);
5961 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5962 }
5963}
5964
5965
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005966static const u8 * wpas_fst_get_peer_first(void *ctx,
5967 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005968 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005969{
5970 struct wpa_supplicant *wpa_s = ctx;
5971
5972 *get_ctx = NULL;
5973 if (!is_zero_ether_addr(wpa_s->bssid))
5974 return (wpa_s->received_mb_ies || !mb_only) ?
5975 wpa_s->bssid : NULL;
5976 return NULL;
5977}
5978
5979
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005980static const u8 * wpas_fst_get_peer_next(void *ctx,
5981 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005982 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005983{
5984 return NULL;
5985}
5986
5987void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5988 struct fst_wpa_obj *iface_obj)
5989{
5990 iface_obj->ctx = wpa_s;
5991 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5992 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5993 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5994 iface_obj->set_ies = wpas_fst_set_ies_cb;
5995 iface_obj->send_action = wpas_fst_send_action_cb;
5996 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5997 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5998 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5999 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6000}
6001#endif /* CONFIG_FST */
6002
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006003static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006004 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006005{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006006 struct wowlan_triggers *triggers;
6007 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006008
6009 if (!wpa_s->conf->wowlan_triggers)
6010 return 0;
6011
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006012 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6013 if (triggers) {
6014 ret = wpa_drv_wowlan(wpa_s, triggers);
6015 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006016 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006017 return ret;
6018}
6019
6020
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006021enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006022{
6023 if (freq < 3000)
6024 return BAND_2_4_GHZ;
6025 if (freq > 50000)
6026 return BAND_60_GHZ;
6027 return BAND_5_GHZ;
6028}
6029
6030
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006031unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006032{
6033 int i;
6034 unsigned int band = 0;
6035
6036 if (freqs) {
6037 /* freqs are specified for the radio work */
6038 for (i = 0; freqs[i]; i++)
6039 band |= wpas_freq_to_band(freqs[i]);
6040 } else {
6041 /*
6042 * freqs are not specified, implies all
6043 * the supported freqs by HW
6044 */
6045 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6046 if (wpa_s->hw.modes[i].num_channels != 0) {
6047 if (wpa_s->hw.modes[i].mode ==
6048 HOSTAPD_MODE_IEEE80211B ||
6049 wpa_s->hw.modes[i].mode ==
6050 HOSTAPD_MODE_IEEE80211G)
6051 band |= BAND_2_4_GHZ;
6052 else if (wpa_s->hw.modes[i].mode ==
6053 HOSTAPD_MODE_IEEE80211A)
6054 band |= BAND_5_GHZ;
6055 else if (wpa_s->hw.modes[i].mode ==
6056 HOSTAPD_MODE_IEEE80211AD)
6057 band |= BAND_60_GHZ;
6058 else if (wpa_s->hw.modes[i].mode ==
6059 HOSTAPD_MODE_IEEE80211ANY)
6060 band = BAND_2_4_GHZ | BAND_5_GHZ |
6061 BAND_60_GHZ;
6062 }
6063 }
6064 }
6065
6066 return band;
6067}
6068
6069
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006070static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6071 const char *rn)
6072{
6073 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6074 struct wpa_radio *radio;
6075
6076 while (rn && iface) {
6077 radio = iface->radio;
6078 if (radio && os_strcmp(rn, radio->name) == 0) {
6079 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6080 wpa_s->ifname, rn);
6081 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6082 return radio;
6083 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006084
6085 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006086 }
6087
6088 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6089 wpa_s->ifname, rn ? rn : "N/A");
6090 radio = os_zalloc(sizeof(*radio));
6091 if (radio == NULL)
6092 return NULL;
6093
6094 if (rn)
6095 os_strlcpy(radio->name, rn, sizeof(radio->name));
6096 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006097 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006098 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6099
6100 return radio;
6101}
6102
6103
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006104static void radio_work_free(struct wpa_radio_work *work)
6105{
6106 if (work->wpa_s->scan_work == work) {
6107 /* This should not really happen. */
6108 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6109 work->type, work, work->started);
6110 work->wpa_s->scan_work = NULL;
6111 }
6112
6113#ifdef CONFIG_P2P
6114 if (work->wpa_s->p2p_scan_work == work) {
6115 /* This should not really happen. */
6116 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6117 work->type, work, work->started);
6118 work->wpa_s->p2p_scan_work = NULL;
6119 }
6120#endif /* CONFIG_P2P */
6121
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006122 if (work->started) {
6123 work->wpa_s->radio->num_active_works--;
6124 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006125 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006126 work->type, work,
6127 work->wpa_s->radio->num_active_works);
6128 }
6129
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006130 dl_list_del(&work->list);
6131 os_free(work);
6132}
6133
6134
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006135static int radio_work_is_connect(struct wpa_radio_work *work)
6136{
6137 return os_strcmp(work->type, "sme-connect") == 0 ||
6138 os_strcmp(work->type, "connect") == 0;
6139}
6140
6141
6142static int radio_work_is_scan(struct wpa_radio_work *work)
6143{
6144 return os_strcmp(work->type, "scan") == 0 ||
6145 os_strcmp(work->type, "p2p-scan") == 0;
6146}
6147
6148
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006149static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6150{
6151 struct wpa_radio_work *active_work = NULL;
6152 struct wpa_radio_work *tmp;
6153
6154 /* Get the active work to know the type and band. */
6155 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6156 if (tmp->started) {
6157 active_work = tmp;
6158 break;
6159 }
6160 }
6161
6162 if (!active_work) {
6163 /* No active work, start one */
6164 radio->num_active_works = 0;
6165 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6166 list) {
6167 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006168 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006169 (((struct wpa_driver_scan_params *)
6170 tmp->ctx)->only_new_results ||
6171 tmp->wpa_s->clear_driver_scan_cache))
6172 continue;
6173 return tmp;
6174 }
6175 return NULL;
6176 }
6177
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006178 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006179 /*
6180 * If the active work is either connect or sme-connect,
6181 * do not parallelize them with other radio works.
6182 */
6183 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6184 "Do not parallelize radio work with %s",
6185 active_work->type);
6186 return NULL;
6187 }
6188
6189 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6190 if (tmp->started)
6191 continue;
6192
6193 /*
6194 * If connect or sme-connect are enqueued, parallelize only
6195 * those operations ahead of them in the queue.
6196 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006197 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006198 break;
6199
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006200 /* Serialize parallel scan and p2p_scan operations on the same
6201 * interface since the driver_nl80211 mechanism for tracking
6202 * scan cookies does not yet have support for this. */
6203 if (active_work->wpa_s == tmp->wpa_s &&
6204 radio_work_is_scan(active_work) &&
6205 radio_work_is_scan(tmp)) {
6206 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6207 "Do not start work '%s' when another work '%s' is already scheduled",
6208 tmp->type, active_work->type);
6209 continue;
6210 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006211 /*
6212 * Check that the radio works are distinct and
6213 * on different bands.
6214 */
6215 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6216 (active_work->bands != tmp->bands)) {
6217 /*
6218 * If a scan has to be scheduled through nl80211 scan
6219 * interface and if an external scan is already running,
6220 * do not schedule the scan since it is likely to get
6221 * rejected by kernel.
6222 */
6223 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006224 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006225 (((struct wpa_driver_scan_params *)
6226 tmp->ctx)->only_new_results ||
6227 tmp->wpa_s->clear_driver_scan_cache))
6228 continue;
6229
6230 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6231 "active_work:%s new_work:%s",
6232 active_work->type, tmp->type);
6233 return tmp;
6234 }
6235 }
6236
6237 /* Did not find a radio work to schedule in parallel. */
6238 return NULL;
6239}
6240
6241
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006242static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6243{
6244 struct wpa_radio *radio = eloop_ctx;
6245 struct wpa_radio_work *work;
6246 struct os_reltime now, diff;
6247 struct wpa_supplicant *wpa_s;
6248
6249 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006250 if (work == NULL) {
6251 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006252 return;
6253 }
6254
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006255 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6256 radio_list);
6257
6258 if (!(wpa_s &&
6259 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6260 if (work->started)
6261 return; /* already started and still in progress */
6262
Hai Shalom60840252021-02-19 19:02:11 -08006263 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006264 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6265 return;
6266 }
6267 } else {
6268 work = NULL;
6269 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6270 /* get the work to schedule next */
6271 work = radio_work_get_next_work(radio);
6272 }
6273 if (!work)
6274 return;
6275 }
6276
6277 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006278 os_get_reltime(&now);
6279 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006280 wpa_dbg(wpa_s, MSG_DEBUG,
6281 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006282 work->type, work, diff.sec, diff.usec);
6283 work->started = 1;
6284 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006285 radio->num_active_works++;
6286
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006287 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006288
6289 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6290 radio->num_active_works < MAX_ACTIVE_WORKS)
6291 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006292}
6293
6294
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006295/*
6296 * This function removes both started and pending radio works running on
6297 * the provided interface's radio.
6298 * Prior to the removal of the radio work, its callback (cb) is called with
6299 * deinit set to be 1. Each work's callback is responsible for clearing its
6300 * internal data and restoring to a correct state.
6301 * @wpa_s: wpa_supplicant data
6302 * @type: type of works to be removed
6303 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6304 * this interface's works.
6305 */
6306void radio_remove_works(struct wpa_supplicant *wpa_s,
6307 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006308{
6309 struct wpa_radio_work *work, *tmp;
6310 struct wpa_radio *radio = wpa_s->radio;
6311
6312 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6313 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006314 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006315 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006316
6317 /* skip other ifaces' works */
6318 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006319 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006320
6321 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6322 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006323 work->cb(work, 1);
6324 radio_work_free(work);
6325 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006326
6327 /* in case we removed the started work */
6328 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006329}
6330
6331
Roshan Pius3a1667e2018-07-03 15:17:14 -07006332void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6333{
6334 struct wpa_radio_work *work;
6335 struct wpa_radio *radio = wpa_s->radio;
6336
6337 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6338 if (work->ctx != ctx)
6339 continue;
6340 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6341 work->type, work, work->started ? " (started)" : "");
6342 radio_work_free(work);
6343 break;
6344 }
6345}
6346
6347
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006348static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6349{
6350 struct wpa_radio *radio = wpa_s->radio;
6351
6352 if (!radio)
6353 return;
6354
6355 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6356 wpa_s->ifname, radio->name);
6357 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006358 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006359 /* If the interface that triggered the external scan was removed, the
6360 * external scan is no longer running. */
6361 if (wpa_s == radio->external_scan_req_interface)
6362 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006363 wpa_s->radio = NULL;
6364 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006365 return; /* Interfaces remain for this radio */
6366
6367 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006368 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006369 os_free(radio);
6370}
6371
6372
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006373void radio_work_check_next(struct wpa_supplicant *wpa_s)
6374{
6375 struct wpa_radio *radio = wpa_s->radio;
6376
6377 if (dl_list_empty(&radio->work))
6378 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006379 if (wpa_s->ext_work_in_progress) {
6380 wpa_printf(MSG_DEBUG,
6381 "External radio work in progress - delay start of pending item");
6382 return;
6383 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006384 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6385 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6386}
6387
6388
6389/**
6390 * radio_add_work - Add a radio work item
6391 * @wpa_s: Pointer to wpa_supplicant data
6392 * @freq: Frequency of the offchannel operation in MHz or 0
6393 * @type: Unique identifier for each type of work
6394 * @next: Force as the next work to be executed
6395 * @cb: Callback function for indicating when radio is available
6396 * @ctx: Context pointer for the work (work->ctx in cb())
6397 * Returns: 0 on success, -1 on failure
6398 *
6399 * This function is used to request time for an operation that requires
6400 * exclusive radio control. Once the radio is available, the registered callback
6401 * function will be called. radio_work_done() must be called once the exclusive
6402 * radio operation has been completed, so that the radio is freed for other
6403 * operations. The special case of deinit=1 is used to free the context data
6404 * during interface removal. That does not allow the callback function to start
6405 * the radio operation, i.e., it must free any resources allocated for the radio
6406 * work and return.
6407 *
6408 * The @freq parameter can be used to indicate a single channel on which the
6409 * offchannel operation will occur. This may allow multiple radio work
6410 * operations to be performed in parallel if they apply for the same channel.
6411 * Setting this to 0 indicates that the work item may use multiple channels or
6412 * requires exclusive control of the radio.
6413 */
6414int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6415 const char *type, int next,
6416 void (*cb)(struct wpa_radio_work *work, int deinit),
6417 void *ctx)
6418{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006419 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006420 struct wpa_radio_work *work;
6421 int was_empty;
6422
6423 work = os_zalloc(sizeof(*work));
6424 if (work == NULL)
6425 return -1;
6426 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6427 os_get_reltime(&work->time);
6428 work->freq = freq;
6429 work->type = type;
6430 work->wpa_s = wpa_s;
6431 work->cb = cb;
6432 work->ctx = ctx;
6433
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006434 if (freq)
6435 work->bands = wpas_freq_to_band(freq);
6436 else if (os_strcmp(type, "scan") == 0 ||
6437 os_strcmp(type, "p2p-scan") == 0)
6438 work->bands = wpas_get_bands(wpa_s,
6439 ((struct wpa_driver_scan_params *)
6440 ctx)->freqs);
6441 else
6442 work->bands = wpas_get_bands(wpa_s, NULL);
6443
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006444 was_empty = dl_list_empty(&wpa_s->radio->work);
6445 if (next)
6446 dl_list_add(&wpa_s->radio->work, &work->list);
6447 else
6448 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6449 if (was_empty) {
6450 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6451 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006452 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6453 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6454 wpa_dbg(wpa_s, MSG_DEBUG,
6455 "Try to schedule a radio work (num_active_works=%u)",
6456 radio->num_active_works);
6457 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006458 }
6459
6460 return 0;
6461}
6462
6463
6464/**
6465 * radio_work_done - Indicate that a radio work item has been completed
6466 * @work: Completed work
6467 *
6468 * This function is called once the callback function registered with
6469 * radio_add_work() has completed its work.
6470 */
6471void radio_work_done(struct wpa_radio_work *work)
6472{
6473 struct wpa_supplicant *wpa_s = work->wpa_s;
6474 struct os_reltime now, diff;
6475 unsigned int started = work->started;
6476
6477 os_get_reltime(&now);
6478 os_reltime_sub(&now, &work->time, &diff);
6479 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6480 work->type, work, started ? "done" : "canceled",
6481 diff.sec, diff.usec);
6482 radio_work_free(work);
6483 if (started)
6484 radio_work_check_next(wpa_s);
6485}
6486
6487
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006488struct wpa_radio_work *
6489radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006490{
6491 struct wpa_radio_work *work;
6492 struct wpa_radio *radio = wpa_s->radio;
6493
6494 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6495 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006496 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006497 }
6498
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006499 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006500}
6501
6502
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006503static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006504 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006505{
6506 const char *ifname, *driver, *rn;
6507
6508 driver = iface->driver;
6509next_driver:
6510 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6511 return -1;
6512
6513 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6514 if (wpa_s->drv_priv == NULL) {
6515 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006516 int level = MSG_ERROR;
6517
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006518 pos = driver ? os_strchr(driver, ',') : NULL;
6519 if (pos) {
6520 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6521 "driver interface - try next driver wrapper");
6522 driver = pos + 1;
6523 goto next_driver;
6524 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006525
6526#ifdef CONFIG_MATCH_IFACE
6527 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6528 level = MSG_DEBUG;
6529#endif /* CONFIG_MATCH_IFACE */
6530 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006531 return -1;
6532 }
6533 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6534 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6535 "driver_param '%s'", wpa_s->conf->driver_param);
6536 return -1;
6537 }
6538
6539 ifname = wpa_drv_get_ifname(wpa_s);
6540 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6541 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6542 "interface name with '%s'", ifname);
6543 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6544 }
6545
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006546 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006547 if (rn && rn[0] == '\0')
6548 rn = NULL;
6549
6550 wpa_s->radio = radio_add_interface(wpa_s, rn);
6551 if (wpa_s->radio == NULL)
6552 return -1;
6553
6554 return 0;
6555}
6556
6557
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006558#ifdef CONFIG_GAS_SERVER
6559
6560static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6561 unsigned int freq, const u8 *dst,
6562 const u8 *src, const u8 *bssid,
6563 const u8 *data, size_t data_len,
6564 enum offchannel_send_action_result result)
6565{
6566 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6567 " result=%s",
6568 freq, MAC2STR(dst),
6569 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6570 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6571 "FAILED"));
6572 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6573 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6574}
6575
6576
6577static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6578 struct wpabuf *buf, unsigned int wait_time)
6579{
6580 struct wpa_supplicant *wpa_s = ctx;
6581 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6582
6583 if (wait_time > wpa_s->max_remain_on_chan)
6584 wait_time = wpa_s->max_remain_on_chan;
6585
6586 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6587 wpabuf_head(buf), wpabuf_len(buf),
6588 wait_time, wpas_gas_server_tx_status, 0);
6589}
6590
6591#endif /* CONFIG_GAS_SERVER */
6592
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006593static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006594 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006595{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006596 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006597 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006598 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006599
6600 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6601 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6602 iface->confname ? iface->confname : "N/A",
6603 iface->driver ? iface->driver : "default",
6604 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6605 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6606
6607 if (iface->confname) {
6608#ifdef CONFIG_BACKEND_FILE
6609 wpa_s->confname = os_rel2abs_path(iface->confname);
6610 if (wpa_s->confname == NULL) {
6611 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6612 "for configuration file '%s'.",
6613 iface->confname);
6614 return -1;
6615 }
6616 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6617 iface->confname, wpa_s->confname);
6618#else /* CONFIG_BACKEND_FILE */
6619 wpa_s->confname = os_strdup(iface->confname);
6620#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006621 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006622 if (wpa_s->conf == NULL) {
6623 wpa_printf(MSG_ERROR, "Failed to read or parse "
6624 "configuration '%s'.", wpa_s->confname);
6625 return -1;
6626 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006627 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006628 if (wpa_s->confanother &&
6629 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6630 wpa_printf(MSG_ERROR,
6631 "Failed to read or parse configuration '%s'.",
6632 wpa_s->confanother);
6633 return -1;
6634 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006635
6636 /*
6637 * Override ctrl_interface and driver_param if set on command
6638 * line.
6639 */
6640 if (iface->ctrl_interface) {
6641 os_free(wpa_s->conf->ctrl_interface);
6642 wpa_s->conf->ctrl_interface =
6643 os_strdup(iface->ctrl_interface);
6644 }
6645
6646 if (iface->driver_param) {
6647 os_free(wpa_s->conf->driver_param);
6648 wpa_s->conf->driver_param =
6649 os_strdup(iface->driver_param);
6650 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006651
6652 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6653 os_free(wpa_s->conf->ctrl_interface);
6654 wpa_s->conf->ctrl_interface = NULL;
6655 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006656 } else
6657 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6658 iface->driver_param);
6659
6660 if (wpa_s->conf == NULL) {
6661 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6662 return -1;
6663 }
6664
6665 if (iface->ifname == NULL) {
6666 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6667 return -1;
6668 }
6669 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6670 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6671 iface->ifname);
6672 return -1;
6673 }
6674 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006675#ifdef CONFIG_MATCH_IFACE
6676 wpa_s->matched = iface->matched;
6677#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006678
6679 if (iface->bridge_ifname) {
6680 if (os_strlen(iface->bridge_ifname) >=
6681 sizeof(wpa_s->bridge_ifname)) {
6682 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6683 "name '%s'.", iface->bridge_ifname);
6684 return -1;
6685 }
6686 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6687 sizeof(wpa_s->bridge_ifname));
6688 }
6689
6690 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006691 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6692 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006693
6694 /* Initialize driver interface and register driver event handler before
6695 * L2 receive handler so that association events are processed before
6696 * EAPOL-Key packets if both become available for the same select()
6697 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006698 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006699 return -1;
6700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006701 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6702 return -1;
6703
6704 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6705 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6706 NULL);
6707 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6708
6709 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6710 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6711 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6712 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6713 "dot11RSNAConfigPMKLifetime");
6714 return -1;
6715 }
6716
6717 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6718 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6719 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6720 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6721 "dot11RSNAConfigPMKReauthThreshold");
6722 return -1;
6723 }
6724
6725 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6726 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6727 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6728 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6729 "dot11RSNAConfigSATimeout");
6730 return -1;
6731 }
6732
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006733 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6734 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006735 &wpa_s->hw.flags,
6736 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006737 if (wpa_s->hw.modes) {
6738 u16 i;
6739
6740 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6741 if (wpa_s->hw.modes[i].vht_capab) {
6742 wpa_s->hw_capab = CAPAB_VHT;
6743 break;
6744 }
6745
6746 if (wpa_s->hw.modes[i].ht_capab &
6747 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6748 wpa_s->hw_capab = CAPAB_HT40;
6749 else if (wpa_s->hw.modes[i].ht_capab &&
6750 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6751 wpa_s->hw_capab = CAPAB_HT;
6752 }
6753 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006754
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006755 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6756 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006757 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006758 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006759 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006760 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006761 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravi59fa4b42022-05-02 22:54:18 -07006762 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006763 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006764 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006765 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006766 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6767 wpa_s->max_sched_scan_plan_interval =
6768 capa.max_sched_scan_plan_interval;
6769 wpa_s->max_sched_scan_plan_iterations =
6770 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006771 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6772 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006773 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6774 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006775 wpa_s->extended_capa = capa.extended_capa;
6776 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6777 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006778 wpa_s->num_multichan_concurrent =
6779 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006780 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6781
6782 if (capa.mac_addr_rand_scan_supported)
6783 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6784 if (wpa_s->sched_scan_supported &&
6785 capa.mac_addr_rand_sched_scan_supported)
6786 wpa_s->mac_addr_rand_supported |=
6787 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006788
6789 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6790 if (wpa_s->extended_capa &&
6791 wpa_s->extended_capa_len >= 3 &&
6792 wpa_s->extended_capa[2] & 0x40)
6793 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006794 }
6795 if (wpa_s->max_remain_on_chan == 0)
6796 wpa_s->max_remain_on_chan = 1000;
6797
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006798 /*
6799 * Only take p2p_mgmt parameters when P2P Device is supported.
6800 * Doing it here as it determines whether l2_packet_init() will be done
6801 * during wpa_supplicant_driver_init().
6802 */
6803 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6804 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006805
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006806 if (wpa_s->num_multichan_concurrent == 0)
6807 wpa_s->num_multichan_concurrent = 1;
6808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006809 if (wpa_supplicant_driver_init(wpa_s) < 0)
6810 return -1;
6811
6812#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006813 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006814 return -1;
6815#endif /* CONFIG_TDLS */
6816
6817 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6818 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6819 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6820 return -1;
6821 }
6822
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006823#ifdef CONFIG_FST
6824 if (wpa_s->conf->fst_group_id) {
6825 struct fst_iface_cfg cfg;
6826 struct fst_wpa_obj iface_obj;
6827
6828 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6829 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6830 sizeof(cfg.group_id));
6831 cfg.priority = wpa_s->conf->fst_priority;
6832 cfg.llt = wpa_s->conf->fst_llt;
6833
6834 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6835 &iface_obj, &cfg);
6836 if (!wpa_s->fst) {
6837 wpa_msg(wpa_s, MSG_ERROR,
6838 "FST: Cannot attach iface %s to group %s",
6839 wpa_s->ifname, cfg.group_id);
6840 return -1;
6841 }
6842 }
6843#endif /* CONFIG_FST */
6844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006845 if (wpas_wps_init(wpa_s))
6846 return -1;
6847
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006848#ifdef CONFIG_GAS_SERVER
6849 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6850 if (!wpa_s->gas_server) {
6851 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6852 return -1;
6853 }
6854#endif /* CONFIG_GAS_SERVER */
6855
6856#ifdef CONFIG_DPP
6857 if (wpas_dpp_init(wpa_s) < 0)
6858 return -1;
6859#endif /* CONFIG_DPP */
6860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006861 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6862 return -1;
6863 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6864
6865 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6866 if (wpa_s->ctrl_iface == NULL) {
6867 wpa_printf(MSG_ERROR,
6868 "Failed to initialize control interface '%s'.\n"
6869 "You may have another wpa_supplicant process "
6870 "already running or the file was\n"
6871 "left by an unclean termination of wpa_supplicant "
6872 "in which case you will need\n"
6873 "to manually remove this file before starting "
6874 "wpa_supplicant again.\n",
6875 wpa_s->conf->ctrl_interface);
6876 return -1;
6877 }
6878
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006879 wpa_s->gas = gas_query_init(wpa_s);
6880 if (wpa_s->gas == NULL) {
6881 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6882 return -1;
6883 }
6884
Roshan Pius3a1667e2018-07-03 15:17:14 -07006885 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6886 wpa_s->p2p_mgmt) &&
6887 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006888 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6889 return -1;
6890 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006891
6892 if (wpa_bss_init(wpa_s) < 0)
6893 return -1;
6894
Paul Stewart092955c2017-02-06 09:13:09 -08006895#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6896#ifdef CONFIG_MESH
6897 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6898#endif /* CONFIG_MESH */
6899#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6900
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006901 /*
6902 * Set Wake-on-WLAN triggers, if configured.
6903 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6904 * have effect anyway when the interface is down).
6905 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006906 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006907 return -1;
6908
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006909#ifdef CONFIG_EAP_PROXY
6910{
6911 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006912 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6913 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006914 if (wpa_s->mnc_len > 0) {
6915 wpa_s->imsi[len] = '\0';
6916 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6917 wpa_s->imsi, wpa_s->mnc_len);
6918 } else {
6919 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6920 }
6921}
6922#endif /* CONFIG_EAP_PROXY */
6923
Dmitry Shmidt04949592012-07-19 12:16:46 -07006924 if (pcsc_reader_init(wpa_s) < 0)
6925 return -1;
6926
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006927 if (wpas_init_ext_pw(wpa_s) < 0)
6928 return -1;
6929
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006930 wpas_rrm_reset(wpa_s);
6931
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006932 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6933
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006934#ifdef CONFIG_HS20
6935 hs20_init(wpa_s);
6936#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006937#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006938 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006939 if ((wpa_s->conf->oce & OCE_STA) &&
6940 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6941 wpa_s->enable_oce = OCE_STA;
6942 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6943 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6944 /* TODO: Need to add STA-CFON support */
6945 wpa_printf(MSG_ERROR,
6946 "OCE STA-CFON feature is not yet supported");
6947 }
6948 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006949 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6950#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006951
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006952 wpa_supplicant_set_default_scan_ies(wpa_s);
6953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954 return 0;
6955}
6956
6957
6958static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006959 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006960{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006961 struct wpa_global *global = wpa_s->global;
6962 struct wpa_supplicant *iface, *prev;
6963
Jimmy Chen0e73c002021-08-18 13:21:30 +08006964 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006965 wpas_p2p_group_remove(wpa_s, "*");
6966
6967 iface = global->ifaces;
6968 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006969 if (iface->p2pdev == wpa_s)
6970 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006971 if (iface == wpa_s || iface->parent != wpa_s) {
6972 iface = iface->next;
6973 continue;
6974 }
6975 wpa_printf(MSG_DEBUG,
6976 "Remove remaining child interface %s from parent %s",
6977 iface->ifname, wpa_s->ifname);
6978 prev = iface;
6979 iface = iface->next;
6980 wpa_supplicant_remove_iface(global, prev, terminate);
6981 }
6982
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006983 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006984 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006985 /*
6986 * Don't deauthenticate if WoWLAN is enable and not explicitly
6987 * been configured to disconnect.
6988 */
6989 if (!wpa_drv_get_wowlan(wpa_s) ||
6990 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006991 wpa_supplicant_deauthenticate(
6992 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006993
Hai Shalomfdcde762020-04-02 11:19:20 -07006994 wpa_drv_set_countermeasures(wpa_s, 0);
6995 wpa_clear_keys(wpa_s, NULL);
6996 } else {
6997 wpa_msg(wpa_s, MSG_INFO,
6998 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007000 }
7001
7002 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007003 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007004
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007005 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007006 radio_remove_interface(wpa_s);
7007
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007008#ifdef CONFIG_FST
7009 if (wpa_s->fst) {
7010 fst_detach(wpa_s->fst);
7011 wpa_s->fst = NULL;
7012 }
7013 if (wpa_s->received_mb_ies) {
7014 wpabuf_free(wpa_s->received_mb_ies);
7015 wpa_s->received_mb_ies = NULL;
7016 }
7017#endif /* CONFIG_FST */
7018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007019 if (wpa_s->drv_priv)
7020 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007021
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007022 if (notify)
7023 wpas_notify_iface_removed(wpa_s);
7024
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007025 if (terminate)
7026 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007027
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007028 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7029 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007030
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007031#ifdef CONFIG_MESH
7032 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007033 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007034 wpa_s->ifmsh = NULL;
7035 }
7036#endif /* CONFIG_MESH */
7037
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007038 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007039 wpa_config_free(wpa_s->conf);
7040 wpa_s->conf = NULL;
7041 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007042
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007043 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007044 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007045
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007046 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047}
7048
7049
Dmitry Shmidte4663042016-04-04 10:07:49 -07007050#ifdef CONFIG_MATCH_IFACE
7051
7052/**
7053 * wpa_supplicant_match_iface - Match an interface description to a name
7054 * @global: Pointer to global data from wpa_supplicant_init()
7055 * @ifname: Name of the interface to match
7056 * Returns: Pointer to the created interface description or %NULL on failure
7057 */
7058struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7059 const char *ifname)
7060{
7061 int i;
7062 struct wpa_interface *iface, *miface;
7063
7064 for (i = 0; i < global->params.match_iface_count; i++) {
7065 miface = &global->params.match_ifaces[i];
7066 if (!miface->ifname ||
7067 fnmatch(miface->ifname, ifname, 0) == 0) {
7068 iface = os_zalloc(sizeof(*iface));
7069 if (!iface)
7070 return NULL;
7071 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007072 if (!miface->ifname)
7073 iface->matched = WPA_IFACE_MATCHED_NULL;
7074 else
7075 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007076 iface->ifname = ifname;
7077 return iface;
7078 }
7079 }
7080
7081 return NULL;
7082}
7083
7084
7085/**
7086 * wpa_supplicant_match_existing - Match existing interfaces
7087 * @global: Pointer to global data from wpa_supplicant_init()
7088 * Returns: 0 on success, -1 on failure
7089 */
7090static int wpa_supplicant_match_existing(struct wpa_global *global)
7091{
7092 struct if_nameindex *ifi, *ifp;
7093 struct wpa_supplicant *wpa_s;
7094 struct wpa_interface *iface;
7095
7096 ifp = if_nameindex();
7097 if (!ifp) {
7098 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7099 return -1;
7100 }
7101
7102 for (ifi = ifp; ifi->if_name; ifi++) {
7103 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7104 if (wpa_s)
7105 continue;
7106 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7107 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007108 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007109 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007110 }
7111 }
7112
7113 if_freenameindex(ifp);
7114 return 0;
7115}
7116
7117#endif /* CONFIG_MATCH_IFACE */
7118
7119
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007120/**
7121 * wpa_supplicant_add_iface - Add a new network interface
7122 * @global: Pointer to global data from wpa_supplicant_init()
7123 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007124 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007125 * Returns: Pointer to the created interface or %NULL on failure
7126 *
7127 * This function is used to add new network interfaces for %wpa_supplicant.
7128 * This can be called before wpa_supplicant_run() to add interfaces before the
7129 * main event loop has been started. In addition, new interfaces can be added
7130 * dynamically while %wpa_supplicant is already running. This could happen,
7131 * e.g., when a hotplug network adapter is inserted.
7132 */
7133struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007134 struct wpa_interface *iface,
7135 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007136{
7137 struct wpa_supplicant *wpa_s;
7138 struct wpa_interface t_iface;
7139 struct wpa_ssid *ssid;
7140
7141 if (global == NULL || iface == NULL)
7142 return NULL;
7143
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007144 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145 if (wpa_s == NULL)
7146 return NULL;
7147
7148 wpa_s->global = global;
7149
7150 t_iface = *iface;
7151 if (global->params.override_driver) {
7152 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7153 "('%s' -> '%s')",
7154 iface->driver, global->params.override_driver);
7155 t_iface.driver = global->params.override_driver;
7156 }
7157 if (global->params.override_ctrl_interface) {
7158 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7159 "ctrl_interface ('%s' -> '%s')",
7160 iface->ctrl_interface,
7161 global->params.override_ctrl_interface);
7162 t_iface.ctrl_interface =
7163 global->params.override_ctrl_interface;
7164 }
7165 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7166 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7167 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007168 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007169 return NULL;
7170 }
7171
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007172 /* Notify the control interfaces about new iface */
7173 if (wpas_notify_iface_added(wpa_s)) {
7174 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7175 return NULL;
7176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007177
Jimmy Chen115616e2022-07-10 10:25:21 +08007178 /* Notify the control interfaces about new networks */
7179 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7180 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007181 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chen115616e2022-07-10 10:25:21 +08007182 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7183 && os_strncmp((const char *) ssid->ssid,
7184 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7185 wpas_notify_persistent_group_added(wpa_s, ssid);
7186 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007187 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007188
7189 wpa_s->next = global->ifaces;
7190 global->ifaces = wpa_s;
7191
7192 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007193 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007194
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007195#ifdef CONFIG_P2P
7196 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007197 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007198 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007199 wpas_p2p_add_p2pdev_interface(
7200 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007201 wpa_printf(MSG_INFO,
7202 "P2P: Failed to enable P2P Device interface");
7203 /* Try to continue without. P2P will be disabled. */
7204 }
7205#endif /* CONFIG_P2P */
7206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007207 return wpa_s;
7208}
7209
7210
7211/**
7212 * wpa_supplicant_remove_iface - Remove a network interface
7213 * @global: Pointer to global data from wpa_supplicant_init()
7214 * @wpa_s: Pointer to the network interface to be removed
7215 * Returns: 0 if interface was removed, -1 if interface was not found
7216 *
7217 * This function can be used to dynamically remove network interfaces from
7218 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7219 * addition, this function is used to remove all remaining interfaces when
7220 * %wpa_supplicant is terminated.
7221 */
7222int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007223 struct wpa_supplicant *wpa_s,
7224 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007225{
7226 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007227#ifdef CONFIG_MESH
7228 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7229 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007230 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007231#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007232
7233 /* Remove interface from the global list of interfaces */
7234 prev = global->ifaces;
7235 if (prev == wpa_s) {
7236 global->ifaces = wpa_s->next;
7237 } else {
7238 while (prev && prev->next != wpa_s)
7239 prev = prev->next;
7240 if (prev == NULL)
7241 return -1;
7242 prev->next = wpa_s->next;
7243 }
7244
7245 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7246
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007247#ifdef CONFIG_MESH
7248 if (mesh_if_created) {
7249 ifname = os_strdup(wpa_s->ifname);
7250 if (ifname == NULL) {
7251 wpa_dbg(wpa_s, MSG_ERROR,
7252 "mesh: Failed to malloc ifname");
7253 return -1;
7254 }
7255 }
7256#endif /* CONFIG_MESH */
7257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007258 if (global->p2p_group_formation == wpa_s)
7259 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007260 if (global->p2p_invite_group == wpa_s)
7261 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007262 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007263
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007264#ifdef CONFIG_MESH
7265 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007266 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007267 os_free(ifname);
7268 }
7269#endif /* CONFIG_MESH */
7270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007271 return 0;
7272}
7273
7274
7275/**
7276 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7277 * @wpa_s: Pointer to the network interface
7278 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7279 */
7280const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7281{
7282 const char *eapol_method;
7283
7284 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7285 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7286 return "NO-EAP";
7287 }
7288
7289 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7290 if (eapol_method == NULL)
7291 return "UNKNOWN-EAP";
7292
7293 return eapol_method;
7294}
7295
7296
7297/**
7298 * wpa_supplicant_get_iface - Get a new network interface
7299 * @global: Pointer to global data from wpa_supplicant_init()
7300 * @ifname: Interface name
7301 * Returns: Pointer to the interface or %NULL if not found
7302 */
7303struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7304 const char *ifname)
7305{
7306 struct wpa_supplicant *wpa_s;
7307
7308 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7309 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7310 return wpa_s;
7311 }
7312 return NULL;
7313}
7314
7315
7316#ifndef CONFIG_NO_WPA_MSG
7317static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7318{
7319 struct wpa_supplicant *wpa_s = ctx;
7320 if (wpa_s == NULL)
7321 return NULL;
7322 return wpa_s->ifname;
7323}
7324#endif /* CONFIG_NO_WPA_MSG */
7325
7326
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007327#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7328#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7329#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7330
7331/* Periodic cleanup tasks */
7332static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7333{
7334 struct wpa_global *global = eloop_ctx;
7335 struct wpa_supplicant *wpa_s;
7336
7337 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7338 wpas_periodic, global, NULL);
7339
7340#ifdef CONFIG_P2P
7341 if (global->p2p)
7342 p2p_expire_peers(global->p2p);
7343#endif /* CONFIG_P2P */
7344
7345 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7346 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7347#ifdef CONFIG_AP
7348 ap_periodic(wpa_s);
7349#endif /* CONFIG_AP */
7350 }
7351}
7352
7353
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007354/**
7355 * wpa_supplicant_init - Initialize %wpa_supplicant
7356 * @params: Parameters for %wpa_supplicant
7357 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7358 *
7359 * This function is used to initialize %wpa_supplicant. After successful
7360 * initialization, the returned data pointer can be used to add and remove
7361 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7362 */
7363struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7364{
7365 struct wpa_global *global;
7366 int ret, i;
7367
7368 if (params == NULL)
7369 return NULL;
7370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007371#ifdef CONFIG_DRIVER_NDIS
7372 {
7373 void driver_ndis_init_ops(void);
7374 driver_ndis_init_ops();
7375 }
7376#endif /* CONFIG_DRIVER_NDIS */
7377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007378#ifndef CONFIG_NO_WPA_MSG
7379 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7380#endif /* CONFIG_NO_WPA_MSG */
7381
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007382 if (params->wpa_debug_file_path)
7383 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007384 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007385 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007386 if (params->wpa_debug_syslog)
7387 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007388 if (params->wpa_debug_tracing) {
7389 ret = wpa_debug_open_linux_tracing();
7390 if (ret) {
7391 wpa_printf(MSG_ERROR,
7392 "Failed to enable trace logging");
7393 return NULL;
7394 }
7395 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007396
7397 ret = eap_register_methods();
7398 if (ret) {
7399 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7400 if (ret == -2)
7401 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7402 "the same EAP type.");
7403 return NULL;
7404 }
7405
7406 global = os_zalloc(sizeof(*global));
7407 if (global == NULL)
7408 return NULL;
7409 dl_list_init(&global->p2p_srv_bonjour);
7410 dl_list_init(&global->p2p_srv_upnp);
7411 global->params.daemonize = params->daemonize;
7412 global->params.wait_for_monitor = params->wait_for_monitor;
7413 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7414 if (params->pid_file)
7415 global->params.pid_file = os_strdup(params->pid_file);
7416 if (params->ctrl_interface)
7417 global->params.ctrl_interface =
7418 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007419 if (params->ctrl_interface_group)
7420 global->params.ctrl_interface_group =
7421 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007422 if (params->override_driver)
7423 global->params.override_driver =
7424 os_strdup(params->override_driver);
7425 if (params->override_ctrl_interface)
7426 global->params.override_ctrl_interface =
7427 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007428#ifdef CONFIG_MATCH_IFACE
7429 global->params.match_iface_count = params->match_iface_count;
7430 if (params->match_iface_count) {
7431 global->params.match_ifaces =
7432 os_calloc(params->match_iface_count,
7433 sizeof(struct wpa_interface));
7434 os_memcpy(global->params.match_ifaces,
7435 params->match_ifaces,
7436 params->match_iface_count *
7437 sizeof(struct wpa_interface));
7438 }
7439#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007440#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007441 if (params->conf_p2p_dev)
7442 global->params.conf_p2p_dev =
7443 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007444#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007445 wpa_debug_level = global->params.wpa_debug_level =
7446 params->wpa_debug_level;
7447 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7448 params->wpa_debug_show_keys;
7449 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7450 params->wpa_debug_timestamp;
7451
Hai Shalomfdcde762020-04-02 11:19:20 -07007452 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007453
7454 if (eloop_init()) {
7455 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7456 wpa_supplicant_deinit(global);
7457 return NULL;
7458 }
7459
Jouni Malinen75ecf522011-06-27 15:19:46 -07007460 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007461
7462 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7463 if (global->ctrl_iface == NULL) {
7464 wpa_supplicant_deinit(global);
7465 return NULL;
7466 }
7467
7468 if (wpas_notify_supplicant_initialized(global)) {
7469 wpa_supplicant_deinit(global);
7470 return NULL;
7471 }
7472
7473 for (i = 0; wpa_drivers[i]; i++)
7474 global->drv_count++;
7475 if (global->drv_count == 0) {
7476 wpa_printf(MSG_ERROR, "No drivers enabled");
7477 wpa_supplicant_deinit(global);
7478 return NULL;
7479 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007480 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481 if (global->drv_priv == NULL) {
7482 wpa_supplicant_deinit(global);
7483 return NULL;
7484 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007485
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007486#ifdef CONFIG_WIFI_DISPLAY
7487 if (wifi_display_init(global) < 0) {
7488 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7489 wpa_supplicant_deinit(global);
7490 return NULL;
7491 }
7492#endif /* CONFIG_WIFI_DISPLAY */
7493
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007494 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7495 wpas_periodic, global, NULL);
7496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007497 return global;
7498}
7499
7500
7501/**
7502 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7503 * @global: Pointer to global data from wpa_supplicant_init()
7504 * Returns: 0 after successful event loop run, -1 on failure
7505 *
7506 * This function starts the main event loop and continues running as long as
7507 * there are any remaining events. In most cases, this function is running as
7508 * long as the %wpa_supplicant process in still in use.
7509 */
7510int wpa_supplicant_run(struct wpa_global *global)
7511{
7512 struct wpa_supplicant *wpa_s;
7513
7514 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007515 (wpa_supplicant_daemon(global->params.pid_file) ||
7516 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007517 return -1;
7518
Dmitry Shmidte4663042016-04-04 10:07:49 -07007519#ifdef CONFIG_MATCH_IFACE
7520 if (wpa_supplicant_match_existing(global))
7521 return -1;
7522#endif
7523
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007524 if (global->params.wait_for_monitor) {
7525 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007526 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007527 wpa_supplicant_ctrl_iface_wait(
7528 wpa_s->ctrl_iface);
7529 }
7530
7531 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7532 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7533
7534 eloop_run();
7535
7536 return 0;
7537}
7538
7539
7540/**
7541 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7542 * @global: Pointer to global data from wpa_supplicant_init()
7543 *
7544 * This function is called to deinitialize %wpa_supplicant and to free all
7545 * allocated resources. Remaining network interfaces will also be removed.
7546 */
7547void wpa_supplicant_deinit(struct wpa_global *global)
7548{
7549 int i;
7550
7551 if (global == NULL)
7552 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007553
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007554 eloop_cancel_timeout(wpas_periodic, global, NULL);
7555
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007556#ifdef CONFIG_WIFI_DISPLAY
7557 wifi_display_deinit(global);
7558#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007559
7560 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007561 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007562
7563 if (global->ctrl_iface)
7564 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7565
7566 wpas_notify_supplicant_deinitialized(global);
7567
7568 eap_peer_unregister_methods();
7569#ifdef CONFIG_AP
7570 eap_server_unregister_methods();
7571#endif /* CONFIG_AP */
7572
7573 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7574 if (!global->drv_priv[i])
7575 continue;
7576 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7577 }
7578 os_free(global->drv_priv);
7579
7580 random_deinit();
7581
7582 eloop_destroy();
7583
7584 if (global->params.pid_file) {
7585 os_daemonize_terminate(global->params.pid_file);
7586 os_free(global->params.pid_file);
7587 }
7588 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007589 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007590 os_free(global->params.override_driver);
7591 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007592#ifdef CONFIG_MATCH_IFACE
7593 os_free(global->params.match_ifaces);
7594#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007595#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007596 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007597#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007598
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007599 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007600 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007601 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007603 os_free(global);
7604 wpa_debug_close_syslog();
7605 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007606 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007607}
7608
7609
7610void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7611{
7612 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7613 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7614 char country[3];
7615 country[0] = wpa_s->conf->country[0];
7616 country[1] = wpa_s->conf->country[1];
7617 country[2] = '\0';
7618 if (wpa_drv_set_country(wpa_s, country) < 0) {
7619 wpa_printf(MSG_ERROR, "Failed to set country code "
7620 "'%s'", country);
7621 }
7622 }
7623
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007624 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7625 wpas_init_ext_pw(wpa_s);
7626
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007627 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7628 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7629
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007630 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7631 struct wpa_driver_capa capa;
7632 int res = wpa_drv_get_capa(wpa_s, &capa);
7633
7634 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7635 wpa_printf(MSG_ERROR,
7636 "Failed to update wowlan_triggers to '%s'",
7637 wpa_s->conf->wowlan_triggers);
7638 }
7639
Hai Shalom81f62d82019-07-22 12:10:00 -07007640 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7641 wpa_supplicant_set_default_scan_ies(wpa_s);
7642
Hai Shalom899fcc72020-10-19 14:38:18 -07007643#ifdef CONFIG_BGSCAN
7644 /*
7645 * We default to global bgscan parameters only when per-network bgscan
7646 * parameters aren't set. Only bother resetting bgscan parameters if
7647 * this is the case.
7648 */
7649 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7650 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7651 wpa_s->wpa_state == WPA_COMPLETED)
7652 wpa_supplicant_reset_bgscan(wpa_s);
7653#endif /* CONFIG_BGSCAN */
7654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007655#ifdef CONFIG_WPS
7656 wpas_wps_update_config(wpa_s);
7657#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007658 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007659 wpa_s->conf->changed_parameters = 0;
7660}
7661
7662
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007663void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007664{
7665 int i;
7666
7667 for (i = 0; i < *num_freqs; i++) {
7668 if (freqs[i] == freq)
7669 return;
7670 }
7671
7672 freqs[*num_freqs] = freq;
7673 (*num_freqs)++;
7674}
7675
7676
7677static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7678{
7679 struct wpa_bss *bss, *cbss;
7680 const int max_freqs = 10;
7681 int *freqs;
7682 int num_freqs = 0;
7683
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007684 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007685 if (freqs == NULL)
7686 return NULL;
7687
7688 cbss = wpa_s->current_bss;
7689
7690 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7691 if (bss == cbss)
7692 continue;
7693 if (bss->ssid_len == cbss->ssid_len &&
7694 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007695 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007696 add_freq(freqs, &num_freqs, bss->freq);
7697 if (num_freqs == max_freqs)
7698 break;
7699 }
7700 }
7701
7702 if (num_freqs == 0) {
7703 os_free(freqs);
7704 freqs = NULL;
7705 }
7706
7707 return freqs;
7708}
7709
7710
7711void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7712{
7713 int timeout;
7714 int count;
7715 int *freqs = NULL;
7716
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007717 wpas_connect_work_done(wpa_s);
7718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007719 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007720 * Remove possible authentication timeout since the connection failed.
7721 */
7722 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7723
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007724 /*
Hai Shalom60840252021-02-19 19:02:11 -08007725 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007726 * generated based on local request to disconnect.
7727 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007728 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007729 wpa_s->own_disconnect_req = 0;
7730 wpa_dbg(wpa_s, MSG_DEBUG,
7731 "Ignore connection failure due to local request to disconnect");
7732 return;
7733 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007734 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007735 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7736 "indication since interface has been put into "
7737 "disconnected state");
7738 return;
7739 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007740 if (wpa_s->auto_reconnect_disabled) {
7741 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7742 "indication since auto connect is disabled");
7743 return;
7744 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007745
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007746 /*
Hai Shalom60840252021-02-19 19:02:11 -08007747 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007748 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007749 */
Hai Shalom60840252021-02-19 19:02:11 -08007750 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007751 if (count == 1 && wpa_s->current_bss) {
7752 /*
Hai Shalom60840252021-02-19 19:02:11 -08007753 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007754 * another BSS available for the same ESS, we should try that
7755 * next. Otherwise, we may as well try this one once more
7756 * before allowing other, likely worse, ESSes to be considered.
7757 */
7758 freqs = get_bss_freqs_in_ess(wpa_s);
7759 if (freqs) {
7760 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7761 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007762 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007763 /*
7764 * On the next scan, go through only the known channels
7765 * used in this ESS based on previous scans to speed up
7766 * common load balancing use case.
7767 */
7768 os_free(wpa_s->next_scan_freqs);
7769 wpa_s->next_scan_freqs = freqs;
7770 }
7771 }
7772
Hai Shalom899fcc72020-10-19 14:38:18 -07007773 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007774
Hai Shalom899fcc72020-10-19 14:38:18 -07007775 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007776 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7777 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007778 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007779 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007780 /*
7781 * Multiple consecutive connection failures mean that other APs are
7782 * either not available or have already been tried, so we can start
7783 * increasing the delay here to avoid constant scanning.
7784 */
7785 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007786 case 1:
7787 timeout = 100;
7788 break;
7789 case 2:
7790 timeout = 500;
7791 break;
7792 case 3:
7793 timeout = 1000;
7794 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007795 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007796 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007797 break;
7798 default:
7799 timeout = 10000;
7800 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007801 }
7802
Hai Shalom899fcc72020-10-19 14:38:18 -07007803 wpa_dbg(wpa_s, MSG_DEBUG,
7804 "Consecutive connection failures: %d --> request scan in %d ms",
7805 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007807 /*
7808 * TODO: if more than one possible AP is available in scan results,
7809 * could try the other ones before requesting a new scan.
7810 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007811
7812 /* speed up the connection attempt with normal scan */
7813 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007814 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7815 1000 * (timeout % 1000));
7816}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007817
7818
Hai Shalomce48b4a2018-09-05 11:41:35 -07007819#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007820
7821void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7822{
7823 struct wpa_ssid *ssid = wpa_s->current_ssid;
7824 const u8 *realm, *username, *rrk;
7825 size_t realm_len, username_len, rrk_len;
7826 u16 next_seq_num;
7827
7828 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7829 * Check for ERP keys existing to limit when this can be done since
7830 * the rejection response is not protected and such triggers should
7831 * really not allow internal state to be modified unless required to
7832 * avoid significant issues in functionality. In addition, drop
7833 * externally configure PMKSA entries even without ERP keys since it
7834 * is possible for an external component to add PMKSA entries for FILS
7835 * authentication without restoring previously generated ERP keys.
7836 *
7837 * In this case, this is needed to allow recovery from cases where the
7838 * AP or authentication server has dropped PMKSAs and ERP keys. */
7839 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7840 return;
7841
7842 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7843 &username, &username_len,
7844 &realm, &realm_len, &next_seq_num,
7845 &rrk, &rrk_len) != 0 ||
7846 !realm) {
7847 wpa_dbg(wpa_s, MSG_DEBUG,
7848 "FILS: Drop external PMKSA cache entry");
7849 wpa_sm_aborted_external_cached(wpa_s->wpa);
7850 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7851 return;
7852 }
7853
7854 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7855 wpa_sm_aborted_cached(wpa_s->wpa);
7856 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7857}
7858
7859
Hai Shalomce48b4a2018-09-05 11:41:35 -07007860void fils_connection_failure(struct wpa_supplicant *wpa_s)
7861{
7862 struct wpa_ssid *ssid = wpa_s->current_ssid;
7863 const u8 *realm, *username, *rrk;
7864 size_t realm_len, username_len, rrk_len;
7865 u16 next_seq_num;
7866
7867 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7868 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7869 &username, &username_len,
7870 &realm, &realm_len, &next_seq_num,
7871 &rrk, &rrk_len) != 0 ||
7872 !realm)
7873 return;
7874
7875 wpa_hexdump_ascii(MSG_DEBUG,
7876 "FILS: Store last connection failure realm",
7877 realm, realm_len);
7878 os_free(wpa_s->last_con_fail_realm);
7879 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7880 if (wpa_s->last_con_fail_realm) {
7881 wpa_s->last_con_fail_realm_len = realm_len;
7882 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7883 }
7884}
7885#endif /* CONFIG_FILS */
7886
7887
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007888int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7889{
7890 return wpa_s->conf->ap_scan == 2 ||
7891 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7892}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007893
Dmitry Shmidt04949592012-07-19 12:16:46 -07007894
Gabriel Biren57ededa2021-09-03 16:08:50 +00007895#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007896int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7897 struct wpa_ssid *ssid,
7898 const char *field,
7899 const char *value)
7900{
7901#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007902 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007903
7904 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7905 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7906 (const u8 *) value, os_strlen(value));
7907
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007908 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007909 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007910#else /* IEEE8021X_EAPOL */
7911 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7912 return -1;
7913#endif /* IEEE8021X_EAPOL */
7914}
7915
7916int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7917 struct wpa_ssid *ssid,
7918 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007919 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007920{
7921#ifdef IEEE8021X_EAPOL
7922 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007923 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007924
7925 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007926 case WPA_CTRL_REQ_EAP_IDENTITY:
7927 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007928 os_free(eap->imsi_identity);
7929 if (value == NULL)
7930 return -1;
7931 identity = os_strchr(value, ':');
7932 if (identity == NULL) {
7933 /* plain identity */
7934 eap->identity = (u8 *)os_strdup(value);
7935 eap->identity_len = os_strlen(value);
7936 } else {
7937 /* have both plain identity and encrypted identity */
7938 imsi_identity = value;
7939 *identity++ = '\0';
7940 /* plain identity */
7941 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7942 eap->imsi_identity_len = strlen(imsi_identity);
7943 /* encrypted identity */
7944 eap->identity = (u8 *)dup_binstr(identity,
7945 value_len - strlen(imsi_identity) - 1);
7946 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7947 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007948 eap->pending_req_identity = 0;
7949 if (ssid == wpa_s->current_ssid)
7950 wpa_s->reassociate = 1;
7951 break;
7952 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007953 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007954 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007955 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007956 eap->pending_req_password = 0;
7957 if (ssid == wpa_s->current_ssid)
7958 wpa_s->reassociate = 1;
7959 break;
7960 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007961 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007962 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007963 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007964 eap->pending_req_new_password = 0;
7965 if (ssid == wpa_s->current_ssid)
7966 wpa_s->reassociate = 1;
7967 break;
7968 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007969 str_clear_free(eap->cert.pin);
7970 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007971 eap->pending_req_pin = 0;
7972 if (ssid == wpa_s->current_ssid)
7973 wpa_s->reassociate = 1;
7974 break;
7975 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007976 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007977 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007978 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007979 os_free(eap->pending_req_otp);
7980 eap->pending_req_otp = NULL;
7981 eap->pending_req_otp_len = 0;
7982 break;
7983 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007984 str_clear_free(eap->cert.private_key_passwd);
7985 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007986 eap->pending_req_passphrase = 0;
7987 if (ssid == wpa_s->current_ssid)
7988 wpa_s->reassociate = 1;
7989 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007990 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007991 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007992 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007993 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007994 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007995 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7996 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7997 return -1;
7998 ssid->mem_only_psk = 1;
7999 if (ssid->passphrase)
8000 wpa_config_update_psk(ssid);
8001 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8002 wpa_supplicant_req_scan(wpa_s, 0, 0);
8003 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008004 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8005 if (eap->pending_ext_cert_check != PENDING_CHECK)
8006 return -1;
8007 if (os_strcmp(value, "good") == 0)
8008 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8009 else if (os_strcmp(value, "bad") == 0)
8010 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8011 else
8012 return -1;
8013 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008014 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008015 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008016 return -1;
8017 }
8018
8019 return 0;
8020#else /* IEEE8021X_EAPOL */
8021 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8022 return -1;
8023#endif /* IEEE8021X_EAPOL */
8024}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008025#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008026
8027
8028int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8029{
Hai Shalomfdcde762020-04-02 11:19:20 -07008030#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008031 int i;
8032 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008033#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008034
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008035 if (wpa_s->p2p_mgmt)
8036 return 1; /* no normal network profiles on p2p_mgmt interface */
8037
Dmitry Shmidt04949592012-07-19 12:16:46 -07008038 if (ssid == NULL)
8039 return 1;
8040
8041 if (ssid->disabled)
8042 return 1;
8043
Hai Shalomfdcde762020-04-02 11:19:20 -07008044#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008045 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008046 drv_enc = wpa_s->drv_enc;
8047 else
8048 drv_enc = (unsigned int) -1;
8049
8050 for (i = 0; i < NUM_WEP_KEYS; i++) {
8051 size_t len = ssid->wep_key_len[i];
8052 if (len == 0)
8053 continue;
8054 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8055 continue;
8056 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8057 continue;
8058 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8059 continue;
8060 return 1; /* invalid WEP key */
8061 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008062#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008063
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008064 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008065 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008066 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008067 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008068 return 1;
8069
Dmitry Shmidt04949592012-07-19 12:16:46 -07008070 return 0;
8071}
8072
8073
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008074int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8075{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008076 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8077 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8078 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8079 /*
8080 * Driver does not support BIP -- ignore pmf=1 default
8081 * since the connection with PMF would fail and the
8082 * configuration does not require PMF to be enabled.
8083 */
8084 return NO_MGMT_FRAME_PROTECTION;
8085 }
8086
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008087 if (ssid &&
8088 (ssid->key_mgmt &
8089 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8090 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8091 /*
8092 * Do not use the default PMF value for non-RSN networks
8093 * since PMF is available only with RSN and pmf=2
8094 * configuration would otherwise prevent connections to
8095 * all open networks.
8096 */
8097 return NO_MGMT_FRAME_PROTECTION;
8098 }
8099
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008100 return wpa_s->conf->pmf;
8101 }
8102
8103 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008104}
8105
8106
Hai Shalomc1a21442022-02-04 13:43:00 -08008107int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8108{
8109 if (wpa_s->current_ssid == NULL ||
8110 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8111 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8112 return 0;
8113 return wpa_sm_pmf_enabled(wpa_s->wpa);
8114}
8115
8116
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008117int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008118{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008119 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008120 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008121 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008122 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008123 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008124}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008125
8126
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008127void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008128{
8129 struct wpa_ssid *ssid = wpa_s->current_ssid;
8130 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008131 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008132
8133 if (ssid == NULL) {
8134 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8135 "SSID block");
8136 return;
8137 }
8138
8139 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8140 return;
8141
8142 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008143
8144#ifdef CONFIG_P2P
8145 if (ssid->p2p_group &&
8146 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8147 /*
8148 * Skip the wait time since there is a short timeout on the
8149 * connection to a P2P group.
8150 */
8151 return;
8152 }
8153#endif /* CONFIG_P2P */
8154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008155 if (ssid->auth_failures > 50)
8156 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008157 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008158 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008159 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008160 dur = 90;
8161 else if (ssid->auth_failures > 3)
8162 dur = 60;
8163 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008164 dur = 30;
8165 else if (ssid->auth_failures > 1)
8166 dur = 20;
8167 else
8168 dur = 10;
8169
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008170 if (ssid->auth_failures > 1 &&
8171 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8172 dur += os_random() % (ssid->auth_failures * 10);
8173
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008174 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008175 if (now.sec + dur <= ssid->disabled_until.sec)
8176 return;
8177
8178 ssid->disabled_until.sec = now.sec + dur;
8179
8180 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008181 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008182 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008183 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008184
8185 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8186 int msg_len = snprintf(NULL, 0, format_str,
8187 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8188 ssid->auth_failures, dur, reason) + 1;
8189 char *msg = os_malloc(msg_len);
8190 snprintf(msg, msg_len, format_str,
8191 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8192 ssid->auth_failures, dur, reason);
8193 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8194 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008195}
8196
8197
8198void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8199 struct wpa_ssid *ssid, int clear_failures)
8200{
8201 if (ssid == NULL)
8202 return;
8203
8204 if (ssid->disabled_until.sec) {
8205 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8206 "id=%d ssid=\"%s\"",
8207 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8208 }
8209 ssid->disabled_until.sec = 0;
8210 ssid->disabled_until.usec = 0;
8211 if (clear_failures)
8212 ssid->auth_failures = 0;
8213}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008214
8215
8216int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8217{
8218 size_t i;
8219
8220 if (wpa_s->disallow_aps_bssid == NULL)
8221 return 0;
8222
8223 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8224 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8225 bssid, ETH_ALEN) == 0)
8226 return 1;
8227 }
8228
8229 return 0;
8230}
8231
8232
8233int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8234 size_t ssid_len)
8235{
8236 size_t i;
8237
8238 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8239 return 0;
8240
8241 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8242 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8243 if (ssid_len == s->ssid_len &&
8244 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8245 return 1;
8246 }
8247
8248 return 0;
8249}
8250
8251
8252/**
8253 * wpas_request_connection - Request a new connection
8254 * @wpa_s: Pointer to the network interface
8255 *
8256 * This function is used to request a new connection to be found. It will mark
8257 * the interface to allow reassociation and request a new scan to find a
8258 * suitable network to connect to.
8259 */
8260void wpas_request_connection(struct wpa_supplicant *wpa_s)
8261{
8262 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008263 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008264 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008265 wpa_s->disconnected = 0;
8266 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008267 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008268
8269 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8270 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008271 else
8272 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008273}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008274
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008275
Roshan Pius02242d72016-08-09 15:31:48 -07008276/**
8277 * wpas_request_disconnection - Request disconnection
8278 * @wpa_s: Pointer to the network interface
8279 *
8280 * This function is used to request disconnection from the currently connected
8281 * network. This will stop any ongoing scans and initiate deauthentication.
8282 */
8283void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8284{
8285#ifdef CONFIG_SME
8286 wpa_s->sme.prev_bssid_set = 0;
8287#endif /* CONFIG_SME */
8288 wpa_s->reassociate = 0;
8289 wpa_s->disconnected = 1;
8290 wpa_supplicant_cancel_sched_scan(wpa_s);
8291 wpa_supplicant_cancel_scan(wpa_s);
8292 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8293 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008294 radio_remove_works(wpa_s, "connect", 0);
8295 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008296 wpa_s->roam_in_progress = false;
8297#ifdef CONFIG_WNM
8298 wpa_s->bss_trans_mgmt_in_progress = false;
8299#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008300}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008301
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008302
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008303void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8304 struct wpa_used_freq_data *freqs_data,
8305 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008306{
8307 unsigned int i;
8308
8309 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8310 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008311 for (i = 0; i < len; i++) {
8312 struct wpa_used_freq_data *cur = &freqs_data[i];
8313 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8314 i, cur->freq, cur->flags);
8315 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008316}
8317
8318
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008319/*
8320 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008321 * are using the same radio as the current interface, and in addition, get
8322 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008323 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008324int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8325 struct wpa_used_freq_data *freqs_data,
8326 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008327{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008328 struct wpa_supplicant *ifs;
8329 u8 bssid[ETH_ALEN];
8330 int freq;
8331 unsigned int idx = 0, i;
8332
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008333 wpa_dbg(wpa_s, MSG_DEBUG,
8334 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008335 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008336
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008337 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8338 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008339 if (idx == len)
8340 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008341
8342 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8343 continue;
8344
8345 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008346 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8347 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008348 freq = ifs->current_ssid->frequency;
8349 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8350 freq = ifs->assoc_freq;
8351 else
8352 continue;
8353
8354 /* Hold only distinct freqs */
8355 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008356 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008357 break;
8358
8359 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008360 freqs_data[idx++].freq = freq;
8361
8362 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008363 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008364 WPA_FREQ_USED_BY_P2P_CLIENT :
8365 WPA_FREQ_USED_BY_INFRA_STATION;
8366 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008367 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008368
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008369 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008370 return idx;
8371}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008372
8373
8374/*
8375 * Find the operating frequencies of any of the virtual interfaces that
8376 * are using the same radio as the current interface.
8377 */
8378int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8379 int *freq_array, unsigned int len)
8380{
8381 struct wpa_used_freq_data *freqs_data;
8382 int num, i;
8383
8384 os_memset(freq_array, 0, sizeof(int) * len);
8385
8386 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8387 if (!freqs_data)
8388 return -1;
8389
8390 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8391 for (i = 0; i < num; i++)
8392 freq_array[i] = freqs_data[i].freq;
8393
8394 os_free(freqs_data);
8395
8396 return num;
8397}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008398
8399
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008400struct wpa_supplicant *
8401wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8402{
8403 switch (frame) {
8404#ifdef CONFIG_P2P
8405 case VENDOR_ELEM_PROBE_REQ_P2P:
8406 case VENDOR_ELEM_PROBE_RESP_P2P:
8407 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8408 case VENDOR_ELEM_BEACON_P2P_GO:
8409 case VENDOR_ELEM_P2P_PD_REQ:
8410 case VENDOR_ELEM_P2P_PD_RESP:
8411 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8412 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8413 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8414 case VENDOR_ELEM_P2P_INV_REQ:
8415 case VENDOR_ELEM_P2P_INV_RESP:
8416 case VENDOR_ELEM_P2P_ASSOC_REQ:
8417 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008418 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008419#endif /* CONFIG_P2P */
8420 default:
8421 return wpa_s;
8422 }
8423}
8424
8425
8426void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8427{
8428 unsigned int i;
8429 char buf[30];
8430
8431 wpa_printf(MSG_DEBUG, "Update vendor elements");
8432
8433 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8434 if (wpa_s->vendor_elem[i]) {
8435 int res;
8436
8437 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8438 if (!os_snprintf_error(sizeof(buf), res)) {
8439 wpa_hexdump_buf(MSG_DEBUG, buf,
8440 wpa_s->vendor_elem[i]);
8441 }
8442 }
8443 }
8444
8445#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008446 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008447 wpa_s->global->p2p &&
8448 !wpa_s->global->p2p_disabled)
8449 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8450#endif /* CONFIG_P2P */
8451}
8452
8453
8454int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8455 const u8 *elem, size_t len)
8456{
8457 u8 *ie, *end;
8458
8459 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8460 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8461
8462 for (; ie + 1 < end; ie += 2 + ie[1]) {
8463 if (ie + len > end)
8464 break;
8465 if (os_memcmp(ie, elem, len) != 0)
8466 continue;
8467
8468 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8469 wpabuf_free(wpa_s->vendor_elem[frame]);
8470 wpa_s->vendor_elem[frame] = NULL;
8471 } else {
8472 os_memmove(ie, ie + len, end - (ie + len));
8473 wpa_s->vendor_elem[frame]->used -= len;
8474 }
8475 wpas_vendor_elem_update(wpa_s);
8476 return 0;
8477 }
8478
8479 return -1;
8480}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008481
8482
8483struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008484 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008485 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008486{
8487 u16 i;
8488
Hai Shalomc1a21442022-02-04 13:43:00 -08008489 if (!modes)
8490 return NULL;
8491
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008492 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008493 if (modes[i].mode != mode ||
8494 !modes[i].num_channels || !modes[i].channels)
8495 continue;
8496 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8497 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008498 return &modes[i];
8499 }
8500
8501 return NULL;
8502}
8503
8504
Hai Shalomc1a21442022-02-04 13:43:00 -08008505struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8506 u16 num_modes, int freq)
8507{
8508 int i, j;
8509
8510 for (i = 0; i < num_modes; i++) {
8511 for (j = 0; j < modes[i].num_channels; j++) {
8512 if (freq == modes[i].channels[j].freq)
8513 return &modes[i];
8514 }
8515 }
8516
8517 return NULL;
8518}
8519
8520
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008521static struct
8522wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8523 const u8 *bssid)
8524{
8525 struct wpa_bss_tmp_disallowed *bss;
8526
8527 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8528 struct wpa_bss_tmp_disallowed, list) {
8529 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8530 return bss;
8531 }
8532
8533 return NULL;
8534}
8535
8536
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008537static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8538{
8539 struct wpa_bss_tmp_disallowed *tmp;
8540 unsigned int num_bssid = 0;
8541 u8 *bssids;
8542 int ret;
8543
8544 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8545 if (!bssids)
8546 return -1;
8547 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8548 struct wpa_bss_tmp_disallowed, list) {
8549 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8550 ETH_ALEN);
8551 num_bssid++;
8552 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008553 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008554 os_free(bssids);
8555 return ret;
8556}
8557
8558
8559static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8560{
8561 struct wpa_supplicant *wpa_s = eloop_ctx;
8562 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8563
8564 /* Make sure the bss is not already freed */
8565 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8566 struct wpa_bss_tmp_disallowed, list) {
8567 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008568 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008569 wpa_set_driver_tmp_disallow_list(wpa_s);
8570 break;
8571 }
8572 }
8573}
8574
8575
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008576void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008577 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008578{
8579 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008580
8581 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8582 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008583 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008584 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008585 }
8586
8587 bss = os_malloc(sizeof(*bss));
8588 if (!bss) {
8589 wpa_printf(MSG_DEBUG,
8590 "Failed to allocate memory for temp disallow BSS");
8591 return;
8592 }
8593
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008594 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8595 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008596 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008597
8598finish:
8599 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008600 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8601 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008602}
8603
8604
Hai Shalom74f70d42019-02-11 14:42:39 -08008605int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8606 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008607{
Hai Shalom74f70d42019-02-11 14:42:39 -08008608 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008609
8610 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8611 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008612 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8613 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008614 break;
8615 }
8616 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008617 if (!disallowed)
8618 return 0;
8619
8620 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008621 bss->level > disallowed->rssi_threshold) {
8622 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8623 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008624 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008625 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008626
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008627 return 1;
8628}
Hai Shalom81f62d82019-07-22 12:10:00 -07008629
8630
8631int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8632 unsigned int type, const u8 *addr,
8633 const u8 *mask)
8634{
8635 if ((addr && !mask) || (!addr && mask)) {
8636 wpa_printf(MSG_INFO,
8637 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8638 return -1;
8639 }
8640
8641 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8642 wpa_printf(MSG_INFO,
8643 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8644 return -1;
8645 }
8646
8647 if (type & MAC_ADDR_RAND_SCAN) {
8648 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8649 addr, mask))
8650 return -1;
8651 }
8652
8653 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8654 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8655 addr, mask))
8656 return -1;
8657
8658 if (wpa_s->sched_scanning && !wpa_s->pno)
8659 wpas_scan_restart_sched_scan(wpa_s);
8660 }
8661
8662 if (type & MAC_ADDR_RAND_PNO) {
8663 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8664 addr, mask))
8665 return -1;
8666
8667 if (wpa_s->pno) {
8668 wpas_stop_pno(wpa_s);
8669 wpas_start_pno(wpa_s);
8670 }
8671 }
8672
8673 return 0;
8674}
8675
8676
8677int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8678 unsigned int type)
8679{
8680 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8681 if (wpa_s->pno) {
8682 if (type & MAC_ADDR_RAND_PNO) {
8683 wpas_stop_pno(wpa_s);
8684 wpas_start_pno(wpa_s);
8685 }
8686 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8687 wpas_scan_restart_sched_scan(wpa_s);
8688 }
8689
8690 return 0;
8691}
Hai Shalomfdcde762020-04-02 11:19:20 -07008692
8693
8694int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8695 struct wpa_signal_info *si)
8696{
8697 int res;
8698
8699 if (!wpa_s->driver->signal_poll)
8700 return -1;
8701
8702 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8703
8704#ifdef CONFIG_TESTING_OPTIONS
8705 if (res == 0) {
8706 struct driver_signal_override *dso;
8707
8708 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8709 struct driver_signal_override, list) {
8710 if (os_memcmp(wpa_s->bssid, dso->bssid,
8711 ETH_ALEN) != 0)
8712 continue;
8713 wpa_printf(MSG_DEBUG,
8714 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8715 si->current_signal,
8716 dso->si_current_signal,
8717 si->avg_signal,
8718 dso->si_avg_signal,
8719 si->avg_beacon_signal,
8720 dso->si_avg_beacon_signal,
8721 si->current_noise,
8722 dso->si_current_noise);
8723 si->current_signal = dso->si_current_signal;
8724 si->avg_signal = dso->si_avg_signal;
8725 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8726 si->current_noise = dso->si_current_noise;
8727 break;
8728 }
8729 }
8730#endif /* CONFIG_TESTING_OPTIONS */
8731
8732 return res;
8733}
8734
8735
8736struct wpa_scan_results *
8737wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8738{
8739 struct wpa_scan_results *scan_res;
8740#ifdef CONFIG_TESTING_OPTIONS
8741 size_t idx;
8742#endif /* CONFIG_TESTING_OPTIONS */
8743
8744 if (!wpa_s->driver->get_scan_results2)
8745 return NULL;
8746
8747 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8748
8749#ifdef CONFIG_TESTING_OPTIONS
8750 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8751 struct driver_signal_override *dso;
8752 struct wpa_scan_res *res = scan_res->res[idx];
8753
8754 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8755 struct driver_signal_override, list) {
8756 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8757 continue;
8758 wpa_printf(MSG_DEBUG,
8759 "Override driver scan signal level %d->%d for "
8760 MACSTR,
8761 res->level, dso->scan_level,
8762 MAC2STR(res->bssid));
8763 res->flags |= WPA_SCAN_QUAL_INVALID;
8764 if (dso->scan_level < 0)
8765 res->flags |= WPA_SCAN_LEVEL_DBM;
8766 else
8767 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8768 res->level = dso->scan_level;
8769 break;
8770 }
8771 }
8772#endif /* CONFIG_TESTING_OPTIONS */
8773
8774 return scan_res;
8775}