blob: 4503ae995f8752b18bbbb309b182a44042c2de56 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalomc1a21442022-02-04 13:43:00 -08003 * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080044#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080046#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080047#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "wpas_glue.h"
49#include "wps_supplicant.h"
50#include "ibss_rsn.h"
51#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "ap.h"
54#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070055#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "notify.h"
57#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059#include "bss.h"
60#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080061#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070062#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070063#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070064#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080065#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066#include "dpp_supplicant.h"
67#ifdef CONFIG_MESH
68#include "ap/ap_config.h"
69#include "ap/hostapd.h"
70#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070072const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080074"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070076const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080077"This software may be distributed under the terms of the BSD license.\n"
78"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079#ifdef EAP_TLS_OPENSSL
80"\nThis product includes software developed by the OpenSSL Project\n"
81"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
82#endif /* EAP_TLS_OPENSSL */
83;
84
85#ifndef CONFIG_NO_STDOUT_DEBUG
86/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080088"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091"\n"
92"Redistribution and use in source and binary forms, with or without\n"
93"modification, are permitted provided that the following conditions are\n"
94"met:\n"
95"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070096const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097"1. Redistributions of source code must retain the above copyright\n"
98" notice, this list of conditions and the following disclaimer.\n"
99"\n"
100"2. Redistributions in binary form must reproduce the above copyright\n"
101" notice, this list of conditions and the following disclaimer in the\n"
102" documentation and/or other materials provided with the distribution.\n"
103"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
106" names of its contributors may be used to endorse or promote products\n"
107" derived from this software without specific prior written permission.\n"
108"\n"
109"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
110"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
111"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
112"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700113const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
115"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
116"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
117"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
118"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
119"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
120"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
121"\n";
122#endif /* CONFIG_NO_STDOUT_DEBUG */
123
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700124
125static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
126#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
127static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
128#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700129#ifdef CONFIG_OWE
130static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
131#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700132
133
Hai Shalomfdcde762020-04-02 11:19:20 -0700134#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700135/* Configure default/group WEP keys for static WEP */
136int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
137{
138 int i, set = 0;
139
140 for (i = 0; i < NUM_WEP_KEYS; i++) {
141 if (ssid->wep_key_len[i] == 0)
142 continue;
143
144 set = 1;
145 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
146 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700147 ssid->wep_key[i], ssid->wep_key_len[i],
148 i == ssid->wep_tx_keyidx ?
149 KEY_FLAG_GROUP_RX_TX_DEFAULT :
150 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151 }
152
153 return set;
154}
Hai Shalomfdcde762020-04-02 11:19:20 -0700155#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156
157
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700158int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
159 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160{
161 u8 key[32];
162 size_t keylen;
163 enum wpa_alg alg;
164 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800165 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166
167 /* IBSS/WPA-None uses only one key (Group) for both receiving and
168 * sending unicast and multicast packets. */
169
170 if (ssid->mode != WPAS_MODE_IBSS) {
171 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
172 "IBSS/ad-hoc) for WPA-None", ssid->mode);
173 return -1;
174 }
175
176 if (!ssid->psk_set) {
177 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
178 "WPA-None");
179 return -1;
180 }
181
182 switch (wpa_s->group_cipher) {
183 case WPA_CIPHER_CCMP:
184 os_memcpy(key, ssid->psk, 16);
185 keylen = 16;
186 alg = WPA_ALG_CCMP;
187 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700188 case WPA_CIPHER_GCMP:
189 os_memcpy(key, ssid->psk, 16);
190 keylen = 16;
191 alg = WPA_ALG_GCMP;
192 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 case WPA_CIPHER_TKIP:
194 /* WPA-None uses the same Michael MIC key for both TX and RX */
195 os_memcpy(key, ssid->psk, 16 + 8);
196 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
197 keylen = 32;
198 alg = WPA_ALG_TKIP;
199 break;
200 default:
201 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
202 "WPA-None", wpa_s->group_cipher);
203 return -1;
204 }
205
206 /* TODO: should actually remember the previously used seq#, both for TX
207 * and RX from each STA.. */
208
Hai Shalomfdcde762020-04-02 11:19:20 -0700209 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
210 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800211 os_memset(key, 0, sizeof(key));
212 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213}
214
215
216static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
217{
218 struct wpa_supplicant *wpa_s = eloop_ctx;
219 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700220 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
221 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
222 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223 bssid = wpa_s->pending_bssid;
224 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
225 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800226 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700227 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800229 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_s->reassociate = 1;
231
232 /*
233 * If we timed out, the AP or the local radio may be busy.
234 * So, wait a second until scanning again.
235 */
236 wpa_supplicant_req_scan(wpa_s, 1, 0);
237}
238
239
240/**
241 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
242 * @wpa_s: Pointer to wpa_supplicant data
243 * @sec: Number of seconds after which to time out authentication
244 * @usec: Number of microseconds after which to time out authentication
245 *
246 * This function is used to schedule a timeout for the current authentication
247 * attempt.
248 */
249void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
250 int sec, int usec)
251{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700252 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
254 return;
255
256 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
257 "%d usec", sec, usec);
258 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700259 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700260 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
261}
262
263
Roshan Pius3a1667e2018-07-03 15:17:14 -0700264/*
265 * wpas_auth_timeout_restart - Restart and change timeout for authentication
266 * @wpa_s: Pointer to wpa_supplicant data
267 * @sec_diff: difference in seconds applied to original timeout value
268 */
269void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
270{
271 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
272
273 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
274 wpa_dbg(wpa_s, MSG_DEBUG,
275 "Authentication timeout restart: %d sec", new_sec);
276 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
277 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
278 wpa_s, NULL);
279 }
280}
281
282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283/**
284 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
285 * @wpa_s: Pointer to wpa_supplicant data
286 *
287 * This function is used to cancel authentication timeout scheduled with
288 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
289 * been completed.
290 */
291void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
292{
293 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
294 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800295 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700296 os_free(wpa_s->last_con_fail_realm);
297 wpa_s->last_con_fail_realm = NULL;
298 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299}
300
301
302/**
303 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
304 * @wpa_s: Pointer to wpa_supplicant data
305 *
306 * This function is used to configure EAPOL state machine based on the selected
307 * authentication mode.
308 */
309void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
310{
311#ifdef IEEE8021X_EAPOL
312 struct eapol_config eapol_conf;
313 struct wpa_ssid *ssid = wpa_s->current_ssid;
314
315#ifdef CONFIG_IBSS_RSN
316 if (ssid->mode == WPAS_MODE_IBSS &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
319 /*
320 * RSN IBSS authentication is per-STA and we can disable the
321 * per-BSSID EAPOL authentication.
322 */
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700324 eapol_sm_notify_eap_success(wpa_s->eapol, true);
325 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 return;
327 }
328#endif /* CONFIG_IBSS_RSN */
329
Hai Shalome21d4e82020-04-29 16:34:06 -0700330 eapol_sm_notify_eap_success(wpa_s->eapol, false);
331 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
334 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
335 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
336 else
337 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
338
339 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
340 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
341 eapol_conf.accept_802_1x_keys = 1;
342 eapol_conf.required_keys = 0;
343 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
344 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
345 }
346 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
347 eapol_conf.required_keys |=
348 EAPOL_REQUIRE_KEY_BROADCAST;
349 }
350
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 eapol_conf.required_keys = 0;
353 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700354 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 eapol_conf.workaround = ssid->eap_workaround;
356 eapol_conf.eap_disabled =
357 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700360 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800361
362#ifdef CONFIG_WPS
363 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
364 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
365 if (wpa_s->current_bss) {
366 struct wpabuf *ie;
367 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
368 WPS_IE_VENDOR_TYPE);
369 if (ie) {
370 if (wps_is_20(ie))
371 eapol_conf.wps |=
372 EAPOL_PEER_IS_WPS20_AP;
373 wpabuf_free(ie);
374 }
375 }
376 }
377#endif /* CONFIG_WPS */
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700380
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800381#ifdef CONFIG_MACSEC
382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
383 ieee802_1x_create_preshared_mka(wpa_s, ssid);
384 else
385 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
386#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800387#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
391/**
392 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
393 * @wpa_s: Pointer to wpa_supplicant data
394 * @ssid: Configuration data for the network
395 *
396 * This function is used to configure WPA state machine and related parameters
397 * to a mode where WPA is not enabled. This is called as part of the
398 * authentication configuration when the selected network does not use WPA.
399 */
400void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
401 struct wpa_ssid *ssid)
402{
Hai Shalomfdcde762020-04-02 11:19:20 -0700403#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406
407 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
408 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
409 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
410 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
411 else
412 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
413 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
414 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700415 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700417 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
418 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
420 wpa_s->group_cipher = WPA_CIPHER_NONE;
421 wpa_s->mgmt_group_cipher = 0;
422
Hai Shalomfdcde762020-04-02 11:19:20 -0700423#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 for (i = 0; i < NUM_WEP_KEYS; i++) {
425 if (ssid->wep_key_len[i] > 5) {
426 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
427 wpa_s->group_cipher = WPA_CIPHER_WEP104;
428 break;
429 } else if (ssid->wep_key_len[i] > 0) {
430 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
431 wpa_s->group_cipher = WPA_CIPHER_WEP40;
432 break;
433 }
434 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700435#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
440 wpa_s->pairwise_cipher);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
443 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
445 pmksa_cache_clear_current(wpa_s->wpa);
446}
447
448
Dmitry Shmidt04949592012-07-19 12:16:46 -0700449void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800450{
451 int i;
452 if (wpa_s->hw.modes == NULL)
453 return;
454
455 for (i = 0; i < wpa_s->hw.num_modes; i++) {
456 os_free(wpa_s->hw.modes[i].channels);
457 os_free(wpa_s->hw.modes[i].rates);
458 }
459
460 os_free(wpa_s->hw.modes);
461 wpa_s->hw.modes = NULL;
462}
463
464
Hai Shalomc1a21442022-02-04 13:43:00 -0800465static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
466 struct wpa_bss_tmp_disallowed *bss)
467{
468 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
469 dl_list_del(&bss->list);
470 os_free(bss);
471}
472
473
Hai Shalom74f70d42019-02-11 14:42:39 -0800474void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800475{
476 struct wpa_bss_tmp_disallowed *bss, *prev;
477
478 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800479 struct wpa_bss_tmp_disallowed, list)
480 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800481}
482
483
Paul Stewart092955c2017-02-06 09:13:09 -0800484void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
485{
486 struct fils_hlp_req *req;
487
488 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
489 list)) != NULL) {
490 dl_list_del(&req->list);
491 wpabuf_free(req->pkt);
492 os_free(req);
493 }
494}
495
496
Hai Shalomfdcde762020-04-02 11:19:20 -0700497void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
498{
499 struct wpa_supplicant *wpa_s = eloop_ctx;
500
501 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
502 return;
503 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
504 wpa_bss_flush(wpa_s);
505}
506
507
508#ifdef CONFIG_TESTING_OPTIONS
509void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
510{
511 struct driver_signal_override *dso;
512
513 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
514 struct driver_signal_override, list))) {
515 dl_list_del(&dso->list);
516 os_free(dso);
517 }
518}
519#endif /* CONFIG_TESTING_OPTIONS */
520
521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
523{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700524 int i;
525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700527 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528 scard_deinit(wpa_s->scard);
529 wpa_s->scard = NULL;
530 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
531 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
532 l2_packet_deinit(wpa_s->l2);
533 wpa_s->l2 = NULL;
534 if (wpa_s->l2_br) {
535 l2_packet_deinit(wpa_s->l2_br);
536 wpa_s->l2_br = NULL;
537 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800538#ifdef CONFIG_TESTING_OPTIONS
539 l2_packet_deinit(wpa_s->l2_test);
540 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800541 os_free(wpa_s->get_pref_freq_list_override);
542 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700543 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
544 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800545 os_free(wpa_s->extra_sae_rejected_groups);
546 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700547 wpabuf_free(wpa_s->rsne_override_eapol);
548 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800549 wpabuf_free(wpa_s->rsnxe_override_assoc);
550 wpa_s->rsnxe_override_assoc = NULL;
551 wpabuf_free(wpa_s->rsnxe_override_eapol);
552 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700553 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800554#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556 if (wpa_s->conf != NULL) {
557 struct wpa_ssid *ssid;
558 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
559 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 }
561
562 os_free(wpa_s->confname);
563 wpa_s->confname = NULL;
564
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700565 os_free(wpa_s->confanother);
566 wpa_s->confanother = NULL;
567
Hai Shalomce48b4a2018-09-05 11:41:35 -0700568 os_free(wpa_s->last_con_fail_realm);
569 wpa_s->last_con_fail_realm = NULL;
570 wpa_s->last_con_fail_realm_len = 0;
571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572 wpa_sm_set_eapol(wpa_s->wpa, NULL);
573 eapol_sm_deinit(wpa_s->eapol);
574 wpa_s->eapol = NULL;
575
576 rsn_preauth_deinit(wpa_s->wpa);
577
578#ifdef CONFIG_TDLS
579 wpa_tdls_deinit(wpa_s->wpa);
580#endif /* CONFIG_TDLS */
581
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800582 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800584 ptksa_cache_deinit(wpa_s->ptksa);
585 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700586 wpa_sm_deinit(wpa_s->wpa);
587 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800588 wpa_bssid_ignore_clear(wpa_s);
589
590#ifdef CONFIG_PASN
591 wpas_pasn_auth_stop(wpa_s);
592#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593
594 wpa_bss_deinit(wpa_s);
595
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700596 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 wpa_supplicant_cancel_scan(wpa_s);
598 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800599 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
600#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
601 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
602 wpa_s, NULL);
603#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700605 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700606 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700607
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608 wpas_wps_deinit(wpa_s);
609
610 wpabuf_free(wpa_s->pending_eapol_rx);
611 wpa_s->pending_eapol_rx = NULL;
612
613#ifdef CONFIG_IBSS_RSN
614 ibss_rsn_deinit(wpa_s->ibss_rsn);
615 wpa_s->ibss_rsn = NULL;
616#endif /* CONFIG_IBSS_RSN */
617
618 sme_deinit(wpa_s);
619
620#ifdef CONFIG_AP
621 wpa_supplicant_ap_deinit(wpa_s);
622#endif /* CONFIG_AP */
623
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800626#ifdef CONFIG_OFFCHANNEL
627 offchannel_deinit(wpa_s);
628#endif /* CONFIG_OFFCHANNEL */
629
630 wpa_supplicant_cancel_sched_scan(wpa_s);
631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700632 os_free(wpa_s->next_scan_freqs);
633 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800634
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800635 os_free(wpa_s->manual_scan_freqs);
636 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700637 os_free(wpa_s->select_network_scan_freqs);
638 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800639
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700640 os_free(wpa_s->manual_sched_scan_freqs);
641 wpa_s->manual_sched_scan_freqs = NULL;
642
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800643 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
644
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700645 /*
646 * Need to remove any pending gas-query radio work before the
647 * gas_query_deinit() call because gas_query::work has not yet been set
648 * for works that have not been started. gas_query_free() will be unable
649 * to cancel such pending radio works and once the pending gas-query
650 * radio work eventually gets removed, the deinit notification call to
651 * gas_query_start_cb() would result in dereferencing freed memory.
652 */
653 if (wpa_s->radio)
654 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800655 gas_query_deinit(wpa_s->gas);
656 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700657 gas_server_deinit(wpa_s->gas_server);
658 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800659
660 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700661
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700662 ieee802_1x_dealloc_kay_sm(wpa_s);
663
Dmitry Shmidt04949592012-07-19 12:16:46 -0700664 os_free(wpa_s->bssid_filter);
665 wpa_s->bssid_filter = NULL;
666
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800667 os_free(wpa_s->disallow_aps_bssid);
668 wpa_s->disallow_aps_bssid = NULL;
669 os_free(wpa_s->disallow_aps_ssid);
670 wpa_s->disallow_aps_ssid = NULL;
671
Dmitry Shmidt04949592012-07-19 12:16:46 -0700672 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700673#ifdef CONFIG_WNM
674 wnm_deallocate_memory(wpa_s);
675#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700676
677 ext_password_deinit(wpa_s->ext_pw);
678 wpa_s->ext_pw = NULL;
679
680 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800681 wpa_s->last_gas_resp = NULL;
682 wpabuf_free(wpa_s->prev_gas_resp);
683 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700684
685 os_free(wpa_s->last_scan_res);
686 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800687
688#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700689 if (wpa_s->drv_priv)
690 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700691 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800692#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700693
694 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
695 wpabuf_free(wpa_s->vendor_elem[i]);
696 wpa_s->vendor_elem[i] = NULL;
697 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800698
699 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800700
701 wpa_s->sched_scan_plans_num = 0;
702 os_free(wpa_s->sched_scan_plans);
703 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800704
705#ifdef CONFIG_MBO
706 wpa_s->non_pref_chan_num = 0;
707 os_free(wpa_s->non_pref_chan);
708 wpa_s->non_pref_chan = NULL;
709#endif /* CONFIG_MBO */
710
711 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700712
713 wpabuf_free(wpa_s->lci);
714 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800715 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800716
717#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
718#ifdef CONFIG_MESH
719 {
720 struct external_pmksa_cache *entry;
721
722 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
723 struct external_pmksa_cache,
724 list)) != NULL) {
725 dl_list_del(&entry->list);
726 os_free(entry->pmksa_cache);
727 os_free(entry);
728 }
729 }
730#endif /* CONFIG_MESH */
731#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
732
733 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800734
735 wpabuf_free(wpa_s->ric_ies);
736 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700737
738#ifdef CONFIG_DPP
739 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700740 dpp_global_deinit(wpa_s->dpp);
741 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700742#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800743
744#ifdef CONFIG_PASN
745 wpas_pasn_auth_stop(wpa_s);
746#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800747 wpas_scs_deinit(wpa_s);
748 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749}
750
751
752/**
753 * wpa_clear_keys - Clear keys configured for the driver
754 * @wpa_s: Pointer to wpa_supplicant data
755 * @addr: Previously used BSSID or %NULL if not available
756 *
757 * This function clears the encryption keys that has been previously configured
758 * for the driver.
759 */
760void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
761{
Hai Shalomc3565922019-10-28 11:58:20 -0700762 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763
764 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 for (i = 0; i < max; i++) {
766 if (wpa_s->keys_cleared & BIT(i))
767 continue;
768 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700769 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800770 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700771 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
772 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800773 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700774 if (!(wpa_s->keys_cleared & BIT(0)))
775 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
776 0, NULL, 0, KEY_FLAG_PAIRWISE);
777 if (!(wpa_s->keys_cleared & BIT(15)))
778 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
779 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700780 /* MLME-SETPROTECTION.request(None) */
781 wpa_drv_mlme_setprotection(
782 wpa_s, addr,
783 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
784 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
785 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800786 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787}
788
789
790/**
791 * wpa_supplicant_state_txt - Get the connection state name as a text string
792 * @state: State (wpa_state; WPA_*)
793 * Returns: The state name as a printable text string
794 */
795const char * wpa_supplicant_state_txt(enum wpa_states state)
796{
797 switch (state) {
798 case WPA_DISCONNECTED:
799 return "DISCONNECTED";
800 case WPA_INACTIVE:
801 return "INACTIVE";
802 case WPA_INTERFACE_DISABLED:
803 return "INTERFACE_DISABLED";
804 case WPA_SCANNING:
805 return "SCANNING";
806 case WPA_AUTHENTICATING:
807 return "AUTHENTICATING";
808 case WPA_ASSOCIATING:
809 return "ASSOCIATING";
810 case WPA_ASSOCIATED:
811 return "ASSOCIATED";
812 case WPA_4WAY_HANDSHAKE:
813 return "4WAY_HANDSHAKE";
814 case WPA_GROUP_HANDSHAKE:
815 return "GROUP_HANDSHAKE";
816 case WPA_COMPLETED:
817 return "COMPLETED";
818 default:
819 return "UNKNOWN";
820 }
821}
822
823
824#ifdef CONFIG_BGSCAN
825
Hai Shalom899fcc72020-10-19 14:38:18 -0700826static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
827{
828 if (wpa_s->bgscan_ssid) {
829 bgscan_deinit(wpa_s);
830 wpa_s->bgscan_ssid = NULL;
831 }
832}
833
834
835/**
836 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
837 * @wpa_s: Pointer to the wpa_supplicant data
838 *
839 * Stop, start, or reconfigure the scan parameters depending on the method.
840 */
841void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700842{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800843 const char *name;
844
845 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
846 name = wpa_s->current_ssid->bgscan;
847 else
848 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700849 if (!name || name[0] == '\0') {
850 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800851 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700852 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800853 if (wpas_driver_bss_selection(wpa_s))
854 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800855#ifdef CONFIG_P2P
856 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
857 return;
858#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859
860 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800861 if (wpa_s->current_ssid) {
862 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
864 "bgscan");
865 /*
866 * Live without bgscan; it is only used as a roaming
867 * optimization, so the initial connection is not
868 * affected.
869 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700870 } else {
871 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700873 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
874 0);
875 if (scan_res) {
876 bgscan_notify_scan(wpa_s, scan_res);
877 wpa_scan_results_free(scan_res);
878 }
879 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 } else
881 wpa_s->bgscan_ssid = NULL;
882}
883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884#endif /* CONFIG_BGSCAN */
885
886
Dmitry Shmidt04949592012-07-19 12:16:46 -0700887static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
888{
889 if (autoscan_init(wpa_s, 0))
890 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
891}
892
893
894static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
895{
896 autoscan_deinit(wpa_s);
897}
898
899
900void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
901{
902 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
903 wpa_s->wpa_state == WPA_SCANNING) {
904 autoscan_deinit(wpa_s);
905 wpa_supplicant_start_autoscan(wpa_s);
906 }
907}
908
909
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700910/**
911 * wpa_supplicant_set_state - Set current connection state
912 * @wpa_s: Pointer to wpa_supplicant data
913 * @state: The new connection state
914 *
915 * This function is called whenever the connection state changes, e.g.,
916 * association is completed for WPA/WPA2 4-Way Handshake is started.
917 */
918void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
919 enum wpa_states state)
920{
921 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700922#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700923 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700924#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925
926 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
927 wpa_supplicant_state_txt(wpa_s->wpa_state),
928 wpa_supplicant_state_txt(state));
929
Hai Shalom74f70d42019-02-11 14:42:39 -0800930 if (state == WPA_COMPLETED &&
931 os_reltime_initialized(&wpa_s->roam_start)) {
932 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
933 wpa_s->roam_start.sec = 0;
934 wpa_s->roam_start.usec = 0;
935 wpas_notify_auth_changed(wpa_s);
936 wpas_notify_roam_time(wpa_s);
937 wpas_notify_roam_complete(wpa_s);
938 } else if (state == WPA_DISCONNECTED &&
939 os_reltime_initialized(&wpa_s->roam_start)) {
940 wpa_s->roam_start.sec = 0;
941 wpa_s->roam_start.usec = 0;
942 wpa_s->roam_time.sec = 0;
943 wpa_s->roam_time.usec = 0;
944 wpas_notify_roam_complete(wpa_s);
945 }
946
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800947 if (state == WPA_INTERFACE_DISABLED) {
948 /* Assure normal scan when interface is restored */
949 wpa_s->normal_scans = 0;
950 }
951
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700952 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800953 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700954 /* Reinitialize normal_scan counter */
955 wpa_s->normal_scans = 0;
956 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800957
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700958#ifdef CONFIG_P2P
959 /*
960 * P2PS client has to reply to Probe Request frames received on the
961 * group operating channel. Enable Probe Request frame reporting for
962 * P2P connected client in case p2p_cli_probe configuration property is
963 * set to 1.
964 */
965 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
966 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
967 wpa_s->current_ssid->p2p_group) {
968 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
969 wpa_dbg(wpa_s, MSG_DEBUG,
970 "P2P: Enable CLI Probe Request RX reporting");
971 wpa_s->p2p_cli_probe =
972 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
973 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
974 wpa_dbg(wpa_s, MSG_DEBUG,
975 "P2P: Disable CLI Probe Request RX reporting");
976 wpa_s->p2p_cli_probe = 0;
977 wpa_drv_probe_req_report(wpa_s, 0);
978 }
979 }
980#endif /* CONFIG_P2P */
981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982 if (state != WPA_SCANNING)
983 wpa_supplicant_notify_scanning(wpa_s, 0);
984
985 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700987 int fils_hlp_sent = 0;
988
989#ifdef CONFIG_SME
990 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
991 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
992 fils_hlp_sent = 1;
993#endif /* CONFIG_SME */
994 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
995 wpa_auth_alg_fils(wpa_s->auth_alg))
996 fils_hlp_sent = 1;
997
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700998#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001000 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001001 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001003 ssid && ssid->id_str ? ssid->id_str : "",
1004 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001006 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001007 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_drv_set_operstate(wpa_s, 1);
1010#ifndef IEEE8021X_EAPOL
1011 wpa_drv_set_supp_port(wpa_s, 1);
1012#endif /* IEEE8021X_EAPOL */
1013 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001014 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001016
1017 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018
1019#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1020 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001021 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001022#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001023#ifdef CONFIG_OWE
1024 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1025 wpas_update_owe_connect_params(wpa_s);
1026#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001027#ifdef CONFIG_HS20
1028 hs20_configure_frame_filters(wpa_s);
1029#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1031 state == WPA_ASSOCIATED) {
1032 wpa_s->new_connection = 1;
1033 wpa_drv_set_operstate(wpa_s, 0);
1034#ifndef IEEE8021X_EAPOL
1035 wpa_drv_set_supp_port(wpa_s, 0);
1036#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001037 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 }
1039 wpa_s->wpa_state = state;
1040
1041#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001042 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1043 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001044 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 wpa_supplicant_stop_bgscan(wpa_s);
1046#endif /* CONFIG_BGSCAN */
1047
Hai Shalom5f92bc92019-04-18 11:54:11 -07001048 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049 wpa_supplicant_stop_autoscan(wpa_s);
1050
1051 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1052 wpa_supplicant_start_autoscan(wpa_s);
1053
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001054 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1055 wmm_ac_notify_disassoc(wpa_s);
1056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 if (wpa_s->wpa_state != old_state) {
1058 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1059
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001060 /*
1061 * Notify the P2P Device interface about a state change in one
1062 * of the interfaces.
1063 */
1064 wpas_p2p_indicate_state_change(wpa_s);
1065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 if (wpa_s->wpa_state == WPA_COMPLETED ||
1067 old_state == WPA_COMPLETED)
1068 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001069#ifdef CONFIG_DPP2
1070 if (wpa_s->wpa_state == WPA_COMPLETED)
1071 wpas_dpp_connected(wpa_s);
1072#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073 }
Hai Shalomc3565922019-10-28 11:58:20 -07001074#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1075 if (update_fils_connect_params)
1076 wpas_update_fils_connect_params(wpa_s);
1077#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078}
1079
1080
1081void wpa_supplicant_terminate_proc(struct wpa_global *global)
1082{
1083 int pending = 0;
1084#ifdef CONFIG_WPS
1085 struct wpa_supplicant *wpa_s = global->ifaces;
1086 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001088 if (wpas_wps_terminate_pending(wpa_s) == 1)
1089 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001090#ifdef CONFIG_P2P
1091 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1092 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1093 wpas_p2p_disconnect(wpa_s);
1094#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001095 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 }
1097#endif /* CONFIG_WPS */
1098 if (pending)
1099 return;
1100 eloop_terminate();
1101}
1102
1103
1104static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1105{
1106 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107 wpa_supplicant_terminate_proc(global);
1108}
1109
1110
1111void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1112{
1113 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001114 enum wpa_states new_state;
1115
1116 if (old_state == WPA_SCANNING)
1117 new_state = WPA_SCANNING;
1118 else
1119 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120
1121 wpa_s->pairwise_cipher = 0;
1122 wpa_s->group_cipher = 0;
1123 wpa_s->mgmt_group_cipher = 0;
1124 wpa_s->key_mgmt = 0;
1125 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001126 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127
1128 if (wpa_s->wpa_state != old_state)
1129 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1130}
1131
1132
1133/**
1134 * wpa_supplicant_reload_configuration - Reload configuration data
1135 * @wpa_s: Pointer to wpa_supplicant data
1136 * Returns: 0 on success or -1 if configuration parsing failed
1137 *
1138 * This function can be used to request that the configuration data is reloaded
1139 * (e.g., after configuration file change). This function is reloading
1140 * configuration only for one interface, so this may need to be called multiple
1141 * times if %wpa_supplicant is controlling multiple interfaces and all
1142 * interfaces need reconfiguration.
1143 */
1144int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1145{
1146 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001147 int reconf_ctrl;
1148 int old_ap_scan;
1149
1150 if (wpa_s->confname == NULL)
1151 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001152 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001153 if (conf == NULL) {
1154 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1155 "file '%s' - exiting", wpa_s->confname);
1156 return -1;
1157 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001158 if (wpa_s->confanother &&
1159 !wpa_config_read(wpa_s->confanother, conf)) {
1160 wpa_msg(wpa_s, MSG_ERROR,
1161 "Failed to parse the configuration file '%s' - exiting",
1162 wpa_s->confanother);
1163 return -1;
1164 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 conf->changed_parameters = (unsigned int) -1;
1167
1168 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1169 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1170 os_strcmp(conf->ctrl_interface,
1171 wpa_s->conf->ctrl_interface) != 0);
1172
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001173 if (reconf_ctrl) {
1174 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175 wpa_s->ctrl_iface = NULL;
1176 }
1177
1178 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001179 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001180 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1181 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001182 wpa_supplicant_deauthenticate(wpa_s,
1183 WLAN_REASON_DEAUTH_LEAVING);
1184 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185
1186 /*
1187 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001188 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001190 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1191 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1192 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 /*
1194 * Clear forced success to clear EAP state for next
1195 * authentication.
1196 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001197 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 }
1199 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1200 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001201 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1203 rsn_preauth_deinit(wpa_s->wpa);
1204
1205 old_ap_scan = wpa_s->conf->ap_scan;
1206 wpa_config_free(wpa_s->conf);
1207 wpa_s->conf = conf;
1208 if (old_ap_scan != wpa_s->conf->ap_scan)
1209 wpas_notify_ap_scan_changed(wpa_s);
1210
1211 if (reconf_ctrl)
1212 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1213
1214 wpa_supplicant_update_config(wpa_s);
1215
1216 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001217 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218 wpa_s->reassociate = 1;
1219 wpa_supplicant_req_scan(wpa_s, 0, 0);
1220 }
Hai Shalom60840252021-02-19 19:02:11 -08001221 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1223 return 0;
1224}
1225
1226
1227static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1228{
1229 struct wpa_global *global = signal_ctx;
1230 struct wpa_supplicant *wpa_s;
1231 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1232 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1233 sig);
1234 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1235 wpa_supplicant_terminate_proc(global);
1236 }
1237 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001238
1239 if (wpa_debug_reopen_file() < 0) {
1240 /* Ignore errors since we cannot really do much to fix this */
1241 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1242 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001243}
1244
1245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1247 struct wpa_ssid *ssid,
1248 struct wpa_ie_data *ie)
1249{
1250 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1251 if (ret) {
1252 if (ret == -2) {
1253 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1254 "from association info");
1255 }
1256 return -1;
1257 }
1258
1259 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1260 "cipher suites");
1261 if (!(ie->group_cipher & ssid->group_cipher)) {
1262 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1263 "cipher 0x%x (mask 0x%x) - reject",
1264 ie->group_cipher, ssid->group_cipher);
1265 return -1;
1266 }
1267 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1268 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1269 "cipher 0x%x (mask 0x%x) - reject",
1270 ie->pairwise_cipher, ssid->pairwise_cipher);
1271 return -1;
1272 }
1273 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1275 "management 0x%x (mask 0x%x) - reject",
1276 ie->key_mgmt, ssid->key_mgmt);
1277 return -1;
1278 }
1279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001281 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001282 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1283 "that does not support management frame protection - "
1284 "reject");
1285 return -1;
1286 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287
1288 return 0;
1289}
1290
1291
Hai Shalom021b0b52019-04-10 11:17:58 -07001292static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1293 int freq)
1294{
1295 if (!ie->has_group)
1296 ie->group_cipher = wpa_default_rsn_cipher(freq);
1297 if (!ie->has_pairwise)
1298 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1299 return (ie->group_cipher & ssid->group_cipher) &&
1300 (ie->pairwise_cipher & ssid->pairwise_cipher);
1301}
1302
1303
Hai Shalomc1a21442022-02-04 13:43:00 -08001304void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1305 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1306{
1307 int sel;
1308
1309 sel = ie->mgmt_group_cipher;
1310 if (ssid->group_mgmt_cipher)
1311 sel &= ssid->group_mgmt_cipher;
1312 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1313 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1314 sel = 0;
1315 wpa_dbg(wpa_s, MSG_DEBUG,
1316 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1317 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1318 if (sel & WPA_CIPHER_AES_128_CMAC) {
1319 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1320 wpa_dbg(wpa_s, MSG_DEBUG,
1321 "WPA: using MGMT group cipher AES-128-CMAC");
1322 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1323 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1324 wpa_dbg(wpa_s, MSG_DEBUG,
1325 "WPA: using MGMT group cipher BIP-GMAC-128");
1326 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1327 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1328 wpa_dbg(wpa_s, MSG_DEBUG,
1329 "WPA: using MGMT group cipher BIP-GMAC-256");
1330 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1331 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: using MGMT group cipher BIP-CMAC-256");
1334 } else {
1335 wpa_s->mgmt_group_cipher = 0;
1336 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1337 }
1338 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1339 wpa_s->mgmt_group_cipher);
1340 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1341 wpas_get_ssid_pmf(wpa_s, ssid));
1342}
1343
1344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345/**
1346 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1347 * @wpa_s: Pointer to wpa_supplicant data
1348 * @bss: Scan results for the selected BSS, or %NULL if not available
1349 * @ssid: Configuration data for the selected network
1350 * @wpa_ie: Buffer for the WPA/RSN IE
1351 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1352 * used buffer length in case the functions returns success.
1353 * Returns: 0 on success or -1 on failure
1354 *
1355 * This function is used to configure authentication and encryption parameters
1356 * based on the network configuration and scan result for the selected BSS (if
1357 * available).
1358 */
1359int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1360 struct wpa_bss *bss, struct wpa_ssid *ssid,
1361 u8 *wpa_ie, size_t *wpa_ie_len)
1362{
1363 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001364 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001365 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366
1367 if (bss) {
1368 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1369 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001370 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001371 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001372 } else {
1373 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1374 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375
1376 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1377 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001378 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 (ie.key_mgmt & ssid->key_mgmt)) {
1380 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1381 proto = WPA_PROTO_RSN;
1382 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001383 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384 (ie.group_cipher & ssid->group_cipher) &&
1385 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1386 (ie.key_mgmt & ssid->key_mgmt)) {
1387 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1388 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001389#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001390 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1391 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1392 (ie.group_cipher & ssid->group_cipher) &&
1393 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1394 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001395 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001396 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1398 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1399 (ie.group_cipher & ssid->group_cipher) &&
1400 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1401 (ie.key_mgmt & ssid->key_mgmt)) {
1402 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1403 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001404#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 } else if (bss) {
1406 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001407 wpa_dbg(wpa_s, MSG_DEBUG,
1408 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1409 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1410 ssid->key_mgmt);
1411 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1412 MAC2STR(bss->bssid),
1413 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1414 bss_wpa ? " WPA" : "",
1415 bss_rsn ? " RSN" : "",
1416 bss_osen ? " OSEN" : "");
1417 if (bss_rsn) {
1418 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1419 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1420 wpa_dbg(wpa_s, MSG_DEBUG,
1421 "Could not parse RSN element");
1422 } else {
1423 wpa_dbg(wpa_s, MSG_DEBUG,
1424 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1425 ie.pairwise_cipher, ie.group_cipher,
1426 ie.key_mgmt);
1427 }
1428 }
1429 if (bss_wpa) {
1430 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1431 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1432 wpa_dbg(wpa_s, MSG_DEBUG,
1433 "Could not parse WPA element");
1434 } else {
1435 wpa_dbg(wpa_s, MSG_DEBUG,
1436 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1437 ie.pairwise_cipher, ie.group_cipher,
1438 ie.key_mgmt);
1439 }
1440 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441 return -1;
1442 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001443 if (ssid->proto & WPA_PROTO_OSEN)
1444 proto = WPA_PROTO_OSEN;
1445 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 proto = WPA_PROTO_RSN;
1447 else
1448 proto = WPA_PROTO_WPA;
1449 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1450 os_memset(&ie, 0, sizeof(ie));
1451 ie.group_cipher = ssid->group_cipher;
1452 ie.pairwise_cipher = ssid->pairwise_cipher;
1453 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001454 ie.mgmt_group_cipher = 0;
1455 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1456 if (ssid->group_mgmt_cipher &
1457 WPA_CIPHER_BIP_GMAC_256)
1458 ie.mgmt_group_cipher =
1459 WPA_CIPHER_BIP_GMAC_256;
1460 else if (ssid->group_mgmt_cipher &
1461 WPA_CIPHER_BIP_CMAC_256)
1462 ie.mgmt_group_cipher =
1463 WPA_CIPHER_BIP_CMAC_256;
1464 else if (ssid->group_mgmt_cipher &
1465 WPA_CIPHER_BIP_GMAC_128)
1466 ie.mgmt_group_cipher =
1467 WPA_CIPHER_BIP_GMAC_128;
1468 else
1469 ie.mgmt_group_cipher =
1470 WPA_CIPHER_AES_128_CMAC;
1471 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001472#ifdef CONFIG_OWE
1473 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1474 !ssid->owe_only &&
1475 !bss_wpa && !bss_rsn && !bss_osen) {
1476 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1477 wpa_s->wpa_proto = 0;
1478 *wpa_ie_len = 0;
1479 return 0;
1480 }
1481#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1483 "based on configuration");
1484 } else
1485 proto = ie.proto;
1486 }
1487
1488 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1489 "pairwise %d key_mgmt %d proto %d",
1490 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 if (ssid->ieee80211w) {
1492 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1493 ie.mgmt_group_cipher);
1494 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001496 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1498 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001499 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500
1501 if (bss || !wpa_s->ap_ies_from_associnfo) {
1502 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1503 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1504 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001505 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1506 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1507 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 return -1;
1509 }
1510
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001511#ifdef CONFIG_NO_WPA
1512 wpa_s->group_cipher = WPA_CIPHER_NONE;
1513 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1514#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001516 wpa_dbg(wpa_s, MSG_DEBUG,
1517 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1518 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001519 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1520 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1522 "cipher");
1523 return -1;
1524 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001525 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1526 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001527
1528 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001529 wpa_dbg(wpa_s, MSG_DEBUG,
1530 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1531 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001532 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1533 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1535 "cipher");
1536 return -1;
1537 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001538 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1539 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001540#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541
1542 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001543#ifdef CONFIG_SAE
1544 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1545 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1546#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001547#ifdef CONFIG_IEEE80211R
1548 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1549 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1550 sel &= ~WPA_KEY_MGMT_FT;
1551#endif /* CONFIG_IEEE80211R */
1552 wpa_dbg(wpa_s, MSG_DEBUG,
1553 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1554 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001556#ifdef CONFIG_IEEE80211R
1557#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001558 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1559 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001560 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1561 wpa_dbg(wpa_s, MSG_DEBUG,
1562 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001563 if (!ssid->ft_eap_pmksa_caching &&
1564 pmksa_cache_get_current(wpa_s->wpa)) {
1565 /* PMKSA caching with FT may have interoperability
1566 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001567 wpa_dbg(wpa_s, MSG_DEBUG,
1568 "WPA: Disable PMKSA caching for FT/802.1X connection");
1569 pmksa_cache_clear_current(wpa_s->wpa);
1570 }
1571#endif /* CONFIG_SHA384 */
1572#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001573#ifdef CONFIG_SUITEB192
1574 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1575 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1576 wpa_dbg(wpa_s, MSG_DEBUG,
1577 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1578#endif /* CONFIG_SUITEB192 */
1579#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001580 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1581 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1582 wpa_dbg(wpa_s, MSG_DEBUG,
1583 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001584#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001585#ifdef CONFIG_FILS
1586#ifdef CONFIG_IEEE80211R
1587 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1588 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1589 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1590 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1591 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1592 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1593#endif /* CONFIG_IEEE80211R */
1594 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1595 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1596 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1597 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1598 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1599 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1600#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001602 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1603 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1605 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001606 if (!ssid->ft_eap_pmksa_caching &&
1607 pmksa_cache_get_current(wpa_s->wpa)) {
1608 /* PMKSA caching with FT may have interoperability
1609 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001610 wpa_dbg(wpa_s, MSG_DEBUG,
1611 "WPA: Disable PMKSA caching for FT/802.1X connection");
1612 pmksa_cache_clear_current(wpa_s->wpa);
1613 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001614#endif /* CONFIG_IEEE80211R */
1615#ifdef CONFIG_DPP
1616 } else if (sel & WPA_KEY_MGMT_DPP) {
1617 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1618 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1619#endif /* CONFIG_DPP */
1620#ifdef CONFIG_SAE
1621 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1622 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1623 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1624 } else if (sel & WPA_KEY_MGMT_SAE) {
1625 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1626 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1627#endif /* CONFIG_SAE */
1628#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1630 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1631 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1632#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1634 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1635 wpa_dbg(wpa_s, MSG_DEBUG,
1636 "WPA: using KEY_MGMT 802.1X with SHA256");
1637 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1638 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1639 wpa_dbg(wpa_s, MSG_DEBUG,
1640 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1642 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1643 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1644 } else if (sel & WPA_KEY_MGMT_PSK) {
1645 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1646 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1647 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1648 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1649 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001650#ifdef CONFIG_HS20
1651 } else if (sel & WPA_KEY_MGMT_OSEN) {
1652 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1653 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1654#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001655#ifdef CONFIG_OWE
1656 } else if (sel & WPA_KEY_MGMT_OWE) {
1657 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1658 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1659#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001660 } else {
1661 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1662 "authenticated key management type");
1663 return -1;
1664 }
1665
1666 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1668 wpa_s->pairwise_cipher);
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1670
Hai Shalomc3565922019-10-28 11:58:20 -07001671 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1672 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1673 wpa_msg(wpa_s, MSG_INFO,
1674 "RSN: Management frame protection required but the selected AP does not enable it");
1675 return -1;
1676 }
1677
Hai Shalomc1a21442022-02-04 13:43:00 -08001678 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001679#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001680 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1681 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1682 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001683#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001684 sae_pwe = wpa_s->conf->sae_pwe;
1685 if (ssid->sae_password_id && sae_pwe != 3)
1686 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001687 if (bss && is_6ghz_freq(bss->freq)) {
1688 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1689 sae_pwe = 1;
1690 }
1691#ifdef CONFIG_TESTING_OPTIONS
1692 if (wpa_s->force_hunting_and_pecking_pwe) {
1693 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1694 sae_pwe = 0;
1695 }
1696#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001697 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001698#ifdef CONFIG_SAE_PK
1699 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1700 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1701 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1702 ((ssid->sae_password &&
1703 sae_pk_valid_password(ssid->sae_password)) ||
1704 (!ssid->sae_password && ssid->passphrase &&
1705 sae_pk_valid_password(ssid->passphrase))));
1706#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001707#ifdef CONFIG_TESTING_OPTIONS
1708 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1709 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001710 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1711 wpa_s->oci_freq_override_eapol);
1712 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1713 wpa_s->oci_freq_override_eapol_g2);
1714 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1715 wpa_s->oci_freq_override_ft_assoc);
1716 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1717 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001718 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1719 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001720#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001721
1722 /* Extended Key ID is only supported in infrastructure BSS so far */
1723 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1724 (ssid->proto & WPA_PROTO_RSN) &&
1725 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1726 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1727 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1728 int use_ext_key_id = 0;
1729
1730 wpa_msg(wpa_s, MSG_DEBUG,
1731 "WPA: Enable Extended Key ID support");
1732 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1733 wpa_s->conf->extended_key_id);
1734 if (bss_rsn &&
1735 wpa_s->conf->extended_key_id &&
1736 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1737 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1738 use_ext_key_id = 1;
1739 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1740 use_ext_key_id);
1741 } else {
1742 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1743 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1744 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745
1746 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1747 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1748 return -1;
1749 }
1750
Hai Shalomc3565922019-10-28 11:58:20 -07001751 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1752 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1753 &wpa_s->rsnxe_len)) {
1754 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1755 return -1;
1756 }
1757
Hai Shalom021b0b52019-04-10 11:17:58 -07001758 if (0) {
1759#ifdef CONFIG_DPP
1760 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1761 /* Use PMK from DPP network introduction (PMKSA entry) */
1762 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001763#ifdef CONFIG_DPP2
1764 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1765#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001766#endif /* CONFIG_DPP */
1767 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001768 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001769 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001770
Roshan Pius3a1667e2018-07-03 15:17:14 -07001771 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1772 WPA_KEY_MGMT_FT_PSK |
1773 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1774
1775 if (ssid->psk_set && !sae_only) {
1776 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1777 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001778 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1779 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001780 psk_set = 1;
1781 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001782
Roshan Pius3a1667e2018-07-03 15:17:14 -07001783 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1784 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001785 psk_set = 1;
1786
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001787#ifndef CONFIG_NO_PBKDF2
1788 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001789 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001790 u8 psk[PMK_LEN];
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001791
1792 if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
1793 bss->ssid_len,
1794 4096, psk, PMK_LEN) != 0) {
1795 wpa_msg(wpa_s, MSG_WARNING,
1796 "Error in pbkdf2_sha1()");
1797 return -1;
1798 }
1799 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001800 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001801 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001802 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001803 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001804 }
1805#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001806#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001807 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1809 ssid->ext_psk);
1810 char pw_str[64 + 1];
1811 u8 psk[PMK_LEN];
1812
1813 if (pw == NULL) {
1814 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1815 "found from external storage");
1816 return -1;
1817 }
1818
1819 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1820 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1821 "PSK length %d in external storage",
1822 (int) wpabuf_len(pw));
1823 ext_password_free(pw);
1824 return -1;
1825 }
1826
1827 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1828 pw_str[wpabuf_len(pw)] = '\0';
1829
1830#ifndef CONFIG_NO_PBKDF2
1831 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1832 {
Sunil Ravi59fa4b42022-05-02 22:54:18 -07001833 if (pbkdf2_sha1(pw_str, bss->ssid,
1834 bss->ssid_len,
1835 4096, psk, PMK_LEN) != 0) {
1836 wpa_msg(wpa_s, MSG_WARNING,
1837 "Error in pbkdf2_sha1()");
1838 ext_password_free(pw);
1839 return -1;
1840 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001841 os_memset(pw_str, 0, sizeof(pw_str));
1842 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1843 "external passphrase)",
1844 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001845 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1846 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001847 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001848 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001849 } else
1850#endif /* CONFIG_NO_PBKDF2 */
1851 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1852 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1853 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1854 "Invalid PSK hex string");
1855 os_memset(pw_str, 0, sizeof(pw_str));
1856 ext_password_free(pw);
1857 return -1;
1858 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001859 wpa_hexdump_key(MSG_MSGDUMP,
1860 "PSK (from external PSK)",
1861 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001862 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1863 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001864 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001865 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001866 } else {
1867 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1868 "PSK available");
1869 os_memset(pw_str, 0, sizeof(pw_str));
1870 ext_password_free(pw);
1871 return -1;
1872 }
1873
1874 os_memset(pw_str, 0, sizeof(pw_str));
1875 ext_password_free(pw);
1876 }
1877#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001878
1879 if (!psk_set) {
1880 wpa_msg(wpa_s, MSG_INFO,
1881 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001883 return -1;
1884 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885#ifdef CONFIG_OWE
1886 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1887 /* OWE Diffie-Hellman exchange in (Re)Association
1888 * Request/Response frames set the PMK, so do not override it
1889 * here. */
1890#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001891 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1893
Hai Shalomfdcde762020-04-02 11:19:20 -07001894 if (ssid->mode != WPAS_MODE_IBSS &&
1895 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1896 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1897 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1898 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1899 wpa_msg(wpa_s, MSG_INFO,
1900 "Disable PTK0 rekey support - replaced with reconnect");
1901 wpa_s->deny_ptk0_rekey = 1;
1902 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1903 } else {
1904 wpa_s->deny_ptk0_rekey = 0;
1905 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1906 }
1907
Vinayak Yadawad14709082022-03-17 14:25:11 +05301908#ifdef CONFIG_DRIVER_NL80211_BRCM
1909 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09001910 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
1911 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
1912 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05301913 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1914 wpa_dbg(wpa_s, MSG_INFO,
1915 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1916 }
1917#endif /* CONFIG_DRIVER_NL80211_BRCM */
1918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001919 return 0;
1920}
1921
1922
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001923static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1924{
Hai Shalomc1a21442022-02-04 13:43:00 -08001925 bool scs = true, mscs = true;
1926
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001927 *pos = 0x00;
1928
1929 switch (idx) {
1930 case 0: /* Bits 0-7 */
1931 break;
1932 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001933 if (wpa_s->conf->coloc_intf_reporting) {
1934 /* Bit 13 - Collocated Interference Reporting */
1935 *pos |= 0x20;
1936 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001937 break;
1938 case 2: /* Bits 16-23 */
1939#ifdef CONFIG_WNM
1940 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001941 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001942 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001943#endif /* CONFIG_WNM */
1944 break;
1945 case 3: /* Bits 24-31 */
1946#ifdef CONFIG_WNM
1947 *pos |= 0x02; /* Bit 25 - SSID List */
1948#endif /* CONFIG_WNM */
1949#ifdef CONFIG_INTERWORKING
1950 if (wpa_s->conf->interworking)
1951 *pos |= 0x80; /* Bit 31 - Interworking */
1952#endif /* CONFIG_INTERWORKING */
1953 break;
1954 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001955#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001956 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001957 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001958#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001959 break;
1960 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001961#ifdef CONFIG_HS20
1962 if (wpa_s->conf->hs20)
1963 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1964#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001965#ifdef CONFIG_MBO
1966 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1967#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001968 break;
1969 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001970#ifdef CONFIG_TESTING_OPTIONS
1971 if (wpa_s->disable_scs_support)
1972 scs = false;
1973#endif /* CONFIG_TESTING_OPTIONS */
1974 if (scs)
1975 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001976 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001977 case 7: /* Bits 56-63 */
1978 break;
1979 case 8: /* Bits 64-71 */
1980 if (wpa_s->conf->ftm_responder)
1981 *pos |= 0x40; /* Bit 70 - FTM responder */
1982 if (wpa_s->conf->ftm_initiator)
1983 *pos |= 0x80; /* Bit 71 - FTM initiator */
1984 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001985 case 9: /* Bits 72-79 */
1986#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001987 if (!wpa_s->disable_fils)
1988 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001989#endif /* CONFIG_FILS */
1990 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001991 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001992#ifdef CONFIG_TESTING_OPTIONS
1993 if (wpa_s->disable_mscs_support)
1994 mscs = false;
1995#endif /* CONFIG_TESTING_OPTIONS */
1996 if (mscs)
1997 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001998 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001999 }
2000}
2001
2002
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002003int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002004{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002005 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002006 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002007
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002008 if (len < wpa_s->extended_capa_len)
2009 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002010 if (buflen < (size_t) len + 2) {
2011 wpa_printf(MSG_INFO,
2012 "Not enough room for building extended capabilities element");
2013 return -1;
2014 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002015
2016 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002017 *pos++ = len;
2018 for (i = 0; i < len; i++, pos++) {
2019 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002020
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002021 if (i < wpa_s->extended_capa_len) {
2022 *pos &= ~wpa_s->extended_capa_mask[i];
2023 *pos |= wpa_s->extended_capa[i];
2024 }
2025 }
2026
2027 while (len > 0 && buf[1 + len] == 0) {
2028 len--;
2029 buf[1] = len;
2030 }
2031 if (len == 0)
2032 return 0;
2033
2034 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002035}
2036
2037
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002038static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2039 struct wpa_bss *test_bss)
2040{
2041 struct wpa_bss *bss;
2042
2043 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2044 if (bss == test_bss)
2045 return 1;
2046 }
2047
2048 return 0;
2049}
2050
2051
2052static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2053 struct wpa_ssid *test_ssid)
2054{
2055 struct wpa_ssid *ssid;
2056
2057 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2058 if (ssid == test_ssid)
2059 return 1;
2060 }
2061
2062 return 0;
2063}
2064
2065
2066int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2067 struct wpa_ssid *test_ssid)
2068{
2069 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2070 return 0;
2071
2072 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2073}
2074
2075
2076void wpas_connect_work_free(struct wpa_connect_work *cwork)
2077{
2078 if (cwork == NULL)
2079 return;
2080 os_free(cwork);
2081}
2082
2083
2084void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2085{
2086 struct wpa_connect_work *cwork;
2087 struct wpa_radio_work *work = wpa_s->connect_work;
2088
2089 if (!work)
2090 return;
2091
2092 wpa_s->connect_work = NULL;
2093 cwork = work->ctx;
2094 work->ctx = NULL;
2095 wpas_connect_work_free(cwork);
2096 radio_work_done(work);
2097}
2098
2099
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002100int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2101{
2102 struct os_reltime now;
2103 u8 addr[ETH_ALEN];
2104
2105 os_get_reltime(&now);
2106 if (wpa_s->last_mac_addr_style == style &&
2107 wpa_s->last_mac_addr_change.sec != 0 &&
2108 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2109 wpa_s->conf->rand_addr_lifetime)) {
2110 wpa_msg(wpa_s, MSG_DEBUG,
2111 "Previously selected random MAC address has not yet expired");
2112 return 0;
2113 }
2114
2115 switch (style) {
2116 case 1:
2117 if (random_mac_addr(addr) < 0)
2118 return -1;
2119 break;
2120 case 2:
2121 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2122 if (random_mac_addr_keep_oui(addr) < 0)
2123 return -1;
2124 break;
2125 default:
2126 return -1;
2127 }
2128
2129 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2130 wpa_msg(wpa_s, MSG_INFO,
2131 "Failed to set random MAC address");
2132 return -1;
2133 }
2134
2135 os_get_reltime(&wpa_s->last_mac_addr_change);
2136 wpa_s->mac_addr_changed = 1;
2137 wpa_s->last_mac_addr_style = style;
2138
2139 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2140 wpa_msg(wpa_s, MSG_INFO,
2141 "Could not update MAC address information");
2142 return -1;
2143 }
2144
2145 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2146 MAC2STR(addr));
2147
2148 return 0;
2149}
2150
2151
2152int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2153{
2154 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2155 !wpa_s->conf->preassoc_mac_addr)
2156 return 0;
2157
2158 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2159}
2160
2161
Hai Shalomc3565922019-10-28 11:58:20 -07002162static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2163{
2164#ifdef CONFIG_SAE
2165 int *groups = conf->sae_groups;
2166 int default_groups[] = { 19, 20, 21, 0 };
2167 const char *password;
2168
2169 if (!groups || groups[0] <= 0)
2170 groups = default_groups;
2171
2172 password = ssid->sae_password;
2173 if (!password)
2174 password = ssid->passphrase;
2175
Hai Shalom899fcc72020-10-19 14:38:18 -07002176 if (!password ||
2177 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2178 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002179 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002180 /* PT derivation not needed */
2181 sae_deinit_pt(ssid->pt);
2182 ssid->pt = NULL;
2183 return;
2184 }
2185
2186 if (ssid->pt)
2187 return; /* PT already derived */
2188 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2189 (const u8 *) password, os_strlen(password),
2190 ssid->sae_password_id);
2191#endif /* CONFIG_SAE */
2192}
2193
2194
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002195static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2196{
2197#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2198 os_free(wpa_s->sme.sae_rejected_groups);
2199 wpa_s->sme.sae_rejected_groups = NULL;
2200#ifdef CONFIG_TESTING_OPTIONS
2201 if (wpa_s->extra_sae_rejected_groups) {
2202 int i, *groups = wpa_s->extra_sae_rejected_groups;
2203
2204 for (i = 0; groups[i]; i++) {
2205 wpa_printf(MSG_DEBUG,
2206 "TESTING: Indicate rejection of an extra SAE group %d",
2207 groups[i]);
2208 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2209 groups[i]);
2210 }
2211 }
2212#endif /* CONFIG_TESTING_OPTIONS */
2213#endif /* CONFIG_SAE && CONFIG_SME */
2214}
2215
2216
Hai Shalom60840252021-02-19 19:02:11 -08002217int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2218{
2219 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2220 wpa_msg(wpa_s, MSG_INFO,
2221 "Could not restore permanent MAC address");
2222 return -1;
2223 }
2224 wpa_s->mac_addr_changed = 0;
2225 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2226 wpa_msg(wpa_s, MSG_INFO,
2227 "Could not update MAC address information");
2228 return -1;
2229 }
2230 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2231 return 0;
2232}
2233
2234
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002235static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2236
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237/**
2238 * wpa_supplicant_associate - Request association
2239 * @wpa_s: Pointer to wpa_supplicant data
2240 * @bss: Scan results for the selected BSS, or %NULL if not available
2241 * @ssid: Configuration data for the selected network
2242 *
2243 * This function is used to request %wpa_supplicant to associate with a BSS.
2244 */
2245void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2246 struct wpa_bss *bss, struct wpa_ssid *ssid)
2247{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002248 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002249 int rand_style;
2250
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002251 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002252 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002253
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002254 /*
2255 * If we are starting a new connection, any previously pending EAPOL
2256 * RX cannot be valid anymore.
2257 */
2258 wpabuf_free(wpa_s->pending_eapol_rx);
2259 wpa_s->pending_eapol_rx = NULL;
2260
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002261 if (ssid->mac_addr == -1)
2262 rand_style = wpa_s->conf->mac_addr;
2263 else
2264 rand_style = ssid->mac_addr;
2265
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002266 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002267 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002268 wmm_ac_clear_saved_tspecs(wpa_s);
2269 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002270 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002271#ifdef CONFIG_TESTING_OPTIONS
2272 wpa_s->testing_resend_assoc = 0;
2273#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002274
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002275 if (wpa_s->last_ssid == ssid) {
2276 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002277 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002278 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2279 wmm_ac_save_tspecs(wpa_s);
2280 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002281 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2282 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002283 }
Hai Shalomc3565922019-10-28 11:58:20 -07002284 } else {
2285#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002286 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002287#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002288 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002289#ifdef CONFIG_SAE
2290 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2291#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002292
2293 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002294 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2295 return;
2296 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002297 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002298 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002299 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002300 }
2301 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302
2303#ifdef CONFIG_IBSS_RSN
2304 ibss_rsn_deinit(wpa_s->ibss_rsn);
2305 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002306#else /* CONFIG_IBSS_RSN */
2307 if (ssid->mode == WPAS_MODE_IBSS &&
2308 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2309 wpa_msg(wpa_s, MSG_INFO,
2310 "IBSS RSN not supported in the build");
2311 return;
2312 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313#endif /* CONFIG_IBSS_RSN */
2314
2315 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2316 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2317#ifdef CONFIG_AP
2318 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2319 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2320 "mode");
2321 return;
2322 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002323 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2324 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002325 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2326 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002327 return;
2328 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002329 wpa_s->current_bss = bss;
2330#else /* CONFIG_AP */
2331 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2332 "the build");
2333#endif /* CONFIG_AP */
2334 return;
2335 }
2336
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002337 if (ssid->mode == WPAS_MODE_MESH) {
2338#ifdef CONFIG_MESH
2339 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2340 wpa_msg(wpa_s, MSG_INFO,
2341 "Driver does not support mesh mode");
2342 return;
2343 }
2344 if (bss)
2345 ssid->frequency = bss->freq;
2346 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2347 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2348 return;
2349 }
2350 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002351#else /* CONFIG_MESH */
2352 wpa_msg(wpa_s, MSG_ERROR,
2353 "mesh mode support not included in the build");
2354#endif /* CONFIG_MESH */
2355 return;
2356 }
2357
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002358 /*
2359 * Set WPA state machine configuration to match the selected network now
2360 * so that the information is available before wpas_start_assoc_cb()
2361 * gets called. This is needed at least for RSN pre-authentication where
2362 * candidate APs are added to a list based on scan result processing
2363 * before completion of the first association.
2364 */
2365 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2366
2367#ifdef CONFIG_DPP
2368 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2369 return;
2370#endif /* CONFIG_DPP */
2371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372#ifdef CONFIG_TDLS
2373 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002374 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002375#endif /* CONFIG_TDLS */
2376
Hai Shalomc3565922019-10-28 11:58:20 -07002377#ifdef CONFIG_MBO
2378 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2379#endif /* CONFIG_MBO */
2380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002382 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 sme_authenticate(wpa_s, bss, ssid);
2384 return;
2385 }
2386
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002387 if (wpa_s->connect_work) {
2388 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2389 return;
2390 }
2391
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002392 if (radio_work_pending(wpa_s, "connect")) {
2393 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2394 return;
2395 }
2396
Dmitry Shmidt29333592017-01-09 12:27:11 -08002397#ifdef CONFIG_SME
2398 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2399 /* Clear possibly set auth_alg, if any, from last attempt. */
2400 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2401 }
2402#endif /* CONFIG_SME */
2403
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002404 wpas_abort_ongoing_scan(wpa_s);
2405
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002406 cwork = os_zalloc(sizeof(*cwork));
2407 if (cwork == NULL)
2408 return;
2409
2410 cwork->bss = bss;
2411 cwork->ssid = ssid;
2412
2413 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2414 wpas_start_assoc_cb, cwork) < 0) {
2415 os_free(cwork);
2416 }
2417}
2418
2419
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002420static int bss_is_ibss(struct wpa_bss *bss)
2421{
2422 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2423 IEEE80211_CAP_IBSS;
2424}
2425
2426
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002427static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2428 const struct wpa_ssid *ssid)
2429{
2430 enum hostapd_hw_mode hw_mode;
2431 struct hostapd_hw_modes *mode = NULL;
2432 u8 channel;
2433 int i;
2434
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002435 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2436 if (hw_mode == NUM_HOSTAPD_MODES)
2437 return 0;
2438 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2439 if (wpa_s->hw.modes[i].mode == hw_mode) {
2440 mode = &wpa_s->hw.modes[i];
2441 break;
2442 }
2443 }
2444
2445 if (!mode)
2446 return 0;
2447
2448 return mode->vht_capab != 0;
2449}
2450
2451
Hai Shalomc1a21442022-02-04 13:43:00 -08002452static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2453{
2454 int i;
2455
2456 for (i = channel; i < channel + 16; i += 4) {
2457 struct hostapd_channel_data *chan;
2458
2459 chan = hw_get_channel_chan(mode, i, NULL);
2460 if (!chan ||
2461 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2462 return false;
2463 }
2464
2465 return true;
2466}
2467
2468
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002469void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2470 const struct wpa_ssid *ssid,
2471 struct hostapd_freq_params *freq)
2472{
Hai Shalom81f62d82019-07-22 12:10:00 -07002473 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474 enum hostapd_hw_mode hw_mode;
2475 struct hostapd_hw_modes *mode = NULL;
2476 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2477 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002478 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2479 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2480 6595, 6675, 6755, 6835, 6915, 6995 };
2481 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002482 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2483 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002484 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002485 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002486 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002487 int chwidth, seg0, seg1;
2488 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002489 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002490
2491 freq->freq = ssid->frequency;
2492
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002493 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2494 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2495
2496 if (ssid->mode != WPAS_MODE_IBSS)
2497 break;
2498
2499 /* Don't adjust control freq in case of fixed_freq */
2500 if (ssid->fixed_freq)
2501 break;
2502
2503 if (!bss_is_ibss(bss))
2504 continue;
2505
2506 if (ssid->ssid_len == bss->ssid_len &&
2507 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2508 wpa_printf(MSG_DEBUG,
2509 "IBSS already found in scan results, adjust control freq: %d",
2510 bss->freq);
2511 freq->freq = bss->freq;
2512 obss_scan = 0;
2513 break;
2514 }
2515 }
2516
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002517 /* For IBSS check HT_IBSS flag */
2518 if (ssid->mode == WPAS_MODE_IBSS &&
2519 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2520 return;
2521
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002522 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2523 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2524 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2525 wpa_printf(MSG_DEBUG,
2526 "IBSS: WEP/TKIP detected, do not try to enable HT");
2527 return;
2528 }
2529
2530 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002531 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2532 if (wpa_s->hw.modes[i].mode == hw_mode) {
2533 mode = &wpa_s->hw.modes[i];
2534 break;
2535 }
2536 }
2537
2538 if (!mode)
2539 return;
2540
Hai Shalom60840252021-02-19 19:02:11 -08002541 freq->channel = channel;
2542
Hai Shalomc3565922019-10-28 11:58:20 -07002543 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2544 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002545
Hai Shalomc1a21442022-02-04 13:43:00 -08002546 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2547 * However, HE is mandatory for 6 GHz.
2548 */
2549 is_6ghz = is_6ghz_freq(freq->freq);
2550 if (is_6ghz)
2551 goto skip_to_6ghz;
2552
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002553#ifdef CONFIG_HT_OVERRIDES
2554 if (ssid->disable_ht) {
2555 freq->ht_enabled = 0;
2556 return;
2557 }
2558#endif /* CONFIG_HT_OVERRIDES */
2559
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002560 freq->ht_enabled = ht_supported(mode);
2561 if (!freq->ht_enabled)
2562 return;
2563
Hai Shalomc3565922019-10-28 11:58:20 -07002564 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2565 if (is_24ghz)
2566 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002567#ifdef CONFIG_HE_OVERRIDES
2568 if (is_24ghz && ssid->disable_he)
2569 freq->he_enabled = 0;
2570#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002571
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002572 /* Setup higher BW only for 5 GHz */
2573 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2574 return;
2575
2576 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2577 pri_chan = &mode->channels[chan_idx];
2578 if (pri_chan->chan == channel)
2579 break;
2580 pri_chan = NULL;
2581 }
2582 if (!pri_chan)
2583 return;
2584
2585 /* Check primary channel flags */
2586 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2587 return;
2588
Hai Shalom74f70d42019-02-11 14:42:39 -08002589 freq->channel = pri_chan->chan;
2590
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002591#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002592 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002593#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002594 if (ssid->disable_vht)
2595 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002596#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002597 goto skip_ht40;
2598 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002599#endif /* CONFIG_HT_OVERRIDES */
2600
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002601 /* Check/setup HT40+/HT40- */
2602 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2603 if (ht40plus[j] == channel) {
2604 ht40 = 1;
2605 break;
2606 }
2607 }
2608
2609 /* Find secondary channel */
2610 for (i = 0; i < mode->num_channels; i++) {
2611 sec_chan = &mode->channels[i];
2612 if (sec_chan->chan == channel + ht40 * 4)
2613 break;
2614 sec_chan = NULL;
2615 }
2616 if (!sec_chan)
2617 return;
2618
2619 /* Check secondary channel flags */
2620 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2621 return;
2622
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002623 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002624 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2625 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002626 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002627 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2628 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002629 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002630 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002631
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002632 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002633 struct wpa_scan_results *scan_res;
2634
2635 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2636 if (scan_res == NULL) {
2637 /* Back to HT20 */
2638 freq->sec_channel_offset = 0;
2639 return;
2640 }
2641
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002642 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002643 switch (res) {
2644 case 0:
2645 /* Back to HT20 */
2646 freq->sec_channel_offset = 0;
2647 break;
2648 case 1:
2649 /* Configuration allowed */
2650 break;
2651 case 2:
2652 /* Switch pri/sec channels */
2653 freq->freq = hw_get_freq(mode, sec_chan->chan);
2654 freq->sec_channel_offset = -freq->sec_channel_offset;
2655 freq->channel = sec_chan->chan;
2656 break;
2657 default:
2658 freq->sec_channel_offset = 0;
2659 break;
2660 }
2661
2662 wpa_scan_results_free(scan_res);
2663 }
2664
Hai Shalom74f70d42019-02-11 14:42:39 -08002665#ifdef CONFIG_HT_OVERRIDES
2666skip_ht40:
2667#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002668 wpa_printf(MSG_DEBUG,
2669 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2670 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002671
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002672 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002673 return;
2674
2675 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002676 if (ssid->mode == WPAS_MODE_IBSS &&
2677 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002678 return;
2679
Paul Stewart092955c2017-02-06 09:13:09 -08002680#ifdef CONFIG_VHT_OVERRIDES
2681 if (ssid->disable_vht) {
2682 freq->vht_enabled = 0;
2683 return;
2684 }
2685#endif /* CONFIG_VHT_OVERRIDES */
2686
Hai Shalomc1a21442022-02-04 13:43:00 -08002687skip_to_6ghz:
2688 vht_freq = *freq;
2689
2690 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002691 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002692 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002693 return;
2694
Hai Shalomfdcde762020-04-02 11:19:20 -07002695 /* Enable HE with VHT for 5 GHz */
2696 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002697
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002698 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002699 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2700 if (freq->freq >= bw80[j] &&
2701 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002702 break;
2703 }
2704
Hai Shalomc1a21442022-02-04 13:43:00 -08002705 if (j == ARRAY_SIZE(bw80) ||
2706 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002707 return;
2708
Hai Shalomc1a21442022-02-04 13:43:00 -08002709 /* Back to HT configuration if channel not usable */
2710 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2711 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002712
Hai Shalom81f62d82019-07-22 12:10:00 -07002713 chwidth = CHANWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002714 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002715 seg1 = 0;
2716
Hai Shalomc1a21442022-02-04 13:43:00 -08002717 if ((mode->he_capab[ieee80211_mode].phy_cap[
2718 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2719 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2720 /* In 160 MHz, the initial four 20 MHz channels were validated
2721 * above; check the remaining four 20 MHz channels for the total
2722 * of 160 MHz bandwidth.
2723 */
2724 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2725 return;
2726
2727 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2728 if (freq->freq == bw160[j]) {
2729 chwidth = CHANWIDTH_160MHZ;
2730 seg0 = channel + 14;
2731 break;
2732 }
2733 }
2734 }
2735
Hai Shalom81f62d82019-07-22 12:10:00 -07002736 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002737 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002738 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002739 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002740 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002741 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002742
2743 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2744 NUM_HOSTAPD_MODES)
2745 return;
2746
2747 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002748 struct hostapd_channel_data *chan;
2749
2750 chan = hw_get_channel_chan(mode, i, NULL);
2751 if (!chan)
2752 continue;
2753
2754 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2755 HOSTAPD_CHAN_NO_IR |
2756 HOSTAPD_CHAN_RADAR))
2757 continue;
2758
2759 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002760 chwidth = CHANWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002761 if (!is_6ghz)
2762 vht_caps |=
2763 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2764 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002765 }
2766
Hai Shalom81f62d82019-07-22 12:10:00 -07002767 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002768 break;
2769 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002770 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002771 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002772 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002773 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2774 seg0 = 50;
2775 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002776 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002777 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2778 seg0 = 114;
2779 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002780 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2781 chwidth = CHANWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002782 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002783#ifdef CONFIG_HT_OVERRIDES
2784 if (ssid->disable_ht40)
2785 seg0 = 0;
2786#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002787 }
2788
Hai Shalomfdcde762020-04-02 11:19:20 -07002789#ifdef CONFIG_HE_OVERRIDES
2790 if (ssid->disable_he) {
2791 vht_freq.he_enabled = 0;
2792 freq->he_enabled = 0;
2793 }
2794#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002795 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002796 freq->channel, ssid->enable_edmg,
2797 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002798 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002799 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002800 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002801 chwidth, seg0, seg1, vht_caps,
Sunil Ravi59fa4b42022-05-02 22:54:18 -07002802 &mode->he_capab[ieee80211_mode],
2803 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002804 return;
2805
2806 *freq = vht_freq;
2807
2808 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2809 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002810}
2811
2812
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002813#ifdef CONFIG_FILS
2814static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2815 size_t ie_buf_len)
2816{
2817 struct fils_hlp_req *req;
2818 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2819 const u8 *pos;
2820 u8 *buf = ie_buf;
2821
2822 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2823 list) {
2824 rem_len = ie_buf_len - ie_len;
2825 pos = wpabuf_head(req->pkt);
2826 hdr_len = 1 + 2 * ETH_ALEN + 6;
2827 hlp_len = wpabuf_len(req->pkt);
2828
2829 if (rem_len < 2 + hdr_len + hlp_len) {
2830 wpa_printf(MSG_ERROR,
2831 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2832 (unsigned long) rem_len,
2833 (unsigned long) (2 + hdr_len + hlp_len));
2834 break;
2835 }
2836
2837 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2838 /* Element ID */
2839 *buf++ = WLAN_EID_EXTENSION;
2840 /* Length */
2841 *buf++ = len;
2842 /* Element ID Extension */
2843 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2844 /* Destination MAC address */
2845 os_memcpy(buf, req->dst, ETH_ALEN);
2846 buf += ETH_ALEN;
2847 /* Source MAC address */
2848 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2849 buf += ETH_ALEN;
2850 /* LLC/SNAP Header */
2851 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2852 buf += 6;
2853 /* HLP Packet */
2854 os_memcpy(buf, pos, len - hdr_len);
2855 buf += len - hdr_len;
2856 pos += len - hdr_len;
2857
2858 hlp_len -= len - hdr_len;
2859 ie_len += 2 + len;
2860 rem_len -= 2 + len;
2861
2862 while (hlp_len) {
2863 len = (hlp_len > 255) ? 255 : hlp_len;
2864 if (rem_len < 2 + len)
2865 break;
2866 *buf++ = WLAN_EID_FRAGMENT;
2867 *buf++ = len;
2868 os_memcpy(buf, pos, len);
2869 buf += len;
2870 pos += len;
2871
2872 hlp_len -= len;
2873 ie_len += 2 + len;
2874 rem_len -= 2 + len;
2875 }
2876 }
2877
2878 return ie_len;
2879}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002880
2881
2882int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2883{
2884 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2885 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2886 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2887 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2888}
2889
2890
2891int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2892{
2893#ifdef CONFIG_FILS_SK_PFS
2894 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2895 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2896#else /* CONFIG_FILS_SK_PFS */
2897 return 0;
2898#endif /* CONFIG_FILS_SK_PFS */
2899}
2900
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002901#endif /* CONFIG_FILS */
2902
2903
Hai Shalomc1a21442022-02-04 13:43:00 -08002904static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2905 struct wpa_bss *bss,
2906 u8 *wpa_ie, size_t wpa_ie_len,
2907 size_t max_wpa_ie_len)
2908{
2909 struct wpabuf *wfa_ie = NULL;
2910 u8 wfa_capa[1];
2911 size_t wfa_ie_len, buf_len;
2912
2913 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2914 if (wpa_s->enable_dscp_policy_capa)
2915 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2916
2917 if (!wfa_capa[0])
2918 return wpa_ie_len;
2919
2920 /* Wi-Fi Alliance element */
2921 buf_len = 1 + /* Element ID */
2922 1 + /* Length */
2923 3 + /* OUI */
2924 1 + /* OUI Type */
2925 1 + /* Capabilities Length */
2926 sizeof(wfa_capa); /* Capabilities */
2927 wfa_ie = wpabuf_alloc(buf_len);
2928 if (!wfa_ie)
2929 return wpa_ie_len;
2930
2931 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2932 wpabuf_put_u8(wfa_ie, buf_len - 2);
2933 wpabuf_put_be24(wfa_ie, OUI_WFA);
2934 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2935 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2936 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2937
2938 wfa_ie_len = wpabuf_len(wfa_ie);
2939 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2940 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2941 wfa_ie);
2942 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2943 wfa_ie_len);
2944 wpa_ie_len += wfa_ie_len;
2945 }
2946
2947 wpabuf_free(wfa_ie);
2948 return wpa_ie_len;
2949}
2950
2951
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002952static u8 * wpas_populate_assoc_ies(
2953 struct wpa_supplicant *wpa_s,
2954 struct wpa_bss *bss, struct wpa_ssid *ssid,
2955 struct wpa_driver_associate_params *params,
2956 enum wpa_drv_update_connect_params_mask *mask)
2957{
2958 u8 *wpa_ie;
2959 size_t max_wpa_ie_len = 500;
2960 size_t wpa_ie_len;
2961 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002962#ifdef CONFIG_MBO
2963 const u8 *mbo_ie;
2964#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302965#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2966 int pmksa_cached = 0;
2967#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002968#ifdef CONFIG_FILS
2969 const u8 *realm, *username, *rrk;
2970 size_t realm_len, username_len, rrk_len;
2971 u16 next_seq_num;
2972 struct fils_hlp_req *req;
2973
2974 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2975 list) {
2976 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2977 2 + 2 * wpabuf_len(req->pkt) / 255;
2978 }
2979#endif /* CONFIG_FILS */
2980
2981 wpa_ie = os_malloc(max_wpa_ie_len);
2982 if (!wpa_ie) {
2983 wpa_printf(MSG_ERROR,
2984 "Failed to allocate connect IE buffer for %lu bytes",
2985 (unsigned long) max_wpa_ie_len);
2986 return NULL;
2987 }
2988
2989 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2990 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2991 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2992 int try_opportunistic;
2993 const u8 *cache_id = NULL;
2994
2995 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2996 wpa_s->conf->okc :
2997 ssid->proactive_key_caching) &&
2998 (ssid->proto & WPA_PROTO_RSN);
2999#ifdef CONFIG_FILS
3000 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3001 cache_id = wpa_bss_get_fils_cache_id(bss);
3002#endif /* CONFIG_FILS */
3003 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3004 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003005 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003006 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303007#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3008 pmksa_cached = 1;
3009#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003010 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003011 wpa_ie_len = max_wpa_ie_len;
3012 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3013 wpa_ie, &wpa_ie_len)) {
3014 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3015 "key management and encryption suites");
3016 os_free(wpa_ie);
3017 return NULL;
3018 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003019#ifdef CONFIG_HS20
3020 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3021 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3022 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3023 wpa_ie_len = max_wpa_ie_len;
3024 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3025 wpa_ie, &wpa_ie_len)) {
3026 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3027 "key management and encryption suites");
3028 os_free(wpa_ie);
3029 return NULL;
3030 }
3031#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003032 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3033 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3034 /*
3035 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3036 * use non-WPA since the scan results did not indicate that the
3037 * AP is using WPA or WPA2.
3038 */
3039 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3040 wpa_ie_len = 0;
3041 wpa_s->wpa_proto = 0;
3042 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3043 wpa_ie_len = max_wpa_ie_len;
3044 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3045 wpa_ie, &wpa_ie_len)) {
3046 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3047 "key management and encryption suites (no "
3048 "scan results)");
3049 os_free(wpa_ie);
3050 return NULL;
3051 }
3052#ifdef CONFIG_WPS
3053 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3054 struct wpabuf *wps_ie;
3055 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3056 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3057 wpa_ie_len = wpabuf_len(wps_ie);
3058 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3059 } else
3060 wpa_ie_len = 0;
3061 wpabuf_free(wps_ie);
3062 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3063 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3064 params->wps = WPS_MODE_PRIVACY;
3065 else
3066 params->wps = WPS_MODE_OPEN;
3067 wpa_s->wpa_proto = 0;
3068#endif /* CONFIG_WPS */
3069 } else {
3070 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3071 wpa_ie_len = 0;
3072 wpa_s->wpa_proto = 0;
3073 }
3074
3075#ifdef IEEE8021X_EAPOL
3076 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3077 if (ssid->leap) {
3078 if (ssid->non_leap == 0)
3079 algs = WPA_AUTH_ALG_LEAP;
3080 else
3081 algs |= WPA_AUTH_ALG_LEAP;
3082 }
3083 }
3084
3085#ifdef CONFIG_FILS
3086 /* Clear FILS association */
3087 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3088
3089 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3090 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3091 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3092 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003093 &next_seq_num, &rrk, &rrk_len) == 0 &&
3094 (!wpa_s->last_con_fail_realm ||
3095 wpa_s->last_con_fail_realm_len != realm_len ||
3096 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003097 algs = WPA_AUTH_ALG_FILS;
3098 params->fils_erp_username = username;
3099 params->fils_erp_username_len = username_len;
3100 params->fils_erp_realm = realm;
3101 params->fils_erp_realm_len = realm_len;
3102 params->fils_erp_next_seq_num = next_seq_num;
3103 params->fils_erp_rrk = rrk;
3104 params->fils_erp_rrk_len = rrk_len;
3105
3106 if (mask)
3107 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303108 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3109 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3110 pmksa_cached) {
3111 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003112 }
3113#endif /* CONFIG_FILS */
3114#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003115#ifdef CONFIG_SAE
3116 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3117 algs = WPA_AUTH_ALG_SAE;
3118#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003119
3120 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3121 if (ssid->auth_alg) {
3122 algs = ssid->auth_alg;
3123 wpa_dbg(wpa_s, MSG_DEBUG,
3124 "Overriding auth_alg selection: 0x%x", algs);
3125 }
3126
Hai Shalom5f92bc92019-04-18 11:54:11 -07003127#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303128 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003129 wpa_dbg(wpa_s, MSG_DEBUG,
3130 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3131 algs = WPA_AUTH_ALG_OPEN;
3132 }
3133#endif /* CONFIG_SAE */
3134
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003135#ifdef CONFIG_P2P
3136 if (wpa_s->global->p2p) {
3137 u8 *pos;
3138 size_t len;
3139 int res;
3140 pos = wpa_ie + wpa_ie_len;
3141 len = max_wpa_ie_len - wpa_ie_len;
3142 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3143 ssid->p2p_group);
3144 if (res >= 0)
3145 wpa_ie_len += res;
3146 }
3147
3148 wpa_s->cross_connect_disallowed = 0;
3149 if (bss) {
3150 struct wpabuf *p2p;
3151 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3152 if (p2p) {
3153 wpa_s->cross_connect_disallowed =
3154 p2p_get_cross_connect_disallowed(p2p);
3155 wpabuf_free(p2p);
3156 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3157 "connection",
3158 wpa_s->cross_connect_disallowed ?
3159 "disallows" : "allows");
3160 }
3161 }
3162
3163 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3164#endif /* CONFIG_P2P */
3165
3166 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003167 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003168 wpa_ie + wpa_ie_len,
3169 max_wpa_ie_len -
3170 wpa_ie_len);
3171 }
3172
3173 /*
3174 * Workaround: Add Extended Capabilities element only if the AP
3175 * included this element in Beacon/Probe Response frames. Some older
3176 * APs seem to have interoperability issues if this element is
3177 * included, so while the standard may require us to include the
3178 * element in all cases, it is justifiable to skip it to avoid
3179 * interoperability issues.
3180 */
3181 if (ssid->p2p_group)
3182 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3183 else
3184 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3185
3186 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3187 u8 ext_capab[18];
3188 int ext_capab_len;
3189 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3190 sizeof(ext_capab));
3191 if (ext_capab_len > 0 &&
3192 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3193 u8 *pos = wpa_ie;
3194 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3195 pos += 2 + pos[1];
3196 os_memmove(pos + ext_capab_len, pos,
3197 wpa_ie_len - (pos - wpa_ie));
3198 wpa_ie_len += ext_capab_len;
3199 os_memcpy(pos, ext_capab, ext_capab_len);
3200 }
3201 }
3202
3203#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003204 if (is_hs20_network(wpa_s, ssid, bss)
3205#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3206 && is_hs20_config(wpa_s)
3207#endif /* ANDROID */
3208 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003209 struct wpabuf *hs20;
3210
Roshan Pius3a1667e2018-07-03 15:17:14 -07003211 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003212 if (hs20) {
3213 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3214 size_t len;
3215
Hai Shalom74f70d42019-02-11 14:42:39 -08003216 wpas_hs20_add_indication(hs20, pps_mo_id,
3217 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003218 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003219 len = max_wpa_ie_len - wpa_ie_len;
3220 if (wpabuf_len(hs20) <= len) {
3221 os_memcpy(wpa_ie + wpa_ie_len,
3222 wpabuf_head(hs20), wpabuf_len(hs20));
3223 wpa_ie_len += wpabuf_len(hs20);
3224 }
3225 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003226 }
3227 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003228 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003229#endif /* CONFIG_HS20 */
3230
3231 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3232 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3233 size_t len;
3234
3235 len = max_wpa_ie_len - wpa_ie_len;
3236 if (wpabuf_len(buf) <= len) {
3237 os_memcpy(wpa_ie + wpa_ie_len,
3238 wpabuf_head(buf), wpabuf_len(buf));
3239 wpa_ie_len += wpabuf_len(buf);
3240 }
3241 }
3242
3243#ifdef CONFIG_FST
3244 if (wpa_s->fst_ies) {
3245 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3246
3247 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3248 os_memcpy(wpa_ie + wpa_ie_len,
3249 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3250 wpa_ie_len += fst_ies_len;
3251 }
3252 }
3253#endif /* CONFIG_FST */
3254
3255#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003256 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003257 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003258 int len;
3259
3260 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003261 max_wpa_ie_len - wpa_ie_len,
3262 !!mbo_attr_from_mbo_ie(mbo_ie,
3263 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003264 if (len >= 0)
3265 wpa_ie_len += len;
3266 }
3267#endif /* CONFIG_MBO */
3268
3269#ifdef CONFIG_FILS
3270 if (algs == WPA_AUTH_ALG_FILS) {
3271 size_t len;
3272
3273 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3274 max_wpa_ie_len - wpa_ie_len);
3275 wpa_ie_len += len;
3276 }
3277#endif /* CONFIG_FILS */
3278
3279#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003280#ifdef CONFIG_TESTING_OPTIONS
3281 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3282 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3283 } else
3284#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003285 if (algs == WPA_AUTH_ALG_OPEN &&
3286 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3287 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003288 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289
Roshan Pius3a1667e2018-07-03 15:17:14 -07003290 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003291 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003292 } else if (wpa_s->assoc_status_code ==
3293 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003294 if (wpa_s->last_owe_group == 19)
3295 group = 20;
3296 else if (wpa_s->last_owe_group == 20)
3297 group = 21;
3298 else
3299 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003300 } else {
3301 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003302 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003303
Roshan Pius3a1667e2018-07-03 15:17:14 -07003304 wpa_s->last_owe_group = group;
3305 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003306 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3307 if (owe_ie &&
3308 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3309 os_memcpy(wpa_ie + wpa_ie_len,
3310 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3311 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003313 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003314 }
3315#endif /* CONFIG_OWE */
3316
Hai Shalom021b0b52019-04-10 11:17:58 -07003317#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003318 if (DPP_VERSION > 1 &&
3319 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003320 ssid->dpp_netaccesskey &&
3321 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003322 struct rsn_pmksa_cache_entry *pmksa;
3323
3324 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3325 if (!pmksa || !pmksa->dpp_pfs)
3326 goto pfs_fail;
3327
Hai Shalom021b0b52019-04-10 11:17:58 -07003328 dpp_pfs_free(wpa_s->dpp_pfs);
3329 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3330 ssid->dpp_netaccesskey_len);
3331 if (!wpa_s->dpp_pfs) {
3332 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3333 /* Try to continue without PFS */
3334 goto pfs_fail;
3335 }
3336 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3337 max_wpa_ie_len - wpa_ie_len) {
3338 os_memcpy(wpa_ie + wpa_ie_len,
3339 wpabuf_head(wpa_s->dpp_pfs->ie),
3340 wpabuf_len(wpa_s->dpp_pfs->ie));
3341 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3342 }
3343 }
3344pfs_fail:
3345#endif /* CONFIG_DPP2 */
3346
Roshan Pius3a1667e2018-07-03 15:17:14 -07003347#ifdef CONFIG_IEEE80211R
3348 /*
3349 * Add MDIE under these conditions: the network profile allows FT,
3350 * the AP supports FT, and the mobility domain ID matches.
3351 */
3352 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3353 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3354
3355 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3356 size_t len = 0;
3357 const u8 *md = mdie + 2;
3358 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3359
3360 if (os_memcmp(md, wpa_md,
3361 MOBILITY_DOMAIN_ID_LEN) == 0) {
3362 /* Add mobility domain IE */
3363 len = wpa_ft_add_mdie(
3364 wpa_s->wpa, wpa_ie + wpa_ie_len,
3365 max_wpa_ie_len - wpa_ie_len, mdie);
3366 wpa_ie_len += len;
3367 }
3368#ifdef CONFIG_SME
3369 if (len > 0 && wpa_s->sme.ft_used &&
3370 wpa_sm_has_ptk(wpa_s->wpa)) {
3371 wpa_dbg(wpa_s, MSG_DEBUG,
3372 "SME: Trying to use FT over-the-air");
3373 algs |= WPA_AUTH_ALG_FT;
3374 }
3375#endif /* CONFIG_SME */
3376 }
3377 }
3378#endif /* CONFIG_IEEE80211R */
3379
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003380#ifdef CONFIG_TESTING_OPTIONS
3381 if (wpa_s->rsnxe_override_assoc &&
3382 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3383 max_wpa_ie_len - wpa_ie_len) {
3384 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3385 os_memcpy(wpa_ie + wpa_ie_len,
3386 wpabuf_head(wpa_s->rsnxe_override_assoc),
3387 wpabuf_len(wpa_s->rsnxe_override_assoc));
3388 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3389 } else
3390#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003391 if (wpa_s->rsnxe_len > 0 &&
3392 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3393 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3394 wpa_ie_len += wpa_s->rsnxe_len;
3395 }
3396
Hai Shalomc1a21442022-02-04 13:43:00 -08003397#ifdef CONFIG_TESTING_OPTIONS
3398 if (wpa_s->disable_mscs_support)
3399 goto mscs_end;
3400#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003401 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3402 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003403 struct wpabuf *mscs_ie;
3404 size_t mscs_ie_len, buf_len;
3405
Hai Shalom899fcc72020-10-19 14:38:18 -07003406 buf_len = 3 + /* MSCS descriptor IE header */
3407 1 + /* Request type */
3408 2 + /* User priority control */
3409 4 + /* Stream timeout */
3410 3 + /* TCLAS Mask IE header */
3411 wpa_s->robust_av.frame_classifier_len;
3412 mscs_ie = wpabuf_alloc(buf_len);
3413 if (!mscs_ie) {
3414 wpa_printf(MSG_INFO,
3415 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003416 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003417 }
3418
3419 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3420 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3421 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3422 mscs_ie_len = wpabuf_len(mscs_ie);
3423 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3424 mscs_ie_len);
3425 wpa_ie_len += mscs_ie_len;
3426 }
3427
3428 wpabuf_free(mscs_ie);
3429 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003430mscs_end:
3431
3432 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3433 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003434
Hai Shalom74f70d42019-02-11 14:42:39 -08003435 if (ssid->multi_ap_backhaul_sta) {
3436 size_t multi_ap_ie_len;
3437
3438 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3439 max_wpa_ie_len - wpa_ie_len,
3440 MULTI_AP_BACKHAUL_STA);
3441 if (multi_ap_ie_len == 0) {
3442 wpa_printf(MSG_ERROR,
3443 "Multi-AP: Failed to build Multi-AP IE");
3444 os_free(wpa_ie);
3445 return NULL;
3446 }
3447 wpa_ie_len += multi_ap_ie_len;
3448 }
3449
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 params->wpa_ie = wpa_ie;
3451 params->wpa_ie_len = wpa_ie_len;
3452 params->auth_alg = algs;
3453 if (mask)
3454 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3455
3456 return wpa_ie;
3457}
3458
3459
Hai Shalomc3565922019-10-28 11:58:20 -07003460#ifdef CONFIG_OWE
3461static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3462{
3463 struct wpa_driver_associate_params params;
3464 u8 *wpa_ie;
3465
3466 os_memset(&params, 0, sizeof(params));
3467 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3468 wpa_s->current_ssid, &params, NULL);
3469 if (!wpa_ie)
3470 return;
3471
3472 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3473 os_free(wpa_ie);
3474}
3475#endif /* CONFIG_OWE */
3476
3477
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3479static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3480{
3481 struct wpa_driver_associate_params params;
3482 enum wpa_drv_update_connect_params_mask mask = 0;
3483 u8 *wpa_ie;
3484
3485 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3486 return; /* nothing to do */
3487
3488 os_memset(&params, 0, sizeof(params));
3489 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3490 wpa_s->current_ssid, &params, &mask);
3491 if (!wpa_ie)
3492 return;
3493
Hai Shalomc1a21442022-02-04 13:43:00 -08003494 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3495 wpa_s->auth_alg = params.auth_alg;
3496 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003497 }
3498
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003499 os_free(wpa_ie);
3500}
3501#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3502
3503
Hai Shalomc3565922019-10-28 11:58:20 -07003504static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3505{
3506 if (!edmg_ie || edmg_ie[1] < 6)
3507 return 0;
3508 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3509}
3510
3511
3512static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3513{
3514 if (!edmg_ie || edmg_ie[1] < 6)
3515 return 0;
3516 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3517}
3518
3519
3520/* Returns the intersection of two EDMG configurations.
3521 * Note: The current implementation is limited to CB2 only (CB1 included),
3522 * i.e., the implementation supports up to 2 contiguous channels.
3523 * For supporting non-contiguous (aggregated) channels and for supporting
3524 * CB3 and above, this function will need to be extended.
3525 */
3526static struct ieee80211_edmg_config
3527get_edmg_intersection(struct ieee80211_edmg_config a,
3528 struct ieee80211_edmg_config b,
3529 u8 primary_channel)
3530{
3531 struct ieee80211_edmg_config result;
3532 int i, contiguous = 0;
3533 int max_contiguous = 0;
3534
3535 result.channels = b.channels & a.channels;
3536 if (!result.channels) {
3537 wpa_printf(MSG_DEBUG,
3538 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3539 a.channels, b.channels);
3540 goto fail;
3541 }
3542
3543 if (!(result.channels & BIT(primary_channel - 1))) {
3544 wpa_printf(MSG_DEBUG,
3545 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3546 primary_channel, result.channels);
3547 goto fail;
3548 }
3549
3550 /* Find max contiguous channels */
3551 for (i = 0; i < 6; i++) {
3552 if (result.channels & BIT(i))
3553 contiguous++;
3554 else
3555 contiguous = 0;
3556
3557 if (contiguous > max_contiguous)
3558 max_contiguous = contiguous;
3559 }
3560
3561 /* Assuming AP and STA supports ONLY contiguous channels,
3562 * bw configuration can have value between 4-7.
3563 */
3564 if ((b.bw_config < a.bw_config))
3565 result.bw_config = b.bw_config;
3566 else
3567 result.bw_config = a.bw_config;
3568
3569 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3570 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3571 wpa_printf(MSG_DEBUG,
3572 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3573 max_contiguous);
3574 goto fail;
3575 }
3576
3577 return result;
3578
3579fail:
3580 result.channels = 0;
3581 result.bw_config = 0;
3582 return result;
3583}
3584
3585
3586static struct ieee80211_edmg_config
3587get_supported_edmg(struct wpa_supplicant *wpa_s,
3588 struct hostapd_freq_params *freq,
3589 struct ieee80211_edmg_config request_edmg)
3590{
3591 enum hostapd_hw_mode hw_mode;
3592 struct hostapd_hw_modes *mode = NULL;
3593 u8 primary_channel;
3594
3595 if (!wpa_s->hw.modes)
3596 goto fail;
3597
3598 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3599 if (hw_mode == NUM_HOSTAPD_MODES)
3600 goto fail;
3601
Hai Shalom60840252021-02-19 19:02:11 -08003602 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003603 if (!mode)
3604 goto fail;
3605
3606 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3607
3608fail:
3609 request_edmg.channels = 0;
3610 request_edmg.bw_config = 0;
3611 return request_edmg;
3612}
3613
3614
Hai Shalom021b0b52019-04-10 11:17:58 -07003615#ifdef CONFIG_MBO
3616void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3617{
3618 struct wpa_driver_associate_params params;
3619 u8 *wpa_ie;
3620
3621 /*
3622 * Update MBO connect params only in case of change of MBO attributes
3623 * when connected, if the AP support MBO.
3624 */
3625
3626 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3627 !wpa_s->current_bss ||
3628 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3629 return;
3630
3631 os_memset(&params, 0, sizeof(params));
3632 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3633 wpa_s->current_ssid, &params, NULL);
3634 if (!wpa_ie)
3635 return;
3636
3637 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3638 os_free(wpa_ie);
3639}
3640#endif /* CONFIG_MBO */
3641
3642
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003643static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3644{
3645 struct wpa_connect_work *cwork = work->ctx;
3646 struct wpa_bss *bss = cwork->bss;
3647 struct wpa_ssid *ssid = cwork->ssid;
3648 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003649 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003650 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003651 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003652 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003653 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003654#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003655 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003656#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003657 int assoc_failed = 0;
3658 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003659 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003660#ifdef CONFIG_HT_OVERRIDES
3661 struct ieee80211_ht_capabilities htcaps;
3662 struct ieee80211_ht_capabilities htcaps_mask;
3663#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003664#ifdef CONFIG_VHT_OVERRIDES
3665 struct ieee80211_vht_capabilities vhtcaps;
3666 struct ieee80211_vht_capabilities vhtcaps_mask;
3667#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003668
Hai Shalomc1a21442022-02-04 13:43:00 -08003669 wpa_s->roam_in_progress = false;
3670#ifdef CONFIG_WNM
3671 wpa_s->bss_trans_mgmt_in_progress = false;
3672#endif /* CONFIG_WNM */
3673
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003674 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003675 if (work->started) {
3676 wpa_s->connect_work = NULL;
3677
3678 /* cancel possible auth. timeout */
3679 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3680 NULL);
3681 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003682 wpas_connect_work_free(cwork);
3683 return;
3684 }
3685
3686 wpa_s->connect_work = work;
3687
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003688 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3689 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003690 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3691 wpas_connect_work_done(wpa_s);
3692 return;
3693 }
3694
Dmitry Shmidte4663042016-04-04 10:07:49 -07003695 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 os_memset(&params, 0, sizeof(params));
3697 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003698 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003699
3700 /* Starting new association, so clear the possibly used WPA IE from the
3701 * previous association. */
3702 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3703 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3704 wpa_s->rsnxe_len = 0;
3705 wpa_s->mscs_setup_done = false;
3706
3707 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3708 if (!wpa_ie) {
3709 wpas_connect_work_done(wpa_s);
3710 return;
3711 }
3712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003713 if (bss &&
3714 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003715#ifdef CONFIG_IEEE80211R
3716 const u8 *ie, *md = NULL;
3717#endif /* CONFIG_IEEE80211R */
3718 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3719 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3720 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3721 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3722 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3723 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3724 if (bssid_changed)
3725 wpas_notify_bssid_changed(wpa_s);
3726#ifdef CONFIG_IEEE80211R
3727 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3728 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3729 md = ie + 2;
3730 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3731 if (md) {
3732 /* Prepare for the next transition */
3733 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3734 }
3735#endif /* CONFIG_IEEE80211R */
3736#ifdef CONFIG_WPS
3737 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3738 wpa_s->conf->ap_scan == 2 &&
3739 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3740 /* Use ap_scan==1 style network selection to find the network
3741 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003742 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003743 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744 wpa_s->reassociate = 1;
3745 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003746 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 return;
3748#endif /* CONFIG_WPS */
3749 } else {
3750 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3751 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003752 if (bss)
3753 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3754 else
3755 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003756 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003757 if (!wpa_s->pno)
3758 wpa_supplicant_cancel_sched_scan(wpa_s);
3759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003760 wpa_supplicant_cancel_scan(wpa_s);
3761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003762 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3763 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003764 cipher_pairwise = wpa_s->pairwise_cipher;
3765 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003766 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3768 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3769 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3770 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003771#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772 if (wpa_set_wep_keys(wpa_s, ssid)) {
3773 use_crypt = 1;
3774 wep_keys_set = 1;
3775 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003776#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 }
3778 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3779 use_crypt = 0;
3780
3781#ifdef IEEE8021X_EAPOL
3782 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3783 if ((ssid->eapol_flags &
3784 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3785 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3786 !wep_keys_set) {
3787 use_crypt = 0;
3788 } else {
3789 /* Assume that dynamic WEP-104 keys will be used and
3790 * set cipher suites in order for drivers to expect
3791 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003792 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793 }
3794 }
3795#endif /* IEEE8021X_EAPOL */
3796
3797 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3798 /* Set the key before (and later after) association */
3799 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3800 }
3801
3802 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3803 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 params.ssid = bss->ssid;
3805 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003806 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3807 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003808 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3809 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003810 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003811 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003812 ssid->bssid_set,
3813 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003814 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003815 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003816 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003817 params.bssid_hint = bss->bssid;
3818 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003819 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003820 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003821 if (ssid->bssid_hint_set)
3822 params.bssid_hint = ssid->bssid_hint;
3823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003824 params.ssid = ssid->ssid;
3825 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003826 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003828
3829 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3830 wpa_s->conf->ap_scan == 2) {
3831 params.bssid = ssid->bssid;
3832 params.fixed_bssid = 1;
3833 }
3834
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003835 /* Initial frequency for IBSS/mesh */
3836 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003837 ssid->frequency > 0 && params.freq.freq == 0)
3838 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003839
3840 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003841 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003842 if (ssid->beacon_int)
3843 params.beacon_int = ssid->beacon_int;
3844 else
3845 params.beacon_int = wpa_s->conf->beacon_int;
3846 }
3847
Hai Shalomc3565922019-10-28 11:58:20 -07003848 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003849 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3850 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003851 else
3852 edmg_ie_oper = NULL;
3853
3854 if (edmg_ie_oper) {
3855 params.freq.edmg.channels =
3856 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3857 params.freq.edmg.bw_config =
3858 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3859 wpa_printf(MSG_DEBUG,
3860 "AP supports EDMG channels 0x%x, bw_config %d",
3861 params.freq.edmg.channels,
3862 params.freq.edmg.bw_config);
3863
3864 /* User may ask for specific EDMG channel for EDMG connection
3865 * (must be supported by AP)
3866 */
3867 if (ssid->edmg_channel) {
3868 struct ieee80211_edmg_config configured_edmg;
3869 enum hostapd_hw_mode hw_mode;
3870 u8 primary_channel;
3871
3872 hw_mode = ieee80211_freq_to_chan(bss->freq,
3873 &primary_channel);
3874 if (hw_mode == NUM_HOSTAPD_MODES)
3875 goto edmg_fail;
3876
3877 hostapd_encode_edmg_chan(ssid->enable_edmg,
3878 ssid->edmg_channel,
3879 primary_channel,
3880 &configured_edmg);
3881
3882 if (ieee802_edmg_is_allowed(params.freq.edmg,
3883 configured_edmg)) {
3884 params.freq.edmg = configured_edmg;
3885 wpa_printf(MSG_DEBUG,
3886 "Use EDMG channel %d for connection",
3887 ssid->edmg_channel);
3888 } else {
3889 edmg_fail:
3890 params.freq.edmg.channels = 0;
3891 params.freq.edmg.bw_config = 0;
3892 wpa_printf(MSG_WARNING,
3893 "EDMG channel %d not supported by AP, fallback to DMG",
3894 ssid->edmg_channel);
3895 }
3896 }
3897
3898 if (params.freq.edmg.channels) {
3899 wpa_printf(MSG_DEBUG,
3900 "EDMG before: channels 0x%x, bw_config %d",
3901 params.freq.edmg.channels,
3902 params.freq.edmg.bw_config);
3903 params.freq.edmg = get_supported_edmg(wpa_s,
3904 &params.freq,
3905 params.freq.edmg);
3906 wpa_printf(MSG_DEBUG,
3907 "EDMG after: channels 0x%x, bw_config %d",
3908 params.freq.edmg.channels,
3909 params.freq.edmg.bw_config);
3910 }
3911 }
3912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 params.pairwise_suite = cipher_pairwise;
3914 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003915 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003916 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003917 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003918 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003919 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003920 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003921#ifdef CONFIG_WEP
3922 {
3923 int i;
3924
3925 for (i = 0; i < NUM_WEP_KEYS; i++) {
3926 if (ssid->wep_key_len[i])
3927 params.wep_key[i] = ssid->wep_key[i];
3928 params.wep_key_len[i] = ssid->wep_key_len[i];
3929 }
3930 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003932#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003933
Hai Shalom74f70d42019-02-11 14:42:39 -08003934 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303935 (
3936#ifdef CONFIG_DRIVER_NL80211_BRCM
3937 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3938#else
3939 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3940#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003941 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003942 params.passphrase = ssid->passphrase;
3943 if (ssid->psk_set)
3944 params.psk = ssid->psk;
3945 }
3946
Hai Shalom74f70d42019-02-11 14:42:39 -08003947 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3948 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3949 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3950 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3951 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003952 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003953
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003954 if (wpa_s->conf->key_mgmt_offload) {
3955 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3956 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003957 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3958 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003959 params.req_key_mgmt_offload =
3960 ssid->proactive_key_caching < 0 ?
3961 wpa_s->conf->okc : ssid->proactive_key_caching;
3962 else
3963 params.req_key_mgmt_offload = 1;
3964
Vinayak Yadawad14709082022-03-17 14:25:11 +05303965 if ((
3966#ifdef CONFIG_DRIVER_NL80211_BRCM
3967 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3968#else
3969 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3970#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003971 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3972 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3973 ssid->psk_set)
3974 params.psk = ssid->psk;
3975 }
3976
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003977 params.drop_unencrypted = use_crypt;
3978
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003979 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003980 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003981 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3982 struct wpa_ie_data ie;
3983 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3984 ie.capabilities &
3985 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3986 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3987 "MFP: require MFP");
3988 params.mgmt_frame_protection =
3989 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003990#ifdef CONFIG_OWE
3991 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3992 !ssid->owe_only) {
3993 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3994#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995 }
3996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003998 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004000 if (wpa_s->p2pdev->set_sta_uapsd)
4001 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002 else
4003 params.uapsd = -1;
4004
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004005#ifdef CONFIG_HT_OVERRIDES
4006 os_memset(&htcaps, 0, sizeof(htcaps));
4007 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4008 params.htcaps = (u8 *) &htcaps;
4009 params.htcaps_mask = (u8 *) &htcaps_mask;
4010 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4011#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004012#ifdef CONFIG_VHT_OVERRIDES
4013 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4014 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4015 params.vhtcaps = &vhtcaps;
4016 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004017 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004018#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004019#ifdef CONFIG_HE_OVERRIDES
4020 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4021#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004022
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004023#ifdef CONFIG_P2P
4024 /*
4025 * If multi-channel concurrency is not supported, check for any
4026 * frequency conflict. In case of any frequency conflict, remove the
4027 * least prioritized connection.
4028 */
4029 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004030 int freq, num;
4031 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004032 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004033 wpa_printf(MSG_DEBUG,
4034 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004035 freq, params.freq.freq);
4036 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004037 wpa_s, params.freq.freq, ssid) < 0) {
4038 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004039 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004040 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004041 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004042 }
4043 }
4044#endif /* CONFIG_P2P */
4045
Dmitry Shmidte4663042016-04-04 10:07:49 -07004046 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
4047 wpa_s->current_ssid)
4048 params.prev_bssid = prev_bssid;
4049
Hai Shalom60840252021-02-19 19:02:11 -08004050#ifdef CONFIG_SAE
4051 params.sae_pwe = wpa_s->conf->sae_pwe;
4052#endif /* CONFIG_SAE */
4053
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004054 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 if (ret < 0) {
4057 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4058 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004059 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 /*
4061 * The driver is known to mean what is saying, so we
4062 * can stop right here; the association will not
4063 * succeed.
4064 */
4065 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004066 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004067 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004068 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004069 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4070 return;
4071 }
4072 /* try to continue anyway; new association will be tried again
4073 * after timeout */
4074 assoc_failed = 1;
4075 }
4076
4077 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4078 /* Set the key after the association just in case association
4079 * cleared the previously configured key. */
4080 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4081 /* No need to timeout authentication since there is no key
4082 * management. */
4083 wpa_supplicant_cancel_auth_timeout(wpa_s);
4084 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4085#ifdef CONFIG_IBSS_RSN
4086 } else if (ssid->mode == WPAS_MODE_IBSS &&
4087 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4088 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4089 /*
4090 * RSN IBSS authentication is per-STA and we can disable the
4091 * per-BSSID authentication.
4092 */
4093 wpa_supplicant_cancel_auth_timeout(wpa_s);
4094#endif /* CONFIG_IBSS_RSN */
4095 } else {
4096 /* Timeout for IEEE 802.11 authentication and association */
4097 int timeout = 60;
4098
4099 if (assoc_failed) {
4100 /* give IBSS a bit more time */
4101 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4102 } else if (wpa_s->conf->ap_scan == 1) {
4103 /* give IBSS a bit more time */
4104 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4105 }
4106 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4107 }
4108
Hai Shalomfdcde762020-04-02 11:19:20 -07004109#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004110 if (wep_keys_set &&
4111 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 /* Set static WEP keys again */
4113 wpa_set_wep_keys(wpa_s, ssid);
4114 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004115#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116
4117 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
4118 /*
4119 * Do not allow EAP session resumption between different
4120 * network configurations.
4121 */
4122 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4123 }
4124 old_ssid = wpa_s->current_ssid;
4125 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004126
4127 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004128 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004129#ifdef CONFIG_HS20
4130 hs20_configure_frame_filters(wpa_s);
4131#endif /* CONFIG_HS20 */
4132 }
4133
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4135 wpa_supplicant_initiate_eapol(wpa_s);
4136 if (old_ssid != wpa_s->current_ssid)
4137 wpas_notify_network_changed(wpa_s);
4138}
4139
4140
4141static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4142 const u8 *addr)
4143{
4144 struct wpa_ssid *old_ssid;
4145
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004146 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004149 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004150 wpa_sm_set_config(wpa_s->wpa, NULL);
4151 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4152 if (old_ssid != wpa_s->current_ssid)
4153 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004154
4155 wpas_scs_deinit(wpa_s);
4156 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004157 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4158}
4159
4160
4161/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004162 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4163 * @wpa_s: Pointer to wpa_supplicant data
4164 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4165 *
4166 * This function is used to request %wpa_supplicant to deauthenticate from the
4167 * current AP.
4168 */
4169void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004170 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171{
4172 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004173 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004174 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004176 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004177 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004178 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004179 reason_code, reason2str(reason_code),
4180 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004181
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004182 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4183 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4184 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004185 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004186 else if (!is_zero_ether_addr(wpa_s->bssid))
4187 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004188 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4189 /*
4190 * When using driver-based BSS selection, we may not know the
4191 * BSSID with which we are currently trying to associate. We
4192 * need to notify the driver of this disconnection even in such
4193 * a case, so use the all zeros address here.
4194 */
4195 addr = wpa_s->bssid;
4196 zero_addr = 1;
4197 }
4198
Hai Shalom74f70d42019-02-11 14:42:39 -08004199 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4200 wpa_s->enabled_4addr_mode = 0;
4201
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004202#ifdef CONFIG_TDLS
4203 wpa_tdls_teardown_peers(wpa_s->wpa);
4204#endif /* CONFIG_TDLS */
4205
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004206#ifdef CONFIG_MESH
4207 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004208 struct mesh_conf *mconf;
4209
4210 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004211 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4212 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004213 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4214 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004215 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004216 }
4217#endif /* CONFIG_MESH */
4218
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004219 if (addr) {
4220 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004221 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004222 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004223 event.deauth_info.locally_generated = 1;
4224 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004225 if (zero_addr)
4226 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004227 }
4228
4229 wpa_supplicant_clear_connection(wpa_s, addr);
4230}
4231
Hai Shalomfdcde762020-04-02 11:19:20 -07004232
4233void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4234{
4235 wpa_s->own_reconnect_req = 1;
4236 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4237
4238}
4239
4240
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004241static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4242 struct wpa_ssid *ssid)
4243{
4244 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4245 return;
4246
4247 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004248 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004249 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4250 wpas_notify_network_enabled_changed(wpa_s, ssid);
4251
4252 /*
4253 * Try to reassociate since there is no current configuration and a new
4254 * network was made available.
4255 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004256 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004257 wpa_s->reassociate = 1;
4258}
4259
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004260
Roshan Pius950bec92016-07-19 09:49:24 -07004261/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004262 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004263 * @wpa_s: wpa_supplicant structure for a network interface
4264 * Returns: The new network configuration or %NULL if operation failed
4265 *
4266 * This function performs the following operations:
4267 * 1. Adds a new network.
4268 * 2. Send network addition notification.
4269 * 3. Marks the network disabled.
4270 * 4. Set network default parameters.
4271 */
4272struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4273{
4274 struct wpa_ssid *ssid;
4275
4276 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004277 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004278 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004279 wpas_notify_network_added(wpa_s, ssid);
4280 ssid->disabled = 1;
4281 wpa_config_set_network_defaults(ssid);
4282
4283 return ssid;
4284}
4285
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004286
Roshan Pius950bec92016-07-19 09:49:24 -07004287/**
4288 * wpa_supplicant_remove_network - Remove a configured network based on id
4289 * @wpa_s: wpa_supplicant structure for a network interface
4290 * @id: Unique network id to search for
4291 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4292 * could not be removed
4293 *
4294 * This function performs the following operations:
4295 * 1. Removes the network.
4296 * 2. Send network removal notification.
4297 * 3. Update internal state machines.
4298 * 4. Stop any running sched scans.
4299 */
4300int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4301{
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004302 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004303 int was_disabled;
4304
4305 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004306 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004307 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004308 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004309
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004310 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004311#ifdef CONFIG_SME
4312 wpa_s->sme.prev_bssid_set = 0;
4313#endif /* CONFIG_SME */
4314 /*
4315 * Invalidate the EAP session cache if the current or
4316 * previously used network is removed.
4317 */
4318 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4319 }
4320
Sunil Ravi59fa4b42022-05-02 22:54:18 -07004321 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004322 wpa_sm_set_config(wpa_s->wpa, NULL);
4323 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4324
4325 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4326 wpa_s->own_disconnect_req = 1;
4327 wpa_supplicant_deauthenticate(wpa_s,
4328 WLAN_REASON_DEAUTH_LEAVING);
4329 }
4330
4331 was_disabled = ssid->disabled;
4332
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004333 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004334 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004335
4336 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004337 wpa_printf(MSG_DEBUG,
4338 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004339 wpa_supplicant_cancel_sched_scan(wpa_s);
4340 wpa_supplicant_req_scan(wpa_s, 0, 0);
4341 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004342
Roshan Pius950bec92016-07-19 09:49:24 -07004343 return 0;
4344}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004346
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004348 * wpa_supplicant_remove_all_networks - Remove all configured networks
4349 * @wpa_s: wpa_supplicant structure for a network interface
4350 * Returns: 0 on success (errors are currently ignored)
4351 *
4352 * This function performs the following operations:
4353 * 1. Remove all networks.
4354 * 2. Send network removal notifications.
4355 * 3. Update internal state machines.
4356 * 4. Stop any running sched scans.
4357 */
4358int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4359{
4360 struct wpa_ssid *ssid;
4361
4362 if (wpa_s->sched_scanning)
4363 wpa_supplicant_cancel_sched_scan(wpa_s);
4364
4365 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4366 if (wpa_s->current_ssid) {
4367#ifdef CONFIG_SME
4368 wpa_s->sme.prev_bssid_set = 0;
4369#endif /* CONFIG_SME */
4370 wpa_sm_set_config(wpa_s->wpa, NULL);
4371 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4372 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4373 wpa_s->own_disconnect_req = 1;
4374 wpa_supplicant_deauthenticate(
4375 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4376 }
4377 ssid = wpa_s->conf->ssid;
4378 while (ssid) {
4379 struct wpa_ssid *remove_ssid = ssid;
4380 int id;
4381
4382 id = ssid->id;
4383 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004384 wpas_notify_network_removed(wpa_s, remove_ssid);
4385 wpa_config_remove_network(wpa_s->conf, id);
4386 }
4387 return 0;
4388}
4389
4390
4391/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392 * wpa_supplicant_enable_network - Mark a configured network as enabled
4393 * @wpa_s: wpa_supplicant structure for a network interface
4394 * @ssid: wpa_ssid structure for a configured network or %NULL
4395 *
4396 * Enables the specified network or all networks if no network specified.
4397 */
4398void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4399 struct wpa_ssid *ssid)
4400{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004402 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4403 wpa_supplicant_enable_one_network(wpa_s, ssid);
4404 } else
4405 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004406
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004407 if (wpa_s->reassociate && !wpa_s->disconnected &&
4408 (!wpa_s->current_ssid ||
4409 wpa_s->wpa_state == WPA_DISCONNECTED ||
4410 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004411 if (wpa_s->sched_scanning) {
4412 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4413 "new network to scan filters");
4414 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004415 }
4416
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004417 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4418 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004419 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004420 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004421 }
4422}
4423
4424
4425/**
4426 * wpa_supplicant_disable_network - Mark a configured network as disabled
4427 * @wpa_s: wpa_supplicant structure for a network interface
4428 * @ssid: wpa_ssid structure for a configured network or %NULL
4429 *
4430 * Disables the specified network or all networks if no network specified.
4431 */
4432void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4433 struct wpa_ssid *ssid)
4434{
4435 struct wpa_ssid *other_ssid;
4436 int was_disabled;
4437
4438 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004439 if (wpa_s->sched_scanning)
4440 wpa_supplicant_cancel_sched_scan(wpa_s);
4441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004442 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4443 other_ssid = other_ssid->next) {
4444 was_disabled = other_ssid->disabled;
4445 if (was_disabled == 2)
4446 continue; /* do not change persistent P2P group
4447 * data */
4448
4449 other_ssid->disabled = 1;
4450
4451 if (was_disabled != other_ssid->disabled)
4452 wpas_notify_network_enabled_changed(
4453 wpa_s, other_ssid);
4454 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004455 if (wpa_s->current_ssid) {
4456 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4457 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004458 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004459 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004460 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004462 if (ssid == wpa_s->current_ssid) {
4463 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4464 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004465 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004466 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468
4469 was_disabled = ssid->disabled;
4470
4471 ssid->disabled = 1;
4472
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004473 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004474 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004475 if (wpa_s->sched_scanning) {
4476 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4477 "to remove network from filters");
4478 wpa_supplicant_cancel_sched_scan(wpa_s);
4479 wpa_supplicant_req_scan(wpa_s, 0, 0);
4480 }
4481 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004482 }
4483}
4484
4485
4486/**
4487 * wpa_supplicant_select_network - Attempt association with a network
4488 * @wpa_s: wpa_supplicant structure for a network interface
4489 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4490 */
4491void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4492 struct wpa_ssid *ssid)
4493{
4494
4495 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004496 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004497
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004498 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004499 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4500 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004501 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004502 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004503 disconnected = 1;
4504 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004505
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004506 if (ssid)
4507 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004509 /*
4510 * Mark all other networks disabled or mark all networks enabled if no
4511 * network specified.
4512 */
4513 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4514 other_ssid = other_ssid->next) {
4515 int was_disabled = other_ssid->disabled;
4516 if (was_disabled == 2)
4517 continue; /* do not change persistent P2P group data */
4518
4519 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004520 if (was_disabled && !other_ssid->disabled)
4521 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522
4523 if (was_disabled != other_ssid->disabled)
4524 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4525 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004526
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004527 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4528 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004529 /* We are already associated with the selected network */
4530 wpa_printf(MSG_DEBUG, "Already associated with the "
4531 "selected network - do nothing");
4532 return;
4533 }
4534
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004535 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004536 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004537 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004538 wpa_s->connect_without_scan =
4539 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004540
4541 /*
4542 * Don't optimize next scan freqs since a new ESS has been
4543 * selected.
4544 */
4545 os_free(wpa_s->next_scan_freqs);
4546 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004547 } else {
4548 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004549 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004550
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 wpa_s->disconnected = 0;
4552 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004553 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004554 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004555 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004556 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004557 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4558 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004559
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004560 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004561 wpa_supplicant_fast_associate(wpa_s) != 1) {
4562 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004563 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004564 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004565 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004566
4567 if (ssid)
4568 wpas_notify_network_selected(wpa_s, ssid);
4569}
4570
4571
4572/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004573 * wpas_remove_cred - Remove the specified credential and all the network
4574 * entries created based on the removed credential
4575 * @wpa_s: wpa_supplicant structure for a network interface
4576 * @cred: The credential to remove
4577 * Returns: 0 on success, -1 on failure
4578 */
4579int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4580{
4581 struct wpa_ssid *ssid, *next;
4582 int id;
4583
4584 if (!cred) {
4585 wpa_printf(MSG_DEBUG, "Could not find cred");
4586 return -1;
4587 }
4588
4589 id = cred->id;
4590 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4591 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4592 return -1;
4593 }
4594
4595 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4596
4597 /* Remove any network entry created based on the removed credential */
4598 ssid = wpa_s->conf->ssid;
4599 while (ssid) {
4600 next = ssid->next;
4601
4602 if (ssid->parent_cred == cred) {
4603 wpa_printf(MSG_DEBUG,
4604 "Remove network id %d since it used the removed credential",
4605 ssid->id);
4606 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4607 -1) {
4608 wpa_printf(MSG_DEBUG,
4609 "Could not find network id=%d",
4610 ssid->id);
4611 }
4612 }
4613
4614 ssid = next;
4615 }
4616
4617 return 0;
4618}
4619
4620
4621/**
4622 * wpas_remove_cred - Remove all the Interworking credentials
4623 * @wpa_s: wpa_supplicant structure for a network interface
4624 * Returns: 0 on success, -1 on failure
4625 */
4626int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4627{
4628 int res, ret = 0;
4629 struct wpa_cred *cred, *prev;
4630
4631 cred = wpa_s->conf->cred;
4632 while (cred) {
4633 prev = cred;
4634 cred = cred->next;
4635 res = wpas_remove_cred(wpa_s, prev);
4636 if (res < 0) {
4637 wpa_printf(MSG_DEBUG,
4638 "Removal of all credentials failed - failed to remove credential id=%d",
4639 prev->id);
4640 ret = -1;
4641 }
4642 }
4643
4644 return ret;
4645}
4646
4647
4648/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004649 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4650 * @wpa_s: wpa_supplicant structure for a network interface
4651 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4652 * @pkcs11_module_path: PKCS #11 module path or NULL
4653 * Returns: 0 on success; -1 on failure
4654 *
4655 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4656 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4657 * module path fails the paths will be reset to the default value (NULL).
4658 */
4659int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4660 const char *pkcs11_engine_path,
4661 const char *pkcs11_module_path)
4662{
4663 char *pkcs11_engine_path_copy = NULL;
4664 char *pkcs11_module_path_copy = NULL;
4665
4666 if (pkcs11_engine_path != NULL) {
4667 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4668 if (pkcs11_engine_path_copy == NULL)
4669 return -1;
4670 }
4671 if (pkcs11_module_path != NULL) {
4672 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004673 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004674 os_free(pkcs11_engine_path_copy);
4675 return -1;
4676 }
4677 }
4678
4679 os_free(wpa_s->conf->pkcs11_engine_path);
4680 os_free(wpa_s->conf->pkcs11_module_path);
4681 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4682 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4683
4684 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4685 eapol_sm_deinit(wpa_s->eapol);
4686 wpa_s->eapol = NULL;
4687 if (wpa_supplicant_init_eapol(wpa_s)) {
4688 /* Error -> Reset paths to the default value (NULL) once. */
4689 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4690 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4691 NULL);
4692
4693 return -1;
4694 }
4695 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4696
4697 return 0;
4698}
4699
4700
4701/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4703 * @wpa_s: wpa_supplicant structure for a network interface
4704 * @ap_scan: AP scan mode
4705 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4706 *
4707 */
4708int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4709{
4710
4711 int old_ap_scan;
4712
4713 if (ap_scan < 0 || ap_scan > 2)
4714 return -1;
4715
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004716 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4717 wpa_printf(MSG_INFO,
4718 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4719 }
4720
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004721#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004722 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4723 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4724 wpa_s->wpa_state < WPA_COMPLETED) {
4725 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4726 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004727 return 0;
4728 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004729#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004731 old_ap_scan = wpa_s->conf->ap_scan;
4732 wpa_s->conf->ap_scan = ap_scan;
4733
4734 if (old_ap_scan != wpa_s->conf->ap_scan)
4735 wpas_notify_ap_scan_changed(wpa_s);
4736
4737 return 0;
4738}
4739
4740
4741/**
4742 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4743 * @wpa_s: wpa_supplicant structure for a network interface
4744 * @expire_age: Expiration age in seconds
4745 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4746 *
4747 */
4748int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4749 unsigned int bss_expire_age)
4750{
4751 if (bss_expire_age < 10) {
4752 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4753 bss_expire_age);
4754 return -1;
4755 }
4756 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4757 bss_expire_age);
4758 wpa_s->conf->bss_expiration_age = bss_expire_age;
4759
4760 return 0;
4761}
4762
4763
4764/**
4765 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4766 * @wpa_s: wpa_supplicant structure for a network interface
4767 * @expire_count: number of scans after which an unseen BSS is reclaimed
4768 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4769 *
4770 */
4771int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4772 unsigned int bss_expire_count)
4773{
4774 if (bss_expire_count < 1) {
4775 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4776 bss_expire_count);
4777 return -1;
4778 }
4779 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4780 bss_expire_count);
4781 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4782
4783 return 0;
4784}
4785
4786
4787/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004788 * wpa_supplicant_set_scan_interval - Set scan interval
4789 * @wpa_s: wpa_supplicant structure for a network interface
4790 * @scan_interval: scan interval in seconds
4791 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4792 *
4793 */
4794int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4795 int scan_interval)
4796{
4797 if (scan_interval < 0) {
4798 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4799 scan_interval);
4800 return -1;
4801 }
4802 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4803 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004804 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004805
4806 return 0;
4807}
4808
4809
4810/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004811 * wpa_supplicant_set_debug_params - Set global debug params
4812 * @global: wpa_global structure
4813 * @debug_level: debug level
4814 * @debug_timestamp: determines if show timestamp in debug data
4815 * @debug_show_keys: determines if show keys in debug data
4816 * Returns: 0 if succeed or -1 if debug_level has wrong value
4817 */
4818int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4819 int debug_timestamp, int debug_show_keys)
4820{
4821
4822 int old_level, old_timestamp, old_show_keys;
4823
4824 /* check for allowed debuglevels */
4825 if (debug_level != MSG_EXCESSIVE &&
4826 debug_level != MSG_MSGDUMP &&
4827 debug_level != MSG_DEBUG &&
4828 debug_level != MSG_INFO &&
4829 debug_level != MSG_WARNING &&
4830 debug_level != MSG_ERROR)
4831 return -1;
4832
4833 old_level = wpa_debug_level;
4834 old_timestamp = wpa_debug_timestamp;
4835 old_show_keys = wpa_debug_show_keys;
4836
4837 wpa_debug_level = debug_level;
4838 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4839 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4840
4841 if (wpa_debug_level != old_level)
4842 wpas_notify_debug_level_changed(global);
4843 if (wpa_debug_timestamp != old_timestamp)
4844 wpas_notify_debug_timestamp_changed(global);
4845 if (wpa_debug_show_keys != old_show_keys)
4846 wpas_notify_debug_show_keys_changed(global);
4847
4848 return 0;
4849}
4850
4851
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004852#ifdef CONFIG_OWE
4853static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4854 const u8 *entry_ssid, size_t entry_ssid_len)
4855{
4856 const u8 *owe, *pos, *end;
4857 u8 ssid_len;
4858 struct wpa_bss *bss;
4859
4860 /* Check network profile SSID aganst the SSID in the
4861 * OWE Transition Mode element. */
4862
4863 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4864 if (!bss)
4865 return 0;
4866
4867 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4868 if (!owe)
4869 return 0;
4870
4871 pos = owe + 6;
4872 end = owe + 2 + owe[1];
4873
4874 if (end - pos < ETH_ALEN + 1)
4875 return 0;
4876 pos += ETH_ALEN;
4877 ssid_len = *pos++;
4878 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4879 return 0;
4880
4881 return entry_ssid_len == ssid_len &&
4882 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4883}
4884#endif /* CONFIG_OWE */
4885
4886
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004887/**
4888 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4889 * @wpa_s: Pointer to wpa_supplicant data
4890 * Returns: A pointer to the current network structure or %NULL on failure
4891 */
4892struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4893{
4894 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004895 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004896 int res;
4897 size_t ssid_len;
4898 u8 bssid[ETH_ALEN];
4899 int wired;
4900
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004901 res = wpa_drv_get_ssid(wpa_s, ssid);
4902 if (res < 0) {
4903 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4904 "driver");
4905 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004906 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004907 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004909 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4911 "driver");
4912 return NULL;
4913 }
4914
4915 wired = wpa_s->conf->ap_scan == 0 &&
4916 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4917
4918 entry = wpa_s->conf->ssid;
4919 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004920 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004921 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004922 (!entry->ssid ||
4923 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4924 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 (!entry->bssid_set ||
4926 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4927 return entry;
4928#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004929 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004930 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4931 (entry->ssid == NULL || entry->ssid_len == 0) &&
4932 (!entry->bssid_set ||
4933 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4934 return entry;
4935#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004936
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004937#ifdef CONFIG_OWE
4938 if (!wpas_network_disabled(wpa_s, entry) &&
4939 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4940 entry->ssid_len) &&
4941 (!entry->bssid_set ||
4942 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4943 return entry;
4944#endif /* CONFIG_OWE */
4945
Dmitry Shmidt04949592012-07-19 12:16:46 -07004946 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004947 entry->ssid_len == 0 &&
4948 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4949 return entry;
4950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004951 entry = entry->next;
4952 }
4953
4954 return NULL;
4955}
4956
4957
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004958static int select_driver(struct wpa_supplicant *wpa_s, int i)
4959{
4960 struct wpa_global *global = wpa_s->global;
4961
4962 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004963 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004964 if (global->drv_priv[i] == NULL) {
4965 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4966 "'%s'", wpa_drivers[i]->name);
4967 return -1;
4968 }
4969 }
4970
4971 wpa_s->driver = wpa_drivers[i];
4972 wpa_s->global_drv_priv = global->drv_priv[i];
4973
4974 return 0;
4975}
4976
4977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004978static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4979 const char *name)
4980{
4981 int i;
4982 size_t len;
4983 const char *pos, *driver = name;
4984
4985 if (wpa_s == NULL)
4986 return -1;
4987
4988 if (wpa_drivers[0] == NULL) {
4989 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4990 "wpa_supplicant");
4991 return -1;
4992 }
4993
4994 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004995 /* Default to first successful driver in the list */
4996 for (i = 0; wpa_drivers[i]; i++) {
4997 if (select_driver(wpa_s, i) == 0)
4998 return 0;
4999 }
5000 /* Drivers have each reported failure, so no wpa_msg() here. */
5001 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005002 }
5003
5004 do {
5005 pos = os_strchr(driver, ',');
5006 if (pos)
5007 len = pos - driver;
5008 else
5009 len = os_strlen(driver);
5010
5011 for (i = 0; wpa_drivers[i]; i++) {
5012 if (os_strlen(wpa_drivers[i]->name) == len &&
5013 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005014 0) {
5015 /* First driver that succeeds wins */
5016 if (select_driver(wpa_s, i) == 0)
5017 return 0;
5018 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005019 }
5020
5021 driver = pos + 1;
5022 } while (pos);
5023
5024 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5025 return -1;
5026}
5027
5028
5029/**
5030 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5031 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5032 * with struct wpa_driver_ops::init()
5033 * @src_addr: Source address of the EAPOL frame
5034 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5035 * @len: Length of the EAPOL data
5036 *
5037 * This function is called for each received EAPOL frame. Most driver
5038 * interfaces rely on more generic OS mechanism for receiving frames through
5039 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5040 * take care of received EAPOL frames and deliver them to the core supplicant
5041 * code by calling this function.
5042 */
5043void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
5044 const u8 *buf, size_t len)
5045{
5046 struct wpa_supplicant *wpa_s = ctx;
5047
5048 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
5049 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5050
Hai Shalomc1a21442022-02-04 13:43:00 -08005051 if (wpa_s->own_disconnect_req) {
5052 wpa_printf(MSG_DEBUG,
5053 "Drop received EAPOL frame as we are disconnecting");
5054 return;
5055 }
5056
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005057#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005058 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5059 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005060 if (wpa_s->ignore_auth_resp) {
5061 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5062 return;
5063 }
5064#endif /* CONFIG_TESTING_OPTIONS */
5065
Jouni Malinena05074c2012-12-21 21:35:35 +02005066 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5067 (wpa_s->last_eapol_matches_bssid &&
5068#ifdef CONFIG_AP
5069 !wpa_s->ap_iface &&
5070#endif /* CONFIG_AP */
5071 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005072 /*
5073 * There is possible race condition between receiving the
5074 * association event and the EAPOL frame since they are coming
5075 * through different paths from the driver. In order to avoid
5076 * issues in trying to process the EAPOL frame before receiving
5077 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005078 * the association event is received. This may also be needed in
5079 * driver-based roaming case, so also use src_addr != BSSID as a
5080 * trigger if we have previously confirmed that the
5081 * Authenticator uses BSSID as the src_addr (which is not the
5082 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005083 */
5084 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005085 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5086 wpa_supplicant_state_txt(wpa_s->wpa_state),
5087 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005088 wpabuf_free(wpa_s->pending_eapol_rx);
5089 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5090 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005091 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005092 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5093 ETH_ALEN);
5094 }
5095 return;
5096 }
5097
Jouni Malinena05074c2012-12-21 21:35:35 +02005098 wpa_s->last_eapol_matches_bssid =
5099 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005101#ifdef CONFIG_AP
5102 if (wpa_s->ap_iface) {
5103 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
5104 return;
5105 }
5106#endif /* CONFIG_AP */
5107
5108 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5109 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5110 "no key management is configured");
5111 return;
5112 }
5113
5114 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005115 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5117 wpa_s->wpa_state != WPA_COMPLETED) &&
5118 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005119 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005120 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005121 int timeout = 10;
5122
5123 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5124 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5125 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5126 /* Use longer timeout for IEEE 802.1X/EAP */
5127 timeout = 70;
5128 }
5129
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005130#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005131 if (wpa_s->current_ssid && wpa_s->current_bss &&
5132 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5133 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5134 /*
5135 * Use shorter timeout if going through WPS AP iteration
5136 * for PIN config method with an AP that does not
5137 * advertise Selected Registrar.
5138 */
5139 struct wpabuf *wps_ie;
5140
5141 wps_ie = wpa_bss_get_vendor_ie_multi(
5142 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5143 if (wps_ie &&
5144 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5145 timeout = 10;
5146 wpabuf_free(wps_ie);
5147 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005148#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005149
5150 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151 }
5152 wpa_s->eapol_received++;
5153
5154 if (wpa_s->countermeasures) {
5155 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5156 "EAPOL packet");
5157 return;
5158 }
5159
5160#ifdef CONFIG_IBSS_RSN
5161 if (wpa_s->current_ssid &&
5162 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
5163 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
5164 return;
5165 }
5166#endif /* CONFIG_IBSS_RSN */
5167
5168 /* Source address of the incoming EAPOL frame could be compared to the
5169 * current BSSID. However, it is possible that a centralized
5170 * Authenticator could be using another MAC address than the BSSID of
5171 * an AP, so just allow any address to be used for now. The replies are
5172 * still sent to the current BSSID (if available), though. */
5173
5174 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5175 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005176 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5177 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005178 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
5179 return;
5180 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005181 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005182 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
5183 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5184 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005185 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005186 * handshake processing which would normally set portValid. We
5187 * need this to allow the EAPOL state machines to be completed
5188 * without going through EAPOL-Key handshake.
5189 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005190 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005191 }
5192}
5193
5194
Hai Shalomb755a2a2020-04-23 21:49:02 -07005195static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5196{
5197 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5198 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5199}
5200
5201
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005202int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005204 if ((!wpa_s->p2p_mgmt ||
5205 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5206 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005207 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005208 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5209 wpa_drv_get_mac_addr(wpa_s),
5210 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005211 wpas_eapol_needs_l2_packet(wpa_s) ?
5212 wpa_supplicant_rx_eapol : NULL,
5213 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005214 if (wpa_s->l2 == NULL)
5215 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005216
5217 if (l2_packet_set_packet_filter(wpa_s->l2,
5218 L2_PACKET_FILTER_PKTTYPE))
5219 wpa_dbg(wpa_s, MSG_DEBUG,
5220 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005221
5222 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5223 wpa_msg(wpa_s, MSG_ERROR,
5224 "Failed to get own L2 address");
5225 return -1;
5226 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005227 } else {
5228 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5229 if (addr)
5230 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5231 }
5232
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005233 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005234 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005235
Hai Shalomc3565922019-10-28 11:58:20 -07005236#ifdef CONFIG_FST
5237 if (wpa_s->fst)
5238 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5239#endif /* CONFIG_FST */
5240
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005241 return 0;
5242}
5243
5244
Dmitry Shmidt04949592012-07-19 12:16:46 -07005245static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5246 const u8 *buf, size_t len)
5247{
5248 struct wpa_supplicant *wpa_s = ctx;
5249 const struct l2_ethhdr *eth;
5250
5251 if (len < sizeof(*eth))
5252 return;
5253 eth = (const struct l2_ethhdr *) buf;
5254
5255 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5256 !(eth->h_dest[0] & 0x01)) {
5257 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5258 " (bridge - not for this interface - ignore)",
5259 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5260 return;
5261 }
5262
5263 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5264 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5265 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5266 len - sizeof(*eth));
5267}
5268
5269
Hai Shalom899fcc72020-10-19 14:38:18 -07005270int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5271 const char *bridge_ifname)
5272{
5273 if (wpa_s->wpa_state > WPA_SCANNING)
5274 return -EBUSY;
5275
5276 if (bridge_ifname &&
5277 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5278 return -EINVAL;
5279
5280 if (!bridge_ifname)
5281 bridge_ifname = "";
5282
5283 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5284 return 0;
5285
5286 if (wpa_s->l2_br) {
5287 l2_packet_deinit(wpa_s->l2_br);
5288 wpa_s->l2_br = NULL;
5289 }
5290
5291 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5292 sizeof(wpa_s->bridge_ifname));
5293
5294 if (wpa_s->bridge_ifname[0]) {
5295 wpa_dbg(wpa_s, MSG_DEBUG,
5296 "Receiving packets from bridge interface '%s'",
5297 wpa_s->bridge_ifname);
5298 wpa_s->l2_br = l2_packet_init_bridge(
5299 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5300 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5301 if (!wpa_s->l2_br) {
5302 wpa_msg(wpa_s, MSG_ERROR,
5303 "Failed to open l2_packet connection for the bridge interface '%s'",
5304 wpa_s->bridge_ifname);
5305 goto fail;
5306 }
5307 }
5308
5309#ifdef CONFIG_TDLS
5310 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5311 goto fail;
5312#endif /* CONFIG_TDLS */
5313
5314 return 0;
5315fail:
5316 wpa_s->bridge_ifname[0] = 0;
5317 if (wpa_s->l2_br) {
5318 l2_packet_deinit(wpa_s->l2_br);
5319 wpa_s->l2_br = NULL;
5320 }
5321#ifdef CONFIG_TDLS
5322 if (!wpa_s->p2p_mgmt)
5323 wpa_tdls_init(wpa_s->wpa);
5324#endif /* CONFIG_TDLS */
5325 return -EIO;
5326}
5327
5328
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005329/**
5330 * wpa_supplicant_driver_init - Initialize driver interface parameters
5331 * @wpa_s: Pointer to wpa_supplicant data
5332 * Returns: 0 on success, -1 on failure
5333 *
5334 * This function is called to initialize driver interface parameters.
5335 * wpa_drv_init() must have been called before this function to initialize the
5336 * driver interface.
5337 */
5338int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5339{
5340 static int interface_count = 0;
5341
5342 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5343 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005344
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005345 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5346 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005347 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005348 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5349
Hai Shalomb755a2a2020-04-23 21:49:02 -07005350 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005351 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5352 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005353 wpa_s->l2_br = l2_packet_init_bridge(
5354 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5355 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005356 if (wpa_s->l2_br == NULL) {
5357 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5358 "connection for the bridge interface '%s'",
5359 wpa_s->bridge_ifname);
5360 return -1;
5361 }
5362 }
5363
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005364 if (wpa_s->conf->ap_scan == 2 &&
5365 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5366 wpa_printf(MSG_INFO,
5367 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5368 }
5369
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005370 wpa_clear_keys(wpa_s, NULL);
5371
5372 /* Make sure that TKIP countermeasures are not left enabled (could
5373 * happen if wpa_supplicant is killed during countermeasures. */
5374 wpa_drv_set_countermeasures(wpa_s, 0);
5375
5376 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5377 wpa_drv_flush_pmkid(wpa_s);
5378
5379 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005380 wpa_s->prev_scan_wildcard = 0;
5381
Dmitry Shmidt04949592012-07-19 12:16:46 -07005382 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005383 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5384 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5385 interface_count = 0;
5386 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005387#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005388 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005389 wpa_supplicant_delayed_sched_scan(wpa_s,
5390 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005391 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005392 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005393 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005394#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005395 interface_count++;
5396 } else
5397 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5398
5399 return 0;
5400}
5401
5402
5403static int wpa_supplicant_daemon(const char *pid_file)
5404{
5405 wpa_printf(MSG_DEBUG, "Daemonize..");
5406 return os_daemonize(pid_file);
5407}
5408
5409
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005410static struct wpa_supplicant *
5411wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005412{
5413 struct wpa_supplicant *wpa_s;
5414
5415 wpa_s = os_zalloc(sizeof(*wpa_s));
5416 if (wpa_s == NULL)
5417 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005418 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005419 wpa_s->scan_interval = 5;
5420 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005421 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005422 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005423 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005424 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005425
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005426 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005427 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005428#ifdef CONFIG_TESTING_OPTIONS
5429 dl_list_init(&wpa_s->drv_signal_override);
5430#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005431 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005433 return wpa_s;
5434}
5435
5436
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005437#ifdef CONFIG_HT_OVERRIDES
5438
5439static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5440 struct ieee80211_ht_capabilities *htcaps,
5441 struct ieee80211_ht_capabilities *htcaps_mask,
5442 const char *ht_mcs)
5443{
5444 /* parse ht_mcs into hex array */
5445 int i;
5446 const char *tmp = ht_mcs;
5447 char *end = NULL;
5448
5449 /* If ht_mcs is null, do not set anything */
5450 if (!ht_mcs)
5451 return 0;
5452
5453 /* This is what we are setting in the kernel */
5454 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5455
5456 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5457
5458 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005459 long v;
5460
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005461 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005462 v = strtol(tmp, &end, 16);
5463
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005464 if (errno == 0) {
5465 wpa_msg(wpa_s, MSG_DEBUG,
5466 "htcap value[%i]: %ld end: %p tmp: %p",
5467 i, v, end, tmp);
5468 if (end == tmp)
5469 break;
5470
5471 htcaps->supported_mcs_set[i] = v;
5472 tmp = end;
5473 } else {
5474 wpa_msg(wpa_s, MSG_ERROR,
5475 "Failed to parse ht-mcs: %s, error: %s\n",
5476 ht_mcs, strerror(errno));
5477 return -1;
5478 }
5479 }
5480
5481 /*
5482 * If we were able to parse any values, then set mask for the MCS set.
5483 */
5484 if (i) {
5485 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5486 IEEE80211_HT_MCS_MASK_LEN - 1);
5487 /* skip the 3 reserved bits */
5488 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5489 0x1f;
5490 }
5491
5492 return 0;
5493}
5494
5495
5496static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5497 struct ieee80211_ht_capabilities *htcaps,
5498 struct ieee80211_ht_capabilities *htcaps_mask,
5499 int disabled)
5500{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005501 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005502
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005503 if (disabled == -1)
5504 return 0;
5505
Hai Shalom74f70d42019-02-11 14:42:39 -08005506 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5507
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005508 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5509 htcaps_mask->ht_capabilities_info |= msk;
5510 if (disabled)
5511 htcaps->ht_capabilities_info &= msk;
5512 else
5513 htcaps->ht_capabilities_info |= msk;
5514
5515 return 0;
5516}
5517
5518
5519static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5520 struct ieee80211_ht_capabilities *htcaps,
5521 struct ieee80211_ht_capabilities *htcaps_mask,
5522 int factor)
5523{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005524 if (factor == -1)
5525 return 0;
5526
Hai Shalom74f70d42019-02-11 14:42:39 -08005527 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5528
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005529 if (factor < 0 || factor > 3) {
5530 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5531 "Must be 0-3 or -1", factor);
5532 return -EINVAL;
5533 }
5534
5535 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5536 htcaps->a_mpdu_params &= ~0x3;
5537 htcaps->a_mpdu_params |= factor & 0x3;
5538
5539 return 0;
5540}
5541
5542
5543static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5544 struct ieee80211_ht_capabilities *htcaps,
5545 struct ieee80211_ht_capabilities *htcaps_mask,
5546 int density)
5547{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005548 if (density == -1)
5549 return 0;
5550
Hai Shalom74f70d42019-02-11 14:42:39 -08005551 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5552
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005553 if (density < 0 || density > 7) {
5554 wpa_msg(wpa_s, MSG_ERROR,
5555 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5556 density);
5557 return -EINVAL;
5558 }
5559
5560 htcaps_mask->a_mpdu_params |= 0x1C;
5561 htcaps->a_mpdu_params &= ~(0x1C);
5562 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5563
5564 return 0;
5565}
5566
5567
5568static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5569 struct ieee80211_ht_capabilities *htcaps,
5570 struct ieee80211_ht_capabilities *htcaps_mask,
5571 int disabled)
5572{
Hai Shalom74f70d42019-02-11 14:42:39 -08005573 if (disabled)
5574 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005575
Paul Stewart092955c2017-02-06 09:13:09 -08005576 set_disable_ht40(htcaps, disabled);
5577 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005578
5579 return 0;
5580}
5581
5582
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005583static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5584 struct ieee80211_ht_capabilities *htcaps,
5585 struct ieee80211_ht_capabilities *htcaps_mask,
5586 int disabled)
5587{
5588 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005589 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5590 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005591
Hai Shalom74f70d42019-02-11 14:42:39 -08005592 if (disabled)
5593 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005594
5595 if (disabled)
5596 htcaps->ht_capabilities_info &= ~msk;
5597 else
5598 htcaps->ht_capabilities_info |= msk;
5599
5600 htcaps_mask->ht_capabilities_info |= msk;
5601
5602 return 0;
5603}
5604
5605
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005606static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5607 struct ieee80211_ht_capabilities *htcaps,
5608 struct ieee80211_ht_capabilities *htcaps_mask,
5609 int disabled)
5610{
5611 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005612 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005613
Hai Shalom74f70d42019-02-11 14:42:39 -08005614 if (disabled)
5615 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005616
5617 if (disabled)
5618 htcaps->ht_capabilities_info &= ~msk;
5619 else
5620 htcaps->ht_capabilities_info |= msk;
5621
5622 htcaps_mask->ht_capabilities_info |= msk;
5623
5624 return 0;
5625}
5626
5627
Hai Shalom74f70d42019-02-11 14:42:39 -08005628static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5629 struct ieee80211_ht_capabilities *htcaps,
5630 struct ieee80211_ht_capabilities *htcaps_mask,
5631 int tx_stbc)
5632{
5633 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5634
5635 if (tx_stbc == -1)
5636 return 0;
5637
5638 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5639
5640 if (tx_stbc < 0 || tx_stbc > 1) {
5641 wpa_msg(wpa_s, MSG_ERROR,
5642 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5643 return -EINVAL;
5644 }
5645
5646 htcaps_mask->ht_capabilities_info |= msk;
5647 htcaps->ht_capabilities_info &= ~msk;
5648 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5649
5650 return 0;
5651}
5652
5653
5654static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5655 struct ieee80211_ht_capabilities *htcaps,
5656 struct ieee80211_ht_capabilities *htcaps_mask,
5657 int rx_stbc)
5658{
5659 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5660
5661 if (rx_stbc == -1)
5662 return 0;
5663
5664 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5665
5666 if (rx_stbc < 0 || rx_stbc > 3) {
5667 wpa_msg(wpa_s, MSG_ERROR,
5668 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5669 return -EINVAL;
5670 }
5671
5672 htcaps_mask->ht_capabilities_info |= msk;
5673 htcaps->ht_capabilities_info &= ~msk;
5674 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5675
5676 return 0;
5677}
5678
5679
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005680void wpa_supplicant_apply_ht_overrides(
5681 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5682 struct wpa_driver_associate_params *params)
5683{
5684 struct ieee80211_ht_capabilities *htcaps;
5685 struct ieee80211_ht_capabilities *htcaps_mask;
5686
5687 if (!ssid)
5688 return;
5689
5690 params->disable_ht = ssid->disable_ht;
5691 if (!params->htcaps || !params->htcaps_mask)
5692 return;
5693
5694 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5695 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5696 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5697 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5698 ssid->disable_max_amsdu);
5699 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5700 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5701 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005702 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005703 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005704 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5705 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005706
5707 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005708 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005709 htcaps->ht_capabilities_info |= bit;
5710 htcaps_mask->ht_capabilities_info |= bit;
5711 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005712}
5713
5714#endif /* CONFIG_HT_OVERRIDES */
5715
5716
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005717#ifdef CONFIG_VHT_OVERRIDES
5718void wpa_supplicant_apply_vht_overrides(
5719 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5720 struct wpa_driver_associate_params *params)
5721{
5722 struct ieee80211_vht_capabilities *vhtcaps;
5723 struct ieee80211_vht_capabilities *vhtcaps_mask;
5724
5725 if (!ssid)
5726 return;
5727
5728 params->disable_vht = ssid->disable_vht;
5729
5730 vhtcaps = (void *) params->vhtcaps;
5731 vhtcaps_mask = (void *) params->vhtcaps_mask;
5732
5733 if (!vhtcaps || !vhtcaps_mask)
5734 return;
5735
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005736 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5737 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005738
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005739#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005740 if (ssid->disable_sgi) {
5741 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5742 VHT_CAP_SHORT_GI_160);
5743 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5744 VHT_CAP_SHORT_GI_160);
5745 wpa_msg(wpa_s, MSG_DEBUG,
5746 "disable-sgi override specified, vht-caps: 0x%x",
5747 vhtcaps->vht_capabilities_info);
5748 }
5749
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005750 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005751 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5752 int max_ampdu;
5753
5754 max_ampdu = (ssid->vht_capa &
5755 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5756 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005757
5758 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5759 wpa_set_ampdu_factor(wpa_s,
5760 (void *) params->htcaps,
5761 (void *) params->htcaps_mask,
5762 max_ampdu);
5763 }
5764#endif /* CONFIG_HT_OVERRIDES */
5765
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005766#define OVERRIDE_MCS(i) \
5767 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5768 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005769 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005770 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005771 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5772 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005773 } \
5774 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5775 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005776 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005777 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005778 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5779 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005780 }
5781
5782 OVERRIDE_MCS(1);
5783 OVERRIDE_MCS(2);
5784 OVERRIDE_MCS(3);
5785 OVERRIDE_MCS(4);
5786 OVERRIDE_MCS(5);
5787 OVERRIDE_MCS(6);
5788 OVERRIDE_MCS(7);
5789 OVERRIDE_MCS(8);
5790}
5791#endif /* CONFIG_VHT_OVERRIDES */
5792
5793
Hai Shalomfdcde762020-04-02 11:19:20 -07005794#ifdef CONFIG_HE_OVERRIDES
5795void wpa_supplicant_apply_he_overrides(
5796 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5797 struct wpa_driver_associate_params *params)
5798{
5799 if (!ssid)
5800 return;
5801
5802 params->disable_he = ssid->disable_he;
5803}
5804#endif /* CONFIG_HE_OVERRIDES */
5805
5806
Dmitry Shmidt04949592012-07-19 12:16:46 -07005807static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5808{
5809#ifdef PCSC_FUNCS
5810 size_t len;
5811
5812 if (!wpa_s->conf->pcsc_reader)
5813 return 0;
5814
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005815 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005816 if (!wpa_s->scard)
5817 return 1;
5818
5819 if (wpa_s->conf->pcsc_pin &&
5820 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5821 scard_deinit(wpa_s->scard);
5822 wpa_s->scard = NULL;
5823 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5824 return -1;
5825 }
5826
5827 len = sizeof(wpa_s->imsi) - 1;
5828 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5829 scard_deinit(wpa_s->scard);
5830 wpa_s->scard = NULL;
5831 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5832 return -1;
5833 }
5834 wpa_s->imsi[len] = '\0';
5835
5836 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5837
5838 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5839 wpa_s->imsi, wpa_s->mnc_len);
5840
5841 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5842 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5843#endif /* PCSC_FUNCS */
5844
5845 return 0;
5846}
5847
5848
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005849int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5850{
5851 char *val, *pos;
5852
5853 ext_password_deinit(wpa_s->ext_pw);
5854 wpa_s->ext_pw = NULL;
5855 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5856
5857 if (!wpa_s->conf->ext_password_backend)
5858 return 0;
5859
5860 val = os_strdup(wpa_s->conf->ext_password_backend);
5861 if (val == NULL)
5862 return -1;
5863 pos = os_strchr(val, ':');
5864 if (pos)
5865 *pos++ = '\0';
5866
5867 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5868
5869 wpa_s->ext_pw = ext_password_init(val, pos);
5870 os_free(val);
5871 if (wpa_s->ext_pw == NULL) {
5872 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5873 return -1;
5874 }
5875 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5876
5877 return 0;
5878}
5879
5880
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005881#ifdef CONFIG_FST
5882
5883static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5884{
5885 struct wpa_supplicant *wpa_s = ctx;
5886
5887 return (is_zero_ether_addr(wpa_s->bssid) ||
5888 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5889}
5890
5891
5892static void wpas_fst_get_channel_info_cb(void *ctx,
5893 enum hostapd_hw_mode *hw_mode,
5894 u8 *channel)
5895{
5896 struct wpa_supplicant *wpa_s = ctx;
5897
5898 if (wpa_s->current_bss) {
5899 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5900 channel);
5901 } else if (wpa_s->hw.num_modes) {
5902 *hw_mode = wpa_s->hw.modes[0].mode;
5903 } else {
5904 WPA_ASSERT(0);
5905 *hw_mode = 0;
5906 }
5907}
5908
5909
5910static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5911{
5912 struct wpa_supplicant *wpa_s = ctx;
5913
5914 *modes = wpa_s->hw.modes;
5915 return wpa_s->hw.num_modes;
5916}
5917
5918
5919static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5920{
5921 struct wpa_supplicant *wpa_s = ctx;
5922
5923 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5924 wpa_s->fst_ies = fst_ies;
5925}
5926
5927
5928static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5929{
5930 struct wpa_supplicant *wpa_s = ctx;
5931
Paul Stewart092955c2017-02-06 09:13:09 -08005932 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5933 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5934 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5935 return -1;
5936 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005937 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005938 wpa_s->own_addr, wpa_s->bssid,
5939 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005940 0);
5941}
5942
5943
5944static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5945{
5946 struct wpa_supplicant *wpa_s = ctx;
5947
5948 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5949 return wpa_s->received_mb_ies;
5950}
5951
5952
5953static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5954 const u8 *buf, size_t size)
5955{
5956 struct wpa_supplicant *wpa_s = ctx;
5957 struct mb_ies_info info;
5958
5959 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5960
5961 if (!mb_ies_info_by_ies(&info, buf, size)) {
5962 wpabuf_free(wpa_s->received_mb_ies);
5963 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5964 }
5965}
5966
5967
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005968static const u8 * wpas_fst_get_peer_first(void *ctx,
5969 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005970 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005971{
5972 struct wpa_supplicant *wpa_s = ctx;
5973
5974 *get_ctx = NULL;
5975 if (!is_zero_ether_addr(wpa_s->bssid))
5976 return (wpa_s->received_mb_ies || !mb_only) ?
5977 wpa_s->bssid : NULL;
5978 return NULL;
5979}
5980
5981
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005982static const u8 * wpas_fst_get_peer_next(void *ctx,
5983 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005984 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005985{
5986 return NULL;
5987}
5988
5989void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5990 struct fst_wpa_obj *iface_obj)
5991{
5992 iface_obj->ctx = wpa_s;
5993 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5994 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5995 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5996 iface_obj->set_ies = wpas_fst_set_ies_cb;
5997 iface_obj->send_action = wpas_fst_send_action_cb;
5998 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5999 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6000 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6001 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6002}
6003#endif /* CONFIG_FST */
6004
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006005static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006006 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006007{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006008 struct wowlan_triggers *triggers;
6009 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006010
6011 if (!wpa_s->conf->wowlan_triggers)
6012 return 0;
6013
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006014 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6015 if (triggers) {
6016 ret = wpa_drv_wowlan(wpa_s, triggers);
6017 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006018 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006019 return ret;
6020}
6021
6022
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006023enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006024{
6025 if (freq < 3000)
6026 return BAND_2_4_GHZ;
6027 if (freq > 50000)
6028 return BAND_60_GHZ;
6029 return BAND_5_GHZ;
6030}
6031
6032
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006033unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006034{
6035 int i;
6036 unsigned int band = 0;
6037
6038 if (freqs) {
6039 /* freqs are specified for the radio work */
6040 for (i = 0; freqs[i]; i++)
6041 band |= wpas_freq_to_band(freqs[i]);
6042 } else {
6043 /*
6044 * freqs are not specified, implies all
6045 * the supported freqs by HW
6046 */
6047 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6048 if (wpa_s->hw.modes[i].num_channels != 0) {
6049 if (wpa_s->hw.modes[i].mode ==
6050 HOSTAPD_MODE_IEEE80211B ||
6051 wpa_s->hw.modes[i].mode ==
6052 HOSTAPD_MODE_IEEE80211G)
6053 band |= BAND_2_4_GHZ;
6054 else if (wpa_s->hw.modes[i].mode ==
6055 HOSTAPD_MODE_IEEE80211A)
6056 band |= BAND_5_GHZ;
6057 else if (wpa_s->hw.modes[i].mode ==
6058 HOSTAPD_MODE_IEEE80211AD)
6059 band |= BAND_60_GHZ;
6060 else if (wpa_s->hw.modes[i].mode ==
6061 HOSTAPD_MODE_IEEE80211ANY)
6062 band = BAND_2_4_GHZ | BAND_5_GHZ |
6063 BAND_60_GHZ;
6064 }
6065 }
6066 }
6067
6068 return band;
6069}
6070
6071
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006072static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6073 const char *rn)
6074{
6075 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6076 struct wpa_radio *radio;
6077
6078 while (rn && iface) {
6079 radio = iface->radio;
6080 if (radio && os_strcmp(rn, radio->name) == 0) {
6081 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6082 wpa_s->ifname, rn);
6083 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6084 return radio;
6085 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006086
6087 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006088 }
6089
6090 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6091 wpa_s->ifname, rn ? rn : "N/A");
6092 radio = os_zalloc(sizeof(*radio));
6093 if (radio == NULL)
6094 return NULL;
6095
6096 if (rn)
6097 os_strlcpy(radio->name, rn, sizeof(radio->name));
6098 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006099 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006100 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6101
6102 return radio;
6103}
6104
6105
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006106static void radio_work_free(struct wpa_radio_work *work)
6107{
6108 if (work->wpa_s->scan_work == work) {
6109 /* This should not really happen. */
6110 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6111 work->type, work, work->started);
6112 work->wpa_s->scan_work = NULL;
6113 }
6114
6115#ifdef CONFIG_P2P
6116 if (work->wpa_s->p2p_scan_work == work) {
6117 /* This should not really happen. */
6118 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6119 work->type, work, work->started);
6120 work->wpa_s->p2p_scan_work = NULL;
6121 }
6122#endif /* CONFIG_P2P */
6123
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006124 if (work->started) {
6125 work->wpa_s->radio->num_active_works--;
6126 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006127 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006128 work->type, work,
6129 work->wpa_s->radio->num_active_works);
6130 }
6131
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006132 dl_list_del(&work->list);
6133 os_free(work);
6134}
6135
6136
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006137static int radio_work_is_connect(struct wpa_radio_work *work)
6138{
6139 return os_strcmp(work->type, "sme-connect") == 0 ||
6140 os_strcmp(work->type, "connect") == 0;
6141}
6142
6143
6144static int radio_work_is_scan(struct wpa_radio_work *work)
6145{
6146 return os_strcmp(work->type, "scan") == 0 ||
6147 os_strcmp(work->type, "p2p-scan") == 0;
6148}
6149
6150
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006151static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6152{
6153 struct wpa_radio_work *active_work = NULL;
6154 struct wpa_radio_work *tmp;
6155
6156 /* Get the active work to know the type and band. */
6157 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6158 if (tmp->started) {
6159 active_work = tmp;
6160 break;
6161 }
6162 }
6163
6164 if (!active_work) {
6165 /* No active work, start one */
6166 radio->num_active_works = 0;
6167 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6168 list) {
6169 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006170 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006171 (((struct wpa_driver_scan_params *)
6172 tmp->ctx)->only_new_results ||
6173 tmp->wpa_s->clear_driver_scan_cache))
6174 continue;
6175 return tmp;
6176 }
6177 return NULL;
6178 }
6179
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006180 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006181 /*
6182 * If the active work is either connect or sme-connect,
6183 * do not parallelize them with other radio works.
6184 */
6185 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6186 "Do not parallelize radio work with %s",
6187 active_work->type);
6188 return NULL;
6189 }
6190
6191 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6192 if (tmp->started)
6193 continue;
6194
6195 /*
6196 * If connect or sme-connect are enqueued, parallelize only
6197 * those operations ahead of them in the queue.
6198 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006199 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006200 break;
6201
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006202 /* Serialize parallel scan and p2p_scan operations on the same
6203 * interface since the driver_nl80211 mechanism for tracking
6204 * scan cookies does not yet have support for this. */
6205 if (active_work->wpa_s == tmp->wpa_s &&
6206 radio_work_is_scan(active_work) &&
6207 radio_work_is_scan(tmp)) {
6208 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6209 "Do not start work '%s' when another work '%s' is already scheduled",
6210 tmp->type, active_work->type);
6211 continue;
6212 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006213 /*
6214 * Check that the radio works are distinct and
6215 * on different bands.
6216 */
6217 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6218 (active_work->bands != tmp->bands)) {
6219 /*
6220 * If a scan has to be scheduled through nl80211 scan
6221 * interface and if an external scan is already running,
6222 * do not schedule the scan since it is likely to get
6223 * rejected by kernel.
6224 */
6225 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006226 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006227 (((struct wpa_driver_scan_params *)
6228 tmp->ctx)->only_new_results ||
6229 tmp->wpa_s->clear_driver_scan_cache))
6230 continue;
6231
6232 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6233 "active_work:%s new_work:%s",
6234 active_work->type, tmp->type);
6235 return tmp;
6236 }
6237 }
6238
6239 /* Did not find a radio work to schedule in parallel. */
6240 return NULL;
6241}
6242
6243
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006244static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6245{
6246 struct wpa_radio *radio = eloop_ctx;
6247 struct wpa_radio_work *work;
6248 struct os_reltime now, diff;
6249 struct wpa_supplicant *wpa_s;
6250
6251 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006252 if (work == NULL) {
6253 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006254 return;
6255 }
6256
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006257 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6258 radio_list);
6259
6260 if (!(wpa_s &&
6261 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6262 if (work->started)
6263 return; /* already started and still in progress */
6264
Hai Shalom60840252021-02-19 19:02:11 -08006265 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006266 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6267 return;
6268 }
6269 } else {
6270 work = NULL;
6271 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6272 /* get the work to schedule next */
6273 work = radio_work_get_next_work(radio);
6274 }
6275 if (!work)
6276 return;
6277 }
6278
6279 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006280 os_get_reltime(&now);
6281 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006282 wpa_dbg(wpa_s, MSG_DEBUG,
6283 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006284 work->type, work, diff.sec, diff.usec);
6285 work->started = 1;
6286 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006287 radio->num_active_works++;
6288
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006289 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006290
6291 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6292 radio->num_active_works < MAX_ACTIVE_WORKS)
6293 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006294}
6295
6296
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006297/*
6298 * This function removes both started and pending radio works running on
6299 * the provided interface's radio.
6300 * Prior to the removal of the radio work, its callback (cb) is called with
6301 * deinit set to be 1. Each work's callback is responsible for clearing its
6302 * internal data and restoring to a correct state.
6303 * @wpa_s: wpa_supplicant data
6304 * @type: type of works to be removed
6305 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6306 * this interface's works.
6307 */
6308void radio_remove_works(struct wpa_supplicant *wpa_s,
6309 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006310{
6311 struct wpa_radio_work *work, *tmp;
6312 struct wpa_radio *radio = wpa_s->radio;
6313
6314 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6315 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006316 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006317 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006318
6319 /* skip other ifaces' works */
6320 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006321 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006322
6323 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6324 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006325 work->cb(work, 1);
6326 radio_work_free(work);
6327 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006328
6329 /* in case we removed the started work */
6330 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006331}
6332
6333
Roshan Pius3a1667e2018-07-03 15:17:14 -07006334void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6335{
6336 struct wpa_radio_work *work;
6337 struct wpa_radio *radio = wpa_s->radio;
6338
6339 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6340 if (work->ctx != ctx)
6341 continue;
6342 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6343 work->type, work, work->started ? " (started)" : "");
6344 radio_work_free(work);
6345 break;
6346 }
6347}
6348
6349
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006350static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6351{
6352 struct wpa_radio *radio = wpa_s->radio;
6353
6354 if (!radio)
6355 return;
6356
6357 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6358 wpa_s->ifname, radio->name);
6359 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006360 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006361 /* If the interface that triggered the external scan was removed, the
6362 * external scan is no longer running. */
6363 if (wpa_s == radio->external_scan_req_interface)
6364 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006365 wpa_s->radio = NULL;
6366 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006367 return; /* Interfaces remain for this radio */
6368
6369 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006370 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006371 os_free(radio);
6372}
6373
6374
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006375void radio_work_check_next(struct wpa_supplicant *wpa_s)
6376{
6377 struct wpa_radio *radio = wpa_s->radio;
6378
6379 if (dl_list_empty(&radio->work))
6380 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006381 if (wpa_s->ext_work_in_progress) {
6382 wpa_printf(MSG_DEBUG,
6383 "External radio work in progress - delay start of pending item");
6384 return;
6385 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006386 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6387 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6388}
6389
6390
6391/**
6392 * radio_add_work - Add a radio work item
6393 * @wpa_s: Pointer to wpa_supplicant data
6394 * @freq: Frequency of the offchannel operation in MHz or 0
6395 * @type: Unique identifier for each type of work
6396 * @next: Force as the next work to be executed
6397 * @cb: Callback function for indicating when radio is available
6398 * @ctx: Context pointer for the work (work->ctx in cb())
6399 * Returns: 0 on success, -1 on failure
6400 *
6401 * This function is used to request time for an operation that requires
6402 * exclusive radio control. Once the radio is available, the registered callback
6403 * function will be called. radio_work_done() must be called once the exclusive
6404 * radio operation has been completed, so that the radio is freed for other
6405 * operations. The special case of deinit=1 is used to free the context data
6406 * during interface removal. That does not allow the callback function to start
6407 * the radio operation, i.e., it must free any resources allocated for the radio
6408 * work and return.
6409 *
6410 * The @freq parameter can be used to indicate a single channel on which the
6411 * offchannel operation will occur. This may allow multiple radio work
6412 * operations to be performed in parallel if they apply for the same channel.
6413 * Setting this to 0 indicates that the work item may use multiple channels or
6414 * requires exclusive control of the radio.
6415 */
6416int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6417 const char *type, int next,
6418 void (*cb)(struct wpa_radio_work *work, int deinit),
6419 void *ctx)
6420{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006421 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006422 struct wpa_radio_work *work;
6423 int was_empty;
6424
6425 work = os_zalloc(sizeof(*work));
6426 if (work == NULL)
6427 return -1;
6428 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6429 os_get_reltime(&work->time);
6430 work->freq = freq;
6431 work->type = type;
6432 work->wpa_s = wpa_s;
6433 work->cb = cb;
6434 work->ctx = ctx;
6435
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006436 if (freq)
6437 work->bands = wpas_freq_to_band(freq);
6438 else if (os_strcmp(type, "scan") == 0 ||
6439 os_strcmp(type, "p2p-scan") == 0)
6440 work->bands = wpas_get_bands(wpa_s,
6441 ((struct wpa_driver_scan_params *)
6442 ctx)->freqs);
6443 else
6444 work->bands = wpas_get_bands(wpa_s, NULL);
6445
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006446 was_empty = dl_list_empty(&wpa_s->radio->work);
6447 if (next)
6448 dl_list_add(&wpa_s->radio->work, &work->list);
6449 else
6450 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6451 if (was_empty) {
6452 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6453 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006454 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6455 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6456 wpa_dbg(wpa_s, MSG_DEBUG,
6457 "Try to schedule a radio work (num_active_works=%u)",
6458 radio->num_active_works);
6459 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006460 }
6461
6462 return 0;
6463}
6464
6465
6466/**
6467 * radio_work_done - Indicate that a radio work item has been completed
6468 * @work: Completed work
6469 *
6470 * This function is called once the callback function registered with
6471 * radio_add_work() has completed its work.
6472 */
6473void radio_work_done(struct wpa_radio_work *work)
6474{
6475 struct wpa_supplicant *wpa_s = work->wpa_s;
6476 struct os_reltime now, diff;
6477 unsigned int started = work->started;
6478
6479 os_get_reltime(&now);
6480 os_reltime_sub(&now, &work->time, &diff);
6481 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6482 work->type, work, started ? "done" : "canceled",
6483 diff.sec, diff.usec);
6484 radio_work_free(work);
6485 if (started)
6486 radio_work_check_next(wpa_s);
6487}
6488
6489
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006490struct wpa_radio_work *
6491radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006492{
6493 struct wpa_radio_work *work;
6494 struct wpa_radio *radio = wpa_s->radio;
6495
6496 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6497 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006498 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006499 }
6500
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006501 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006502}
6503
6504
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006505static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006506 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006507{
6508 const char *ifname, *driver, *rn;
6509
6510 driver = iface->driver;
6511next_driver:
6512 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6513 return -1;
6514
6515 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6516 if (wpa_s->drv_priv == NULL) {
6517 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006518 int level = MSG_ERROR;
6519
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006520 pos = driver ? os_strchr(driver, ',') : NULL;
6521 if (pos) {
6522 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6523 "driver interface - try next driver wrapper");
6524 driver = pos + 1;
6525 goto next_driver;
6526 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006527
6528#ifdef CONFIG_MATCH_IFACE
6529 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6530 level = MSG_DEBUG;
6531#endif /* CONFIG_MATCH_IFACE */
6532 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006533 return -1;
6534 }
6535 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6536 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6537 "driver_param '%s'", wpa_s->conf->driver_param);
6538 return -1;
6539 }
6540
6541 ifname = wpa_drv_get_ifname(wpa_s);
6542 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6543 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6544 "interface name with '%s'", ifname);
6545 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6546 }
6547
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006548 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006549 if (rn && rn[0] == '\0')
6550 rn = NULL;
6551
6552 wpa_s->radio = radio_add_interface(wpa_s, rn);
6553 if (wpa_s->radio == NULL)
6554 return -1;
6555
6556 return 0;
6557}
6558
6559
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006560#ifdef CONFIG_GAS_SERVER
6561
6562static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6563 unsigned int freq, const u8 *dst,
6564 const u8 *src, const u8 *bssid,
6565 const u8 *data, size_t data_len,
6566 enum offchannel_send_action_result result)
6567{
6568 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6569 " result=%s",
6570 freq, MAC2STR(dst),
6571 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6572 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6573 "FAILED"));
6574 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6575 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6576}
6577
6578
6579static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6580 struct wpabuf *buf, unsigned int wait_time)
6581{
6582 struct wpa_supplicant *wpa_s = ctx;
6583 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6584
6585 if (wait_time > wpa_s->max_remain_on_chan)
6586 wait_time = wpa_s->max_remain_on_chan;
6587
6588 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6589 wpabuf_head(buf), wpabuf_len(buf),
6590 wait_time, wpas_gas_server_tx_status, 0);
6591}
6592
6593#endif /* CONFIG_GAS_SERVER */
6594
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006595static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006596 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006597{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006598 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006599 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006600 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006601
6602 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6603 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6604 iface->confname ? iface->confname : "N/A",
6605 iface->driver ? iface->driver : "default",
6606 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6607 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6608
6609 if (iface->confname) {
6610#ifdef CONFIG_BACKEND_FILE
6611 wpa_s->confname = os_rel2abs_path(iface->confname);
6612 if (wpa_s->confname == NULL) {
6613 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6614 "for configuration file '%s'.",
6615 iface->confname);
6616 return -1;
6617 }
6618 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6619 iface->confname, wpa_s->confname);
6620#else /* CONFIG_BACKEND_FILE */
6621 wpa_s->confname = os_strdup(iface->confname);
6622#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006623 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006624 if (wpa_s->conf == NULL) {
6625 wpa_printf(MSG_ERROR, "Failed to read or parse "
6626 "configuration '%s'.", wpa_s->confname);
6627 return -1;
6628 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006629 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006630 if (wpa_s->confanother &&
6631 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6632 wpa_printf(MSG_ERROR,
6633 "Failed to read or parse configuration '%s'.",
6634 wpa_s->confanother);
6635 return -1;
6636 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006637
6638 /*
6639 * Override ctrl_interface and driver_param if set on command
6640 * line.
6641 */
6642 if (iface->ctrl_interface) {
6643 os_free(wpa_s->conf->ctrl_interface);
6644 wpa_s->conf->ctrl_interface =
6645 os_strdup(iface->ctrl_interface);
6646 }
6647
6648 if (iface->driver_param) {
6649 os_free(wpa_s->conf->driver_param);
6650 wpa_s->conf->driver_param =
6651 os_strdup(iface->driver_param);
6652 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006653
6654 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6655 os_free(wpa_s->conf->ctrl_interface);
6656 wpa_s->conf->ctrl_interface = NULL;
6657 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006658 } else
6659 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6660 iface->driver_param);
6661
6662 if (wpa_s->conf == NULL) {
6663 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6664 return -1;
6665 }
6666
6667 if (iface->ifname == NULL) {
6668 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6669 return -1;
6670 }
6671 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6672 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6673 iface->ifname);
6674 return -1;
6675 }
6676 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006677#ifdef CONFIG_MATCH_IFACE
6678 wpa_s->matched = iface->matched;
6679#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006680
6681 if (iface->bridge_ifname) {
6682 if (os_strlen(iface->bridge_ifname) >=
6683 sizeof(wpa_s->bridge_ifname)) {
6684 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6685 "name '%s'.", iface->bridge_ifname);
6686 return -1;
6687 }
6688 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6689 sizeof(wpa_s->bridge_ifname));
6690 }
6691
6692 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006693 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6694 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006695
6696 /* Initialize driver interface and register driver event handler before
6697 * L2 receive handler so that association events are processed before
6698 * EAPOL-Key packets if both become available for the same select()
6699 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006700 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006701 return -1;
6702
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006703 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6704 return -1;
6705
6706 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6707 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6708 NULL);
6709 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6710
6711 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6712 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6713 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6714 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6715 "dot11RSNAConfigPMKLifetime");
6716 return -1;
6717 }
6718
6719 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6720 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6721 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6722 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6723 "dot11RSNAConfigPMKReauthThreshold");
6724 return -1;
6725 }
6726
6727 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6728 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6729 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6730 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6731 "dot11RSNAConfigSATimeout");
6732 return -1;
6733 }
6734
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006735 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6736 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006737 &wpa_s->hw.flags,
6738 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006739 if (wpa_s->hw.modes) {
6740 u16 i;
6741
6742 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6743 if (wpa_s->hw.modes[i].vht_capab) {
6744 wpa_s->hw_capab = CAPAB_VHT;
6745 break;
6746 }
6747
6748 if (wpa_s->hw.modes[i].ht_capab &
6749 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6750 wpa_s->hw_capab = CAPAB_HT40;
6751 else if (wpa_s->hw.modes[i].ht_capab &&
6752 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6753 wpa_s->hw_capab = CAPAB_HT;
6754 }
6755 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006756
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006757 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6758 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006759 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006760 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006761 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006762 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006763 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravi59fa4b42022-05-02 22:54:18 -07006764 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006765 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006766 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006767 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006768 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6769 wpa_s->max_sched_scan_plan_interval =
6770 capa.max_sched_scan_plan_interval;
6771 wpa_s->max_sched_scan_plan_iterations =
6772 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006773 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6774 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006775 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6776 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006777 wpa_s->extended_capa = capa.extended_capa;
6778 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6779 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006780 wpa_s->num_multichan_concurrent =
6781 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006782 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6783
6784 if (capa.mac_addr_rand_scan_supported)
6785 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6786 if (wpa_s->sched_scan_supported &&
6787 capa.mac_addr_rand_sched_scan_supported)
6788 wpa_s->mac_addr_rand_supported |=
6789 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006790
6791 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6792 if (wpa_s->extended_capa &&
6793 wpa_s->extended_capa_len >= 3 &&
6794 wpa_s->extended_capa[2] & 0x40)
6795 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006796 }
6797 if (wpa_s->max_remain_on_chan == 0)
6798 wpa_s->max_remain_on_chan = 1000;
6799
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006800 /*
6801 * Only take p2p_mgmt parameters when P2P Device is supported.
6802 * Doing it here as it determines whether l2_packet_init() will be done
6803 * during wpa_supplicant_driver_init().
6804 */
6805 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6806 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006807
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006808 if (wpa_s->num_multichan_concurrent == 0)
6809 wpa_s->num_multichan_concurrent = 1;
6810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006811 if (wpa_supplicant_driver_init(wpa_s) < 0)
6812 return -1;
6813
6814#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006815 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006816 return -1;
6817#endif /* CONFIG_TDLS */
6818
6819 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6820 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6821 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6822 return -1;
6823 }
6824
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006825#ifdef CONFIG_FST
6826 if (wpa_s->conf->fst_group_id) {
6827 struct fst_iface_cfg cfg;
6828 struct fst_wpa_obj iface_obj;
6829
6830 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6831 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6832 sizeof(cfg.group_id));
6833 cfg.priority = wpa_s->conf->fst_priority;
6834 cfg.llt = wpa_s->conf->fst_llt;
6835
6836 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6837 &iface_obj, &cfg);
6838 if (!wpa_s->fst) {
6839 wpa_msg(wpa_s, MSG_ERROR,
6840 "FST: Cannot attach iface %s to group %s",
6841 wpa_s->ifname, cfg.group_id);
6842 return -1;
6843 }
6844 }
6845#endif /* CONFIG_FST */
6846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006847 if (wpas_wps_init(wpa_s))
6848 return -1;
6849
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006850#ifdef CONFIG_GAS_SERVER
6851 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6852 if (!wpa_s->gas_server) {
6853 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6854 return -1;
6855 }
6856#endif /* CONFIG_GAS_SERVER */
6857
6858#ifdef CONFIG_DPP
6859 if (wpas_dpp_init(wpa_s) < 0)
6860 return -1;
6861#endif /* CONFIG_DPP */
6862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006863 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6864 return -1;
6865 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6866
6867 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6868 if (wpa_s->ctrl_iface == NULL) {
6869 wpa_printf(MSG_ERROR,
6870 "Failed to initialize control interface '%s'.\n"
6871 "You may have another wpa_supplicant process "
6872 "already running or the file was\n"
6873 "left by an unclean termination of wpa_supplicant "
6874 "in which case you will need\n"
6875 "to manually remove this file before starting "
6876 "wpa_supplicant again.\n",
6877 wpa_s->conf->ctrl_interface);
6878 return -1;
6879 }
6880
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006881 wpa_s->gas = gas_query_init(wpa_s);
6882 if (wpa_s->gas == NULL) {
6883 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6884 return -1;
6885 }
6886
Roshan Pius3a1667e2018-07-03 15:17:14 -07006887 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6888 wpa_s->p2p_mgmt) &&
6889 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006890 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6891 return -1;
6892 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006893
6894 if (wpa_bss_init(wpa_s) < 0)
6895 return -1;
6896
Paul Stewart092955c2017-02-06 09:13:09 -08006897#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6898#ifdef CONFIG_MESH
6899 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6900#endif /* CONFIG_MESH */
6901#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6902
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006903 /*
6904 * Set Wake-on-WLAN triggers, if configured.
6905 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6906 * have effect anyway when the interface is down).
6907 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006908 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006909 return -1;
6910
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006911#ifdef CONFIG_EAP_PROXY
6912{
6913 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006914 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6915 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006916 if (wpa_s->mnc_len > 0) {
6917 wpa_s->imsi[len] = '\0';
6918 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6919 wpa_s->imsi, wpa_s->mnc_len);
6920 } else {
6921 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6922 }
6923}
6924#endif /* CONFIG_EAP_PROXY */
6925
Dmitry Shmidt04949592012-07-19 12:16:46 -07006926 if (pcsc_reader_init(wpa_s) < 0)
6927 return -1;
6928
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006929 if (wpas_init_ext_pw(wpa_s) < 0)
6930 return -1;
6931
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006932 wpas_rrm_reset(wpa_s);
6933
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006934 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6935
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006936#ifdef CONFIG_HS20
6937 hs20_init(wpa_s);
6938#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006939#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006940 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006941 if ((wpa_s->conf->oce & OCE_STA) &&
6942 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6943 wpa_s->enable_oce = OCE_STA;
6944 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6945 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6946 /* TODO: Need to add STA-CFON support */
6947 wpa_printf(MSG_ERROR,
6948 "OCE STA-CFON feature is not yet supported");
6949 }
6950 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006951 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6952#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006953
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006954 wpa_supplicant_set_default_scan_ies(wpa_s);
6955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006956 return 0;
6957}
6958
6959
6960static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006961 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006962{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006963 struct wpa_global *global = wpa_s->global;
6964 struct wpa_supplicant *iface, *prev;
6965
Jimmy Chen0e73c002021-08-18 13:21:30 +08006966 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006967 wpas_p2p_group_remove(wpa_s, "*");
6968
6969 iface = global->ifaces;
6970 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006971 if (iface->p2pdev == wpa_s)
6972 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006973 if (iface == wpa_s || iface->parent != wpa_s) {
6974 iface = iface->next;
6975 continue;
6976 }
6977 wpa_printf(MSG_DEBUG,
6978 "Remove remaining child interface %s from parent %s",
6979 iface->ifname, wpa_s->ifname);
6980 prev = iface;
6981 iface = iface->next;
6982 wpa_supplicant_remove_iface(global, prev, terminate);
6983 }
6984
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006985 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006986 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006987 /*
6988 * Don't deauthenticate if WoWLAN is enable and not explicitly
6989 * been configured to disconnect.
6990 */
6991 if (!wpa_drv_get_wowlan(wpa_s) ||
6992 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006993 wpa_supplicant_deauthenticate(
6994 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006995
Hai Shalomfdcde762020-04-02 11:19:20 -07006996 wpa_drv_set_countermeasures(wpa_s, 0);
6997 wpa_clear_keys(wpa_s, NULL);
6998 } else {
6999 wpa_msg(wpa_s, MSG_INFO,
7000 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7001 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007002 }
7003
7004 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007005 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007006
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007007 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007008 radio_remove_interface(wpa_s);
7009
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007010#ifdef CONFIG_FST
7011 if (wpa_s->fst) {
7012 fst_detach(wpa_s->fst);
7013 wpa_s->fst = NULL;
7014 }
7015 if (wpa_s->received_mb_ies) {
7016 wpabuf_free(wpa_s->received_mb_ies);
7017 wpa_s->received_mb_ies = NULL;
7018 }
7019#endif /* CONFIG_FST */
7020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007021 if (wpa_s->drv_priv)
7022 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007023
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007024 if (notify)
7025 wpas_notify_iface_removed(wpa_s);
7026
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007027 if (terminate)
7028 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007029
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007030 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7031 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007032
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007033#ifdef CONFIG_MESH
7034 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007035 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007036 wpa_s->ifmsh = NULL;
7037 }
7038#endif /* CONFIG_MESH */
7039
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007040 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007041 wpa_config_free(wpa_s->conf);
7042 wpa_s->conf = NULL;
7043 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007044
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007045 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007046 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007047
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007048 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007049}
7050
7051
Dmitry Shmidte4663042016-04-04 10:07:49 -07007052#ifdef CONFIG_MATCH_IFACE
7053
7054/**
7055 * wpa_supplicant_match_iface - Match an interface description to a name
7056 * @global: Pointer to global data from wpa_supplicant_init()
7057 * @ifname: Name of the interface to match
7058 * Returns: Pointer to the created interface description or %NULL on failure
7059 */
7060struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7061 const char *ifname)
7062{
7063 int i;
7064 struct wpa_interface *iface, *miface;
7065
7066 for (i = 0; i < global->params.match_iface_count; i++) {
7067 miface = &global->params.match_ifaces[i];
7068 if (!miface->ifname ||
7069 fnmatch(miface->ifname, ifname, 0) == 0) {
7070 iface = os_zalloc(sizeof(*iface));
7071 if (!iface)
7072 return NULL;
7073 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007074 if (!miface->ifname)
7075 iface->matched = WPA_IFACE_MATCHED_NULL;
7076 else
7077 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007078 iface->ifname = ifname;
7079 return iface;
7080 }
7081 }
7082
7083 return NULL;
7084}
7085
7086
7087/**
7088 * wpa_supplicant_match_existing - Match existing interfaces
7089 * @global: Pointer to global data from wpa_supplicant_init()
7090 * Returns: 0 on success, -1 on failure
7091 */
7092static int wpa_supplicant_match_existing(struct wpa_global *global)
7093{
7094 struct if_nameindex *ifi, *ifp;
7095 struct wpa_supplicant *wpa_s;
7096 struct wpa_interface *iface;
7097
7098 ifp = if_nameindex();
7099 if (!ifp) {
7100 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7101 return -1;
7102 }
7103
7104 for (ifi = ifp; ifi->if_name; ifi++) {
7105 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7106 if (wpa_s)
7107 continue;
7108 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7109 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007110 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007111 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007112 }
7113 }
7114
7115 if_freenameindex(ifp);
7116 return 0;
7117}
7118
7119#endif /* CONFIG_MATCH_IFACE */
7120
7121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007122/**
7123 * wpa_supplicant_add_iface - Add a new network interface
7124 * @global: Pointer to global data from wpa_supplicant_init()
7125 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007126 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007127 * Returns: Pointer to the created interface or %NULL on failure
7128 *
7129 * This function is used to add new network interfaces for %wpa_supplicant.
7130 * This can be called before wpa_supplicant_run() to add interfaces before the
7131 * main event loop has been started. In addition, new interfaces can be added
7132 * dynamically while %wpa_supplicant is already running. This could happen,
7133 * e.g., when a hotplug network adapter is inserted.
7134 */
7135struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007136 struct wpa_interface *iface,
7137 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007138{
7139 struct wpa_supplicant *wpa_s;
7140 struct wpa_interface t_iface;
7141 struct wpa_ssid *ssid;
7142
7143 if (global == NULL || iface == NULL)
7144 return NULL;
7145
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007146 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007147 if (wpa_s == NULL)
7148 return NULL;
7149
7150 wpa_s->global = global;
7151
7152 t_iface = *iface;
7153 if (global->params.override_driver) {
7154 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7155 "('%s' -> '%s')",
7156 iface->driver, global->params.override_driver);
7157 t_iface.driver = global->params.override_driver;
7158 }
7159 if (global->params.override_ctrl_interface) {
7160 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7161 "ctrl_interface ('%s' -> '%s')",
7162 iface->ctrl_interface,
7163 global->params.override_ctrl_interface);
7164 t_iface.ctrl_interface =
7165 global->params.override_ctrl_interface;
7166 }
7167 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7168 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7169 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007170 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007171 return NULL;
7172 }
7173
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007174 /* Notify the control interfaces about new iface */
7175 if (wpas_notify_iface_added(wpa_s)) {
7176 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7177 return NULL;
7178 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007179
Jimmy Chen115616e2022-07-10 10:25:21 +08007180 /* Notify the control interfaces about new networks */
7181 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7182 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007183 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chen115616e2022-07-10 10:25:21 +08007184 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7185 && os_strncmp((const char *) ssid->ssid,
7186 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7187 wpas_notify_persistent_group_added(wpa_s, ssid);
7188 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007189 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007190
7191 wpa_s->next = global->ifaces;
7192 global->ifaces = wpa_s;
7193
7194 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007195 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007196
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007197#ifdef CONFIG_P2P
7198 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007199 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007200 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007201 wpas_p2p_add_p2pdev_interface(
7202 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007203 wpa_printf(MSG_INFO,
7204 "P2P: Failed to enable P2P Device interface");
7205 /* Try to continue without. P2P will be disabled. */
7206 }
7207#endif /* CONFIG_P2P */
7208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007209 return wpa_s;
7210}
7211
7212
7213/**
7214 * wpa_supplicant_remove_iface - Remove a network interface
7215 * @global: Pointer to global data from wpa_supplicant_init()
7216 * @wpa_s: Pointer to the network interface to be removed
7217 * Returns: 0 if interface was removed, -1 if interface was not found
7218 *
7219 * This function can be used to dynamically remove network interfaces from
7220 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7221 * addition, this function is used to remove all remaining interfaces when
7222 * %wpa_supplicant is terminated.
7223 */
7224int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007225 struct wpa_supplicant *wpa_s,
7226 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007227{
7228 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007229#ifdef CONFIG_MESH
7230 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7231 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007232 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007233#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007234
7235 /* Remove interface from the global list of interfaces */
7236 prev = global->ifaces;
7237 if (prev == wpa_s) {
7238 global->ifaces = wpa_s->next;
7239 } else {
7240 while (prev && prev->next != wpa_s)
7241 prev = prev->next;
7242 if (prev == NULL)
7243 return -1;
7244 prev->next = wpa_s->next;
7245 }
7246
7247 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7248
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007249#ifdef CONFIG_MESH
7250 if (mesh_if_created) {
7251 ifname = os_strdup(wpa_s->ifname);
7252 if (ifname == NULL) {
7253 wpa_dbg(wpa_s, MSG_ERROR,
7254 "mesh: Failed to malloc ifname");
7255 return -1;
7256 }
7257 }
7258#endif /* CONFIG_MESH */
7259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007260 if (global->p2p_group_formation == wpa_s)
7261 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007262 if (global->p2p_invite_group == wpa_s)
7263 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007264 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007266#ifdef CONFIG_MESH
7267 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007268 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007269 os_free(ifname);
7270 }
7271#endif /* CONFIG_MESH */
7272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007273 return 0;
7274}
7275
7276
7277/**
7278 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7279 * @wpa_s: Pointer to the network interface
7280 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7281 */
7282const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7283{
7284 const char *eapol_method;
7285
7286 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7287 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7288 return "NO-EAP";
7289 }
7290
7291 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7292 if (eapol_method == NULL)
7293 return "UNKNOWN-EAP";
7294
7295 return eapol_method;
7296}
7297
7298
7299/**
7300 * wpa_supplicant_get_iface - Get a new network interface
7301 * @global: Pointer to global data from wpa_supplicant_init()
7302 * @ifname: Interface name
7303 * Returns: Pointer to the interface or %NULL if not found
7304 */
7305struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7306 const char *ifname)
7307{
7308 struct wpa_supplicant *wpa_s;
7309
7310 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7311 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7312 return wpa_s;
7313 }
7314 return NULL;
7315}
7316
7317
7318#ifndef CONFIG_NO_WPA_MSG
7319static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7320{
7321 struct wpa_supplicant *wpa_s = ctx;
7322 if (wpa_s == NULL)
7323 return NULL;
7324 return wpa_s->ifname;
7325}
7326#endif /* CONFIG_NO_WPA_MSG */
7327
7328
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007329#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7330#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7331#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7332
7333/* Periodic cleanup tasks */
7334static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7335{
7336 struct wpa_global *global = eloop_ctx;
7337 struct wpa_supplicant *wpa_s;
7338
7339 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7340 wpas_periodic, global, NULL);
7341
7342#ifdef CONFIG_P2P
7343 if (global->p2p)
7344 p2p_expire_peers(global->p2p);
7345#endif /* CONFIG_P2P */
7346
7347 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7348 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7349#ifdef CONFIG_AP
7350 ap_periodic(wpa_s);
7351#endif /* CONFIG_AP */
7352 }
7353}
7354
7355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007356/**
7357 * wpa_supplicant_init - Initialize %wpa_supplicant
7358 * @params: Parameters for %wpa_supplicant
7359 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7360 *
7361 * This function is used to initialize %wpa_supplicant. After successful
7362 * initialization, the returned data pointer can be used to add and remove
7363 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7364 */
7365struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7366{
7367 struct wpa_global *global;
7368 int ret, i;
7369
7370 if (params == NULL)
7371 return NULL;
7372
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007373#ifdef CONFIG_DRIVER_NDIS
7374 {
7375 void driver_ndis_init_ops(void);
7376 driver_ndis_init_ops();
7377 }
7378#endif /* CONFIG_DRIVER_NDIS */
7379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007380#ifndef CONFIG_NO_WPA_MSG
7381 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7382#endif /* CONFIG_NO_WPA_MSG */
7383
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007384 if (params->wpa_debug_file_path)
7385 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007386 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007387 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007388 if (params->wpa_debug_syslog)
7389 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007390 if (params->wpa_debug_tracing) {
7391 ret = wpa_debug_open_linux_tracing();
7392 if (ret) {
7393 wpa_printf(MSG_ERROR,
7394 "Failed to enable trace logging");
7395 return NULL;
7396 }
7397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007398
7399 ret = eap_register_methods();
7400 if (ret) {
7401 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7402 if (ret == -2)
7403 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7404 "the same EAP type.");
7405 return NULL;
7406 }
7407
7408 global = os_zalloc(sizeof(*global));
7409 if (global == NULL)
7410 return NULL;
7411 dl_list_init(&global->p2p_srv_bonjour);
7412 dl_list_init(&global->p2p_srv_upnp);
7413 global->params.daemonize = params->daemonize;
7414 global->params.wait_for_monitor = params->wait_for_monitor;
7415 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7416 if (params->pid_file)
7417 global->params.pid_file = os_strdup(params->pid_file);
7418 if (params->ctrl_interface)
7419 global->params.ctrl_interface =
7420 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007421 if (params->ctrl_interface_group)
7422 global->params.ctrl_interface_group =
7423 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007424 if (params->override_driver)
7425 global->params.override_driver =
7426 os_strdup(params->override_driver);
7427 if (params->override_ctrl_interface)
7428 global->params.override_ctrl_interface =
7429 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007430#ifdef CONFIG_MATCH_IFACE
7431 global->params.match_iface_count = params->match_iface_count;
7432 if (params->match_iface_count) {
7433 global->params.match_ifaces =
7434 os_calloc(params->match_iface_count,
7435 sizeof(struct wpa_interface));
7436 os_memcpy(global->params.match_ifaces,
7437 params->match_ifaces,
7438 params->match_iface_count *
7439 sizeof(struct wpa_interface));
7440 }
7441#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007442#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007443 if (params->conf_p2p_dev)
7444 global->params.conf_p2p_dev =
7445 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007446#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007447 wpa_debug_level = global->params.wpa_debug_level =
7448 params->wpa_debug_level;
7449 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7450 params->wpa_debug_show_keys;
7451 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7452 params->wpa_debug_timestamp;
7453
Hai Shalomfdcde762020-04-02 11:19:20 -07007454 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007455
7456 if (eloop_init()) {
7457 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7458 wpa_supplicant_deinit(global);
7459 return NULL;
7460 }
7461
Jouni Malinen75ecf522011-06-27 15:19:46 -07007462 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007463
7464 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7465 if (global->ctrl_iface == NULL) {
7466 wpa_supplicant_deinit(global);
7467 return NULL;
7468 }
7469
7470 if (wpas_notify_supplicant_initialized(global)) {
7471 wpa_supplicant_deinit(global);
7472 return NULL;
7473 }
7474
7475 for (i = 0; wpa_drivers[i]; i++)
7476 global->drv_count++;
7477 if (global->drv_count == 0) {
7478 wpa_printf(MSG_ERROR, "No drivers enabled");
7479 wpa_supplicant_deinit(global);
7480 return NULL;
7481 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007482 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483 if (global->drv_priv == NULL) {
7484 wpa_supplicant_deinit(global);
7485 return NULL;
7486 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007487
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007488#ifdef CONFIG_WIFI_DISPLAY
7489 if (wifi_display_init(global) < 0) {
7490 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7491 wpa_supplicant_deinit(global);
7492 return NULL;
7493 }
7494#endif /* CONFIG_WIFI_DISPLAY */
7495
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007496 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7497 wpas_periodic, global, NULL);
7498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007499 return global;
7500}
7501
7502
7503/**
7504 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7505 * @global: Pointer to global data from wpa_supplicant_init()
7506 * Returns: 0 after successful event loop run, -1 on failure
7507 *
7508 * This function starts the main event loop and continues running as long as
7509 * there are any remaining events. In most cases, this function is running as
7510 * long as the %wpa_supplicant process in still in use.
7511 */
7512int wpa_supplicant_run(struct wpa_global *global)
7513{
7514 struct wpa_supplicant *wpa_s;
7515
7516 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007517 (wpa_supplicant_daemon(global->params.pid_file) ||
7518 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007519 return -1;
7520
Dmitry Shmidte4663042016-04-04 10:07:49 -07007521#ifdef CONFIG_MATCH_IFACE
7522 if (wpa_supplicant_match_existing(global))
7523 return -1;
7524#endif
7525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007526 if (global->params.wait_for_monitor) {
7527 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007528 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007529 wpa_supplicant_ctrl_iface_wait(
7530 wpa_s->ctrl_iface);
7531 }
7532
7533 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7534 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7535
7536 eloop_run();
7537
7538 return 0;
7539}
7540
7541
7542/**
7543 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7544 * @global: Pointer to global data from wpa_supplicant_init()
7545 *
7546 * This function is called to deinitialize %wpa_supplicant and to free all
7547 * allocated resources. Remaining network interfaces will also be removed.
7548 */
7549void wpa_supplicant_deinit(struct wpa_global *global)
7550{
7551 int i;
7552
7553 if (global == NULL)
7554 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007555
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007556 eloop_cancel_timeout(wpas_periodic, global, NULL);
7557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007558#ifdef CONFIG_WIFI_DISPLAY
7559 wifi_display_deinit(global);
7560#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007561
7562 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007563 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007564
7565 if (global->ctrl_iface)
7566 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7567
7568 wpas_notify_supplicant_deinitialized(global);
7569
7570 eap_peer_unregister_methods();
7571#ifdef CONFIG_AP
7572 eap_server_unregister_methods();
7573#endif /* CONFIG_AP */
7574
7575 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7576 if (!global->drv_priv[i])
7577 continue;
7578 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7579 }
7580 os_free(global->drv_priv);
7581
7582 random_deinit();
7583
7584 eloop_destroy();
7585
7586 if (global->params.pid_file) {
7587 os_daemonize_terminate(global->params.pid_file);
7588 os_free(global->params.pid_file);
7589 }
7590 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007591 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007592 os_free(global->params.override_driver);
7593 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007594#ifdef CONFIG_MATCH_IFACE
7595 os_free(global->params.match_ifaces);
7596#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007597#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007598 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007599#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007600
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007601 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007602 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007603 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007605 os_free(global);
7606 wpa_debug_close_syslog();
7607 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007608 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007609}
7610
7611
7612void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7613{
7614 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7615 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7616 char country[3];
7617 country[0] = wpa_s->conf->country[0];
7618 country[1] = wpa_s->conf->country[1];
7619 country[2] = '\0';
7620 if (wpa_drv_set_country(wpa_s, country) < 0) {
7621 wpa_printf(MSG_ERROR, "Failed to set country code "
7622 "'%s'", country);
7623 }
7624 }
7625
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007626 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7627 wpas_init_ext_pw(wpa_s);
7628
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007629 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7630 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7631
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007632 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7633 struct wpa_driver_capa capa;
7634 int res = wpa_drv_get_capa(wpa_s, &capa);
7635
7636 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7637 wpa_printf(MSG_ERROR,
7638 "Failed to update wowlan_triggers to '%s'",
7639 wpa_s->conf->wowlan_triggers);
7640 }
7641
Hai Shalom81f62d82019-07-22 12:10:00 -07007642 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7643 wpa_supplicant_set_default_scan_ies(wpa_s);
7644
Hai Shalom899fcc72020-10-19 14:38:18 -07007645#ifdef CONFIG_BGSCAN
7646 /*
7647 * We default to global bgscan parameters only when per-network bgscan
7648 * parameters aren't set. Only bother resetting bgscan parameters if
7649 * this is the case.
7650 */
7651 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7652 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7653 wpa_s->wpa_state == WPA_COMPLETED)
7654 wpa_supplicant_reset_bgscan(wpa_s);
7655#endif /* CONFIG_BGSCAN */
7656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007657#ifdef CONFIG_WPS
7658 wpas_wps_update_config(wpa_s);
7659#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007660 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007661 wpa_s->conf->changed_parameters = 0;
7662}
7663
7664
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007665void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007666{
7667 int i;
7668
7669 for (i = 0; i < *num_freqs; i++) {
7670 if (freqs[i] == freq)
7671 return;
7672 }
7673
7674 freqs[*num_freqs] = freq;
7675 (*num_freqs)++;
7676}
7677
7678
7679static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7680{
7681 struct wpa_bss *bss, *cbss;
7682 const int max_freqs = 10;
7683 int *freqs;
7684 int num_freqs = 0;
7685
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007686 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007687 if (freqs == NULL)
7688 return NULL;
7689
7690 cbss = wpa_s->current_bss;
7691
7692 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7693 if (bss == cbss)
7694 continue;
7695 if (bss->ssid_len == cbss->ssid_len &&
7696 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007697 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007698 add_freq(freqs, &num_freqs, bss->freq);
7699 if (num_freqs == max_freqs)
7700 break;
7701 }
7702 }
7703
7704 if (num_freqs == 0) {
7705 os_free(freqs);
7706 freqs = NULL;
7707 }
7708
7709 return freqs;
7710}
7711
7712
7713void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7714{
7715 int timeout;
7716 int count;
7717 int *freqs = NULL;
7718
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007719 wpas_connect_work_done(wpa_s);
7720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007721 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007722 * Remove possible authentication timeout since the connection failed.
7723 */
7724 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7725
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007726 /*
Hai Shalom60840252021-02-19 19:02:11 -08007727 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007728 * generated based on local request to disconnect.
7729 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007730 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007731 wpa_s->own_disconnect_req = 0;
7732 wpa_dbg(wpa_s, MSG_DEBUG,
7733 "Ignore connection failure due to local request to disconnect");
7734 return;
7735 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007736 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007737 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7738 "indication since interface has been put into "
7739 "disconnected state");
7740 return;
7741 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007742 if (wpa_s->auto_reconnect_disabled) {
7743 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7744 "indication since auto connect is disabled");
7745 return;
7746 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007747
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007748 /*
Hai Shalom60840252021-02-19 19:02:11 -08007749 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007750 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007751 */
Hai Shalom60840252021-02-19 19:02:11 -08007752 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007753 if (count == 1 && wpa_s->current_bss) {
7754 /*
Hai Shalom60840252021-02-19 19:02:11 -08007755 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007756 * another BSS available for the same ESS, we should try that
7757 * next. Otherwise, we may as well try this one once more
7758 * before allowing other, likely worse, ESSes to be considered.
7759 */
7760 freqs = get_bss_freqs_in_ess(wpa_s);
7761 if (freqs) {
7762 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7763 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007764 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007765 /*
7766 * On the next scan, go through only the known channels
7767 * used in this ESS based on previous scans to speed up
7768 * common load balancing use case.
7769 */
7770 os_free(wpa_s->next_scan_freqs);
7771 wpa_s->next_scan_freqs = freqs;
7772 }
7773 }
7774
Hai Shalom899fcc72020-10-19 14:38:18 -07007775 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007776
Hai Shalom899fcc72020-10-19 14:38:18 -07007777 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007778 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7779 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007780 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007781 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007782 /*
7783 * Multiple consecutive connection failures mean that other APs are
7784 * either not available or have already been tried, so we can start
7785 * increasing the delay here to avoid constant scanning.
7786 */
7787 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007788 case 1:
7789 timeout = 100;
7790 break;
7791 case 2:
7792 timeout = 500;
7793 break;
7794 case 3:
7795 timeout = 1000;
7796 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007797 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007798 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007799 break;
7800 default:
7801 timeout = 10000;
7802 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007803 }
7804
Hai Shalom899fcc72020-10-19 14:38:18 -07007805 wpa_dbg(wpa_s, MSG_DEBUG,
7806 "Consecutive connection failures: %d --> request scan in %d ms",
7807 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007809 /*
7810 * TODO: if more than one possible AP is available in scan results,
7811 * could try the other ones before requesting a new scan.
7812 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007813
7814 /* speed up the connection attempt with normal scan */
7815 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007816 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7817 1000 * (timeout % 1000));
7818}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007819
7820
Hai Shalomce48b4a2018-09-05 11:41:35 -07007821#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007822
7823void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7824{
7825 struct wpa_ssid *ssid = wpa_s->current_ssid;
7826 const u8 *realm, *username, *rrk;
7827 size_t realm_len, username_len, rrk_len;
7828 u16 next_seq_num;
7829
7830 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7831 * Check for ERP keys existing to limit when this can be done since
7832 * the rejection response is not protected and such triggers should
7833 * really not allow internal state to be modified unless required to
7834 * avoid significant issues in functionality. In addition, drop
7835 * externally configure PMKSA entries even without ERP keys since it
7836 * is possible for an external component to add PMKSA entries for FILS
7837 * authentication without restoring previously generated ERP keys.
7838 *
7839 * In this case, this is needed to allow recovery from cases where the
7840 * AP or authentication server has dropped PMKSAs and ERP keys. */
7841 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7842 return;
7843
7844 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7845 &username, &username_len,
7846 &realm, &realm_len, &next_seq_num,
7847 &rrk, &rrk_len) != 0 ||
7848 !realm) {
7849 wpa_dbg(wpa_s, MSG_DEBUG,
7850 "FILS: Drop external PMKSA cache entry");
7851 wpa_sm_aborted_external_cached(wpa_s->wpa);
7852 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7853 return;
7854 }
7855
7856 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7857 wpa_sm_aborted_cached(wpa_s->wpa);
7858 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7859}
7860
7861
Hai Shalomce48b4a2018-09-05 11:41:35 -07007862void fils_connection_failure(struct wpa_supplicant *wpa_s)
7863{
7864 struct wpa_ssid *ssid = wpa_s->current_ssid;
7865 const u8 *realm, *username, *rrk;
7866 size_t realm_len, username_len, rrk_len;
7867 u16 next_seq_num;
7868
7869 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7870 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7871 &username, &username_len,
7872 &realm, &realm_len, &next_seq_num,
7873 &rrk, &rrk_len) != 0 ||
7874 !realm)
7875 return;
7876
7877 wpa_hexdump_ascii(MSG_DEBUG,
7878 "FILS: Store last connection failure realm",
7879 realm, realm_len);
7880 os_free(wpa_s->last_con_fail_realm);
7881 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7882 if (wpa_s->last_con_fail_realm) {
7883 wpa_s->last_con_fail_realm_len = realm_len;
7884 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7885 }
7886}
7887#endif /* CONFIG_FILS */
7888
7889
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007890int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7891{
7892 return wpa_s->conf->ap_scan == 2 ||
7893 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7894}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007895
Dmitry Shmidt04949592012-07-19 12:16:46 -07007896
Gabriel Biren57ededa2021-09-03 16:08:50 +00007897#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007898int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7899 struct wpa_ssid *ssid,
7900 const char *field,
7901 const char *value)
7902{
7903#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007904 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007905
7906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7907 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7908 (const u8 *) value, os_strlen(value));
7909
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007910 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007911 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007912#else /* IEEE8021X_EAPOL */
7913 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7914 return -1;
7915#endif /* IEEE8021X_EAPOL */
7916}
7917
7918int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7919 struct wpa_ssid *ssid,
7920 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007921 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007922{
7923#ifdef IEEE8021X_EAPOL
7924 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007925 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007926
7927 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007928 case WPA_CTRL_REQ_EAP_IDENTITY:
7929 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007930 os_free(eap->imsi_identity);
7931 if (value == NULL)
7932 return -1;
7933 identity = os_strchr(value, ':');
7934 if (identity == NULL) {
7935 /* plain identity */
7936 eap->identity = (u8 *)os_strdup(value);
7937 eap->identity_len = os_strlen(value);
7938 } else {
7939 /* have both plain identity and encrypted identity */
7940 imsi_identity = value;
7941 *identity++ = '\0';
7942 /* plain identity */
7943 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7944 eap->imsi_identity_len = strlen(imsi_identity);
7945 /* encrypted identity */
7946 eap->identity = (u8 *)dup_binstr(identity,
7947 value_len - strlen(imsi_identity) - 1);
7948 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7949 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007950 eap->pending_req_identity = 0;
7951 if (ssid == wpa_s->current_ssid)
7952 wpa_s->reassociate = 1;
7953 break;
7954 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007955 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007956 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007957 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007958 eap->pending_req_password = 0;
7959 if (ssid == wpa_s->current_ssid)
7960 wpa_s->reassociate = 1;
7961 break;
7962 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007963 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007964 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007965 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007966 eap->pending_req_new_password = 0;
7967 if (ssid == wpa_s->current_ssid)
7968 wpa_s->reassociate = 1;
7969 break;
7970 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007971 str_clear_free(eap->cert.pin);
7972 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007973 eap->pending_req_pin = 0;
7974 if (ssid == wpa_s->current_ssid)
7975 wpa_s->reassociate = 1;
7976 break;
7977 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007978 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007979 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007980 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007981 os_free(eap->pending_req_otp);
7982 eap->pending_req_otp = NULL;
7983 eap->pending_req_otp_len = 0;
7984 break;
7985 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007986 str_clear_free(eap->cert.private_key_passwd);
7987 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007988 eap->pending_req_passphrase = 0;
7989 if (ssid == wpa_s->current_ssid)
7990 wpa_s->reassociate = 1;
7991 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007992 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007993 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007994 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007995 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007996 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007997 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7998 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7999 return -1;
8000 ssid->mem_only_psk = 1;
8001 if (ssid->passphrase)
8002 wpa_config_update_psk(ssid);
8003 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8004 wpa_supplicant_req_scan(wpa_s, 0, 0);
8005 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008006 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8007 if (eap->pending_ext_cert_check != PENDING_CHECK)
8008 return -1;
8009 if (os_strcmp(value, "good") == 0)
8010 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8011 else if (os_strcmp(value, "bad") == 0)
8012 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8013 else
8014 return -1;
8015 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008016 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008017 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008018 return -1;
8019 }
8020
8021 return 0;
8022#else /* IEEE8021X_EAPOL */
8023 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8024 return -1;
8025#endif /* IEEE8021X_EAPOL */
8026}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008027#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008028
8029
8030int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8031{
Hai Shalomfdcde762020-04-02 11:19:20 -07008032#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008033 int i;
8034 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008035#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008036
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008037 if (wpa_s->p2p_mgmt)
8038 return 1; /* no normal network profiles on p2p_mgmt interface */
8039
Dmitry Shmidt04949592012-07-19 12:16:46 -07008040 if (ssid == NULL)
8041 return 1;
8042
8043 if (ssid->disabled)
8044 return 1;
8045
Hai Shalomfdcde762020-04-02 11:19:20 -07008046#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008047 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008048 drv_enc = wpa_s->drv_enc;
8049 else
8050 drv_enc = (unsigned int) -1;
8051
8052 for (i = 0; i < NUM_WEP_KEYS; i++) {
8053 size_t len = ssid->wep_key_len[i];
8054 if (len == 0)
8055 continue;
8056 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8057 continue;
8058 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8059 continue;
8060 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8061 continue;
8062 return 1; /* invalid WEP key */
8063 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008064#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008065
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008066 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008067 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008068 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008069 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008070 return 1;
8071
Dmitry Shmidt04949592012-07-19 12:16:46 -07008072 return 0;
8073}
8074
8075
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008076int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8077{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008078 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8079 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8080 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8081 /*
8082 * Driver does not support BIP -- ignore pmf=1 default
8083 * since the connection with PMF would fail and the
8084 * configuration does not require PMF to be enabled.
8085 */
8086 return NO_MGMT_FRAME_PROTECTION;
8087 }
8088
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008089 if (ssid &&
8090 (ssid->key_mgmt &
8091 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8092 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8093 /*
8094 * Do not use the default PMF value for non-RSN networks
8095 * since PMF is available only with RSN and pmf=2
8096 * configuration would otherwise prevent connections to
8097 * all open networks.
8098 */
8099 return NO_MGMT_FRAME_PROTECTION;
8100 }
8101
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008102 return wpa_s->conf->pmf;
8103 }
8104
8105 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008106}
8107
8108
Hai Shalomc1a21442022-02-04 13:43:00 -08008109int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8110{
8111 if (wpa_s->current_ssid == NULL ||
8112 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8113 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8114 return 0;
8115 return wpa_sm_pmf_enabled(wpa_s->wpa);
8116}
8117
8118
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008119int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008120{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008121 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008122 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008123 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008124 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008125 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008126}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008127
8128
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008129void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008130{
8131 struct wpa_ssid *ssid = wpa_s->current_ssid;
8132 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008133 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008134
8135 if (ssid == NULL) {
8136 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8137 "SSID block");
8138 return;
8139 }
8140
8141 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8142 return;
8143
8144 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008145
8146#ifdef CONFIG_P2P
8147 if (ssid->p2p_group &&
8148 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8149 /*
8150 * Skip the wait time since there is a short timeout on the
8151 * connection to a P2P group.
8152 */
8153 return;
8154 }
8155#endif /* CONFIG_P2P */
8156
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008157 if (ssid->auth_failures > 50)
8158 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008159 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008160 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008161 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008162 dur = 90;
8163 else if (ssid->auth_failures > 3)
8164 dur = 60;
8165 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008166 dur = 30;
8167 else if (ssid->auth_failures > 1)
8168 dur = 20;
8169 else
8170 dur = 10;
8171
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008172 if (ssid->auth_failures > 1 &&
8173 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8174 dur += os_random() % (ssid->auth_failures * 10);
8175
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008176 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008177 if (now.sec + dur <= ssid->disabled_until.sec)
8178 return;
8179
8180 ssid->disabled_until.sec = now.sec + dur;
8181
8182 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008183 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008184 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008185 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008186
8187 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8188 int msg_len = snprintf(NULL, 0, format_str,
8189 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8190 ssid->auth_failures, dur, reason) + 1;
8191 char *msg = os_malloc(msg_len);
8192 snprintf(msg, msg_len, format_str,
8193 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8194 ssid->auth_failures, dur, reason);
8195 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8196 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008197}
8198
8199
8200void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8201 struct wpa_ssid *ssid, int clear_failures)
8202{
8203 if (ssid == NULL)
8204 return;
8205
8206 if (ssid->disabled_until.sec) {
8207 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8208 "id=%d ssid=\"%s\"",
8209 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8210 }
8211 ssid->disabled_until.sec = 0;
8212 ssid->disabled_until.usec = 0;
8213 if (clear_failures)
8214 ssid->auth_failures = 0;
8215}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008216
8217
8218int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8219{
8220 size_t i;
8221
8222 if (wpa_s->disallow_aps_bssid == NULL)
8223 return 0;
8224
8225 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8226 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8227 bssid, ETH_ALEN) == 0)
8228 return 1;
8229 }
8230
8231 return 0;
8232}
8233
8234
8235int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8236 size_t ssid_len)
8237{
8238 size_t i;
8239
8240 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8241 return 0;
8242
8243 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8244 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8245 if (ssid_len == s->ssid_len &&
8246 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8247 return 1;
8248 }
8249
8250 return 0;
8251}
8252
8253
8254/**
8255 * wpas_request_connection - Request a new connection
8256 * @wpa_s: Pointer to the network interface
8257 *
8258 * This function is used to request a new connection to be found. It will mark
8259 * the interface to allow reassociation and request a new scan to find a
8260 * suitable network to connect to.
8261 */
8262void wpas_request_connection(struct wpa_supplicant *wpa_s)
8263{
8264 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008265 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008266 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008267 wpa_s->disconnected = 0;
8268 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008269 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008270
8271 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8272 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008273 else
8274 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008275}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008276
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008277
Roshan Pius02242d72016-08-09 15:31:48 -07008278/**
8279 * wpas_request_disconnection - Request disconnection
8280 * @wpa_s: Pointer to the network interface
8281 *
8282 * This function is used to request disconnection from the currently connected
8283 * network. This will stop any ongoing scans and initiate deauthentication.
8284 */
8285void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8286{
8287#ifdef CONFIG_SME
8288 wpa_s->sme.prev_bssid_set = 0;
8289#endif /* CONFIG_SME */
8290 wpa_s->reassociate = 0;
8291 wpa_s->disconnected = 1;
8292 wpa_supplicant_cancel_sched_scan(wpa_s);
8293 wpa_supplicant_cancel_scan(wpa_s);
8294 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8295 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008296 radio_remove_works(wpa_s, "connect", 0);
8297 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008298 wpa_s->roam_in_progress = false;
8299#ifdef CONFIG_WNM
8300 wpa_s->bss_trans_mgmt_in_progress = false;
8301#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008302}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008303
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008304
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008305void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8306 struct wpa_used_freq_data *freqs_data,
8307 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008308{
8309 unsigned int i;
8310
8311 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8312 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008313 for (i = 0; i < len; i++) {
8314 struct wpa_used_freq_data *cur = &freqs_data[i];
8315 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8316 i, cur->freq, cur->flags);
8317 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008318}
8319
8320
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008321/*
8322 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008323 * are using the same radio as the current interface, and in addition, get
8324 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008325 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008326int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8327 struct wpa_used_freq_data *freqs_data,
8328 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008329{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008330 struct wpa_supplicant *ifs;
8331 u8 bssid[ETH_ALEN];
8332 int freq;
8333 unsigned int idx = 0, i;
8334
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008335 wpa_dbg(wpa_s, MSG_DEBUG,
8336 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008337 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008338
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008339 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8340 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008341 if (idx == len)
8342 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008343
8344 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8345 continue;
8346
8347 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008348 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8349 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008350 freq = ifs->current_ssid->frequency;
8351 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8352 freq = ifs->assoc_freq;
8353 else
8354 continue;
8355
8356 /* Hold only distinct freqs */
8357 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008358 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008359 break;
8360
8361 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008362 freqs_data[idx++].freq = freq;
8363
8364 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008365 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008366 WPA_FREQ_USED_BY_P2P_CLIENT :
8367 WPA_FREQ_USED_BY_INFRA_STATION;
8368 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008369 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008370
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008371 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008372 return idx;
8373}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008374
8375
8376/*
8377 * Find the operating frequencies of any of the virtual interfaces that
8378 * are using the same radio as the current interface.
8379 */
8380int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8381 int *freq_array, unsigned int len)
8382{
8383 struct wpa_used_freq_data *freqs_data;
8384 int num, i;
8385
8386 os_memset(freq_array, 0, sizeof(int) * len);
8387
8388 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8389 if (!freqs_data)
8390 return -1;
8391
8392 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8393 for (i = 0; i < num; i++)
8394 freq_array[i] = freqs_data[i].freq;
8395
8396 os_free(freqs_data);
8397
8398 return num;
8399}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008400
8401
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008402struct wpa_supplicant *
8403wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8404{
8405 switch (frame) {
8406#ifdef CONFIG_P2P
8407 case VENDOR_ELEM_PROBE_REQ_P2P:
8408 case VENDOR_ELEM_PROBE_RESP_P2P:
8409 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8410 case VENDOR_ELEM_BEACON_P2P_GO:
8411 case VENDOR_ELEM_P2P_PD_REQ:
8412 case VENDOR_ELEM_P2P_PD_RESP:
8413 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8414 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8415 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8416 case VENDOR_ELEM_P2P_INV_REQ:
8417 case VENDOR_ELEM_P2P_INV_RESP:
8418 case VENDOR_ELEM_P2P_ASSOC_REQ:
8419 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008420 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008421#endif /* CONFIG_P2P */
8422 default:
8423 return wpa_s;
8424 }
8425}
8426
8427
8428void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8429{
8430 unsigned int i;
8431 char buf[30];
8432
8433 wpa_printf(MSG_DEBUG, "Update vendor elements");
8434
8435 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8436 if (wpa_s->vendor_elem[i]) {
8437 int res;
8438
8439 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8440 if (!os_snprintf_error(sizeof(buf), res)) {
8441 wpa_hexdump_buf(MSG_DEBUG, buf,
8442 wpa_s->vendor_elem[i]);
8443 }
8444 }
8445 }
8446
8447#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008448 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008449 wpa_s->global->p2p &&
8450 !wpa_s->global->p2p_disabled)
8451 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8452#endif /* CONFIG_P2P */
8453}
8454
8455
8456int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8457 const u8 *elem, size_t len)
8458{
8459 u8 *ie, *end;
8460
8461 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8462 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8463
8464 for (; ie + 1 < end; ie += 2 + ie[1]) {
8465 if (ie + len > end)
8466 break;
8467 if (os_memcmp(ie, elem, len) != 0)
8468 continue;
8469
8470 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8471 wpabuf_free(wpa_s->vendor_elem[frame]);
8472 wpa_s->vendor_elem[frame] = NULL;
8473 } else {
8474 os_memmove(ie, ie + len, end - (ie + len));
8475 wpa_s->vendor_elem[frame]->used -= len;
8476 }
8477 wpas_vendor_elem_update(wpa_s);
8478 return 0;
8479 }
8480
8481 return -1;
8482}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008483
8484
8485struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008486 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008487 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008488{
8489 u16 i;
8490
Hai Shalomc1a21442022-02-04 13:43:00 -08008491 if (!modes)
8492 return NULL;
8493
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008494 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008495 if (modes[i].mode != mode ||
8496 !modes[i].num_channels || !modes[i].channels)
8497 continue;
8498 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8499 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008500 return &modes[i];
8501 }
8502
8503 return NULL;
8504}
8505
8506
Hai Shalomc1a21442022-02-04 13:43:00 -08008507struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8508 u16 num_modes, int freq)
8509{
8510 int i, j;
8511
8512 for (i = 0; i < num_modes; i++) {
8513 for (j = 0; j < modes[i].num_channels; j++) {
8514 if (freq == modes[i].channels[j].freq)
8515 return &modes[i];
8516 }
8517 }
8518
8519 return NULL;
8520}
8521
8522
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008523static struct
8524wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8525 const u8 *bssid)
8526{
8527 struct wpa_bss_tmp_disallowed *bss;
8528
8529 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8530 struct wpa_bss_tmp_disallowed, list) {
8531 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8532 return bss;
8533 }
8534
8535 return NULL;
8536}
8537
8538
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008539static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8540{
8541 struct wpa_bss_tmp_disallowed *tmp;
8542 unsigned int num_bssid = 0;
8543 u8 *bssids;
8544 int ret;
8545
8546 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8547 if (!bssids)
8548 return -1;
8549 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8550 struct wpa_bss_tmp_disallowed, list) {
8551 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8552 ETH_ALEN);
8553 num_bssid++;
8554 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008555 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008556 os_free(bssids);
8557 return ret;
8558}
8559
8560
8561static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8562{
8563 struct wpa_supplicant *wpa_s = eloop_ctx;
8564 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8565
8566 /* Make sure the bss is not already freed */
8567 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8568 struct wpa_bss_tmp_disallowed, list) {
8569 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008570 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008571 wpa_set_driver_tmp_disallow_list(wpa_s);
8572 break;
8573 }
8574 }
8575}
8576
8577
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008578void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008579 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008580{
8581 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008582
8583 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8584 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008585 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008586 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008587 }
8588
8589 bss = os_malloc(sizeof(*bss));
8590 if (!bss) {
8591 wpa_printf(MSG_DEBUG,
8592 "Failed to allocate memory for temp disallow BSS");
8593 return;
8594 }
8595
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008596 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8597 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008598 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008599
8600finish:
8601 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008602 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8603 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008604}
8605
8606
Hai Shalom74f70d42019-02-11 14:42:39 -08008607int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8608 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008609{
Hai Shalom74f70d42019-02-11 14:42:39 -08008610 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008611
8612 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8613 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008614 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8615 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008616 break;
8617 }
8618 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008619 if (!disallowed)
8620 return 0;
8621
8622 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008623 bss->level > disallowed->rssi_threshold) {
8624 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8625 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008626 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008627 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008628
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008629 return 1;
8630}
Hai Shalom81f62d82019-07-22 12:10:00 -07008631
8632
8633int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8634 unsigned int type, const u8 *addr,
8635 const u8 *mask)
8636{
8637 if ((addr && !mask) || (!addr && mask)) {
8638 wpa_printf(MSG_INFO,
8639 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8640 return -1;
8641 }
8642
8643 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8644 wpa_printf(MSG_INFO,
8645 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8646 return -1;
8647 }
8648
8649 if (type & MAC_ADDR_RAND_SCAN) {
8650 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8651 addr, mask))
8652 return -1;
8653 }
8654
8655 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8656 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8657 addr, mask))
8658 return -1;
8659
8660 if (wpa_s->sched_scanning && !wpa_s->pno)
8661 wpas_scan_restart_sched_scan(wpa_s);
8662 }
8663
8664 if (type & MAC_ADDR_RAND_PNO) {
8665 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8666 addr, mask))
8667 return -1;
8668
8669 if (wpa_s->pno) {
8670 wpas_stop_pno(wpa_s);
8671 wpas_start_pno(wpa_s);
8672 }
8673 }
8674
8675 return 0;
8676}
8677
8678
8679int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8680 unsigned int type)
8681{
8682 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8683 if (wpa_s->pno) {
8684 if (type & MAC_ADDR_RAND_PNO) {
8685 wpas_stop_pno(wpa_s);
8686 wpas_start_pno(wpa_s);
8687 }
8688 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8689 wpas_scan_restart_sched_scan(wpa_s);
8690 }
8691
8692 return 0;
8693}
Hai Shalomfdcde762020-04-02 11:19:20 -07008694
8695
8696int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8697 struct wpa_signal_info *si)
8698{
8699 int res;
8700
8701 if (!wpa_s->driver->signal_poll)
8702 return -1;
8703
8704 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8705
8706#ifdef CONFIG_TESTING_OPTIONS
8707 if (res == 0) {
8708 struct driver_signal_override *dso;
8709
8710 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8711 struct driver_signal_override, list) {
8712 if (os_memcmp(wpa_s->bssid, dso->bssid,
8713 ETH_ALEN) != 0)
8714 continue;
8715 wpa_printf(MSG_DEBUG,
8716 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8717 si->current_signal,
8718 dso->si_current_signal,
8719 si->avg_signal,
8720 dso->si_avg_signal,
8721 si->avg_beacon_signal,
8722 dso->si_avg_beacon_signal,
8723 si->current_noise,
8724 dso->si_current_noise);
8725 si->current_signal = dso->si_current_signal;
8726 si->avg_signal = dso->si_avg_signal;
8727 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8728 si->current_noise = dso->si_current_noise;
8729 break;
8730 }
8731 }
8732#endif /* CONFIG_TESTING_OPTIONS */
8733
8734 return res;
8735}
8736
8737
8738struct wpa_scan_results *
8739wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8740{
8741 struct wpa_scan_results *scan_res;
8742#ifdef CONFIG_TESTING_OPTIONS
8743 size_t idx;
8744#endif /* CONFIG_TESTING_OPTIONS */
8745
8746 if (!wpa_s->driver->get_scan_results2)
8747 return NULL;
8748
8749 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8750
8751#ifdef CONFIG_TESTING_OPTIONS
8752 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8753 struct driver_signal_override *dso;
8754 struct wpa_scan_res *res = scan_res->res[idx];
8755
8756 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8757 struct driver_signal_override, list) {
8758 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8759 continue;
8760 wpa_printf(MSG_DEBUG,
8761 "Override driver scan signal level %d->%d for "
8762 MACSTR,
8763 res->level, dso->scan_level,
8764 MAC2STR(res->bssid));
8765 res->flags |= WPA_SCAN_QUAL_INVALID;
8766 if (dso->scan_level < 0)
8767 res->flags |= WPA_SCAN_LEVEL_DBM;
8768 else
8769 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8770 res->level = dso->scan_level;
8771 break;
8772 }
8773 }
8774#endif /* CONFIG_TESTING_OPTIONS */
8775
8776 return scan_res;
8777}