blob: 54d223d115c60e5d1f1b8b46add184481704acd7 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalom74f70d42019-02-11 14:42:39 -08003 * Copyright (c) 2003-2019, 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 Shalom74f70d42019-02-11 14:42:39 -080074"Copyright (c) 2003-2019, 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 Shalom74f70d42019-02-11 14:42:39 -0800465void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800466{
467 struct wpa_bss_tmp_disallowed *bss, *prev;
468
469 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
470 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700471 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800472 dl_list_del(&bss->list);
473 os_free(bss);
474 }
475}
476
477
Paul Stewart092955c2017-02-06 09:13:09 -0800478void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
479{
480 struct fils_hlp_req *req;
481
482 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
483 list)) != NULL) {
484 dl_list_del(&req->list);
485 wpabuf_free(req->pkt);
486 os_free(req);
487 }
488}
489
490
Hai Shalomfdcde762020-04-02 11:19:20 -0700491void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
492{
493 struct wpa_supplicant *wpa_s = eloop_ctx;
494
495 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
496 return;
497 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
498 wpa_bss_flush(wpa_s);
499}
500
501
502#ifdef CONFIG_TESTING_OPTIONS
503void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
504{
505 struct driver_signal_override *dso;
506
507 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
508 struct driver_signal_override, list))) {
509 dl_list_del(&dso->list);
510 os_free(dso);
511 }
512}
513#endif /* CONFIG_TESTING_OPTIONS */
514
515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
517{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700518 int i;
519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700521 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522 scard_deinit(wpa_s->scard);
523 wpa_s->scard = NULL;
524 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
525 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
526 l2_packet_deinit(wpa_s->l2);
527 wpa_s->l2 = NULL;
528 if (wpa_s->l2_br) {
529 l2_packet_deinit(wpa_s->l2_br);
530 wpa_s->l2_br = NULL;
531 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800532#ifdef CONFIG_TESTING_OPTIONS
533 l2_packet_deinit(wpa_s->l2_test);
534 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800535 os_free(wpa_s->get_pref_freq_list_override);
536 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700537 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
538 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800539 os_free(wpa_s->extra_sae_rejected_groups);
540 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700541 wpabuf_free(wpa_s->rsne_override_eapol);
542 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800543 wpabuf_free(wpa_s->rsnxe_override_assoc);
544 wpa_s->rsnxe_override_assoc = NULL;
545 wpabuf_free(wpa_s->rsnxe_override_eapol);
546 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700547 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800548#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 if (wpa_s->conf != NULL) {
551 struct wpa_ssid *ssid;
552 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
553 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554 }
555
556 os_free(wpa_s->confname);
557 wpa_s->confname = NULL;
558
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700559 os_free(wpa_s->confanother);
560 wpa_s->confanother = NULL;
561
Hai Shalomce48b4a2018-09-05 11:41:35 -0700562 os_free(wpa_s->last_con_fail_realm);
563 wpa_s->last_con_fail_realm = NULL;
564 wpa_s->last_con_fail_realm_len = 0;
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566 wpa_sm_set_eapol(wpa_s->wpa, NULL);
567 eapol_sm_deinit(wpa_s->eapol);
568 wpa_s->eapol = NULL;
569
570 rsn_preauth_deinit(wpa_s->wpa);
571
572#ifdef CONFIG_TDLS
573 wpa_tdls_deinit(wpa_s->wpa);
574#endif /* CONFIG_TDLS */
575
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800576 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800578 ptksa_cache_deinit(wpa_s->ptksa);
579 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 wpa_sm_deinit(wpa_s->wpa);
581 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800582 wpa_bssid_ignore_clear(wpa_s);
583
584#ifdef CONFIG_PASN
585 wpas_pasn_auth_stop(wpa_s);
586#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587
588 wpa_bss_deinit(wpa_s);
589
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700590 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_supplicant_cancel_scan(wpa_s);
592 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800593 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
594#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
595 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
596 wpa_s, NULL);
597#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700599 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700600 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpas_wps_deinit(wpa_s);
603
604 wpabuf_free(wpa_s->pending_eapol_rx);
605 wpa_s->pending_eapol_rx = NULL;
606
607#ifdef CONFIG_IBSS_RSN
608 ibss_rsn_deinit(wpa_s->ibss_rsn);
609 wpa_s->ibss_rsn = NULL;
610#endif /* CONFIG_IBSS_RSN */
611
612 sme_deinit(wpa_s);
613
614#ifdef CONFIG_AP
615 wpa_supplicant_ap_deinit(wpa_s);
616#endif /* CONFIG_AP */
617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800620#ifdef CONFIG_OFFCHANNEL
621 offchannel_deinit(wpa_s);
622#endif /* CONFIG_OFFCHANNEL */
623
624 wpa_supplicant_cancel_sched_scan(wpa_s);
625
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 os_free(wpa_s->next_scan_freqs);
627 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800628
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800629 os_free(wpa_s->manual_scan_freqs);
630 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700631 os_free(wpa_s->select_network_scan_freqs);
632 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800633
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700634 os_free(wpa_s->manual_sched_scan_freqs);
635 wpa_s->manual_sched_scan_freqs = NULL;
636
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800637 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
638
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700639 /*
640 * Need to remove any pending gas-query radio work before the
641 * gas_query_deinit() call because gas_query::work has not yet been set
642 * for works that have not been started. gas_query_free() will be unable
643 * to cancel such pending radio works and once the pending gas-query
644 * radio work eventually gets removed, the deinit notification call to
645 * gas_query_start_cb() would result in dereferencing freed memory.
646 */
647 if (wpa_s->radio)
648 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800649 gas_query_deinit(wpa_s->gas);
650 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 gas_server_deinit(wpa_s->gas_server);
652 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800653
654 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700655
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700656 ieee802_1x_dealloc_kay_sm(wpa_s);
657
Dmitry Shmidt04949592012-07-19 12:16:46 -0700658 os_free(wpa_s->bssid_filter);
659 wpa_s->bssid_filter = NULL;
660
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800661 os_free(wpa_s->disallow_aps_bssid);
662 wpa_s->disallow_aps_bssid = NULL;
663 os_free(wpa_s->disallow_aps_ssid);
664 wpa_s->disallow_aps_ssid = NULL;
665
Dmitry Shmidt04949592012-07-19 12:16:46 -0700666 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700667#ifdef CONFIG_WNM
668 wnm_deallocate_memory(wpa_s);
669#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670
671 ext_password_deinit(wpa_s->ext_pw);
672 wpa_s->ext_pw = NULL;
673
674 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800675 wpa_s->last_gas_resp = NULL;
676 wpabuf_free(wpa_s->prev_gas_resp);
677 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700678
679 os_free(wpa_s->last_scan_res);
680 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800681
682#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700683 if (wpa_s->drv_priv)
684 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700685 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800686#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700687
688 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
689 wpabuf_free(wpa_s->vendor_elem[i]);
690 wpa_s->vendor_elem[i] = NULL;
691 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800692
693 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800694
695 wpa_s->sched_scan_plans_num = 0;
696 os_free(wpa_s->sched_scan_plans);
697 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800698
699#ifdef CONFIG_MBO
700 wpa_s->non_pref_chan_num = 0;
701 os_free(wpa_s->non_pref_chan);
702 wpa_s->non_pref_chan = NULL;
703#endif /* CONFIG_MBO */
704
705 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700706
707 wpabuf_free(wpa_s->lci);
708 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800709 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800710
711#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
712#ifdef CONFIG_MESH
713 {
714 struct external_pmksa_cache *entry;
715
716 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
717 struct external_pmksa_cache,
718 list)) != NULL) {
719 dl_list_del(&entry->list);
720 os_free(entry->pmksa_cache);
721 os_free(entry);
722 }
723 }
724#endif /* CONFIG_MESH */
725#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
726
727 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800728
729 wpabuf_free(wpa_s->ric_ies);
730 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700731
732#ifdef CONFIG_DPP
733 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700734 dpp_global_deinit(wpa_s->dpp);
735 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700736#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800737
738#ifdef CONFIG_PASN
739 wpas_pasn_auth_stop(wpa_s);
740#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741}
742
743
744/**
745 * wpa_clear_keys - Clear keys configured for the driver
746 * @wpa_s: Pointer to wpa_supplicant data
747 * @addr: Previously used BSSID or %NULL if not available
748 *
749 * This function clears the encryption keys that has been previously configured
750 * for the driver.
751 */
752void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
753{
Hai Shalomc3565922019-10-28 11:58:20 -0700754 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755
756 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800757 for (i = 0; i < max; i++) {
758 if (wpa_s->keys_cleared & BIT(i))
759 continue;
760 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700761 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700763 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
764 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700766 if (!(wpa_s->keys_cleared & BIT(0)))
767 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
768 0, NULL, 0, KEY_FLAG_PAIRWISE);
769 if (!(wpa_s->keys_cleared & BIT(15)))
770 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
771 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 /* MLME-SETPROTECTION.request(None) */
773 wpa_drv_mlme_setprotection(
774 wpa_s, addr,
775 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
776 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
777 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800778 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779}
780
781
782/**
783 * wpa_supplicant_state_txt - Get the connection state name as a text string
784 * @state: State (wpa_state; WPA_*)
785 * Returns: The state name as a printable text string
786 */
787const char * wpa_supplicant_state_txt(enum wpa_states state)
788{
789 switch (state) {
790 case WPA_DISCONNECTED:
791 return "DISCONNECTED";
792 case WPA_INACTIVE:
793 return "INACTIVE";
794 case WPA_INTERFACE_DISABLED:
795 return "INTERFACE_DISABLED";
796 case WPA_SCANNING:
797 return "SCANNING";
798 case WPA_AUTHENTICATING:
799 return "AUTHENTICATING";
800 case WPA_ASSOCIATING:
801 return "ASSOCIATING";
802 case WPA_ASSOCIATED:
803 return "ASSOCIATED";
804 case WPA_4WAY_HANDSHAKE:
805 return "4WAY_HANDSHAKE";
806 case WPA_GROUP_HANDSHAKE:
807 return "GROUP_HANDSHAKE";
808 case WPA_COMPLETED:
809 return "COMPLETED";
810 default:
811 return "UNKNOWN";
812 }
813}
814
815
816#ifdef CONFIG_BGSCAN
817
Hai Shalom899fcc72020-10-19 14:38:18 -0700818static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
819{
820 if (wpa_s->bgscan_ssid) {
821 bgscan_deinit(wpa_s);
822 wpa_s->bgscan_ssid = NULL;
823 }
824}
825
826
827/**
828 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
829 * @wpa_s: Pointer to the wpa_supplicant data
830 *
831 * Stop, start, or reconfigure the scan parameters depending on the method.
832 */
833void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800835 const char *name;
836
837 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
838 name = wpa_s->current_ssid->bgscan;
839 else
840 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700841 if (!name || name[0] == '\0') {
842 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800843 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700844 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800845 if (wpas_driver_bss_selection(wpa_s))
846 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800847#ifdef CONFIG_P2P
848 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
849 return;
850#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851
852 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800853 if (wpa_s->current_ssid) {
854 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
856 "bgscan");
857 /*
858 * Live without bgscan; it is only used as a roaming
859 * optimization, so the initial connection is not
860 * affected.
861 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700862 } else {
863 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700865 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
866 0);
867 if (scan_res) {
868 bgscan_notify_scan(wpa_s, scan_res);
869 wpa_scan_results_free(scan_res);
870 }
871 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 } else
873 wpa_s->bgscan_ssid = NULL;
874}
875
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876#endif /* CONFIG_BGSCAN */
877
878
Dmitry Shmidt04949592012-07-19 12:16:46 -0700879static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
880{
881 if (autoscan_init(wpa_s, 0))
882 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
883}
884
885
886static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
887{
888 autoscan_deinit(wpa_s);
889}
890
891
892void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
893{
894 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
895 wpa_s->wpa_state == WPA_SCANNING) {
896 autoscan_deinit(wpa_s);
897 wpa_supplicant_start_autoscan(wpa_s);
898 }
899}
900
901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902/**
903 * wpa_supplicant_set_state - Set current connection state
904 * @wpa_s: Pointer to wpa_supplicant data
905 * @state: The new connection state
906 *
907 * This function is called whenever the connection state changes, e.g.,
908 * association is completed for WPA/WPA2 4-Way Handshake is started.
909 */
910void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
911 enum wpa_states state)
912{
913 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700914#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700915 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700916#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917
918 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
919 wpa_supplicant_state_txt(wpa_s->wpa_state),
920 wpa_supplicant_state_txt(state));
921
Hai Shalom74f70d42019-02-11 14:42:39 -0800922 if (state == WPA_COMPLETED &&
923 os_reltime_initialized(&wpa_s->roam_start)) {
924 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
925 wpa_s->roam_start.sec = 0;
926 wpa_s->roam_start.usec = 0;
927 wpas_notify_auth_changed(wpa_s);
928 wpas_notify_roam_time(wpa_s);
929 wpas_notify_roam_complete(wpa_s);
930 } else if (state == WPA_DISCONNECTED &&
931 os_reltime_initialized(&wpa_s->roam_start)) {
932 wpa_s->roam_start.sec = 0;
933 wpa_s->roam_start.usec = 0;
934 wpa_s->roam_time.sec = 0;
935 wpa_s->roam_time.usec = 0;
936 wpas_notify_roam_complete(wpa_s);
937 }
938
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800939 if (state == WPA_INTERFACE_DISABLED) {
940 /* Assure normal scan when interface is restored */
941 wpa_s->normal_scans = 0;
942 }
943
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700944 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800945 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700946 /* Reinitialize normal_scan counter */
947 wpa_s->normal_scans = 0;
948 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800949
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700950#ifdef CONFIG_P2P
951 /*
952 * P2PS client has to reply to Probe Request frames received on the
953 * group operating channel. Enable Probe Request frame reporting for
954 * P2P connected client in case p2p_cli_probe configuration property is
955 * set to 1.
956 */
957 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
958 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
959 wpa_s->current_ssid->p2p_group) {
960 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
961 wpa_dbg(wpa_s, MSG_DEBUG,
962 "P2P: Enable CLI Probe Request RX reporting");
963 wpa_s->p2p_cli_probe =
964 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
965 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
966 wpa_dbg(wpa_s, MSG_DEBUG,
967 "P2P: Disable CLI Probe Request RX reporting");
968 wpa_s->p2p_cli_probe = 0;
969 wpa_drv_probe_req_report(wpa_s, 0);
970 }
971 }
972#endif /* CONFIG_P2P */
973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 if (state != WPA_SCANNING)
975 wpa_supplicant_notify_scanning(wpa_s, 0);
976
977 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700979 int fils_hlp_sent = 0;
980
981#ifdef CONFIG_SME
982 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
983 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
984 fils_hlp_sent = 1;
985#endif /* CONFIG_SME */
986 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
987 wpa_auth_alg_fils(wpa_s->auth_alg))
988 fils_hlp_sent = 1;
989
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700990#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700992 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800993 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700995 ssid && ssid->id_str ? ssid->id_str : "",
996 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700997#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700998 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -0700999 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001 wpa_drv_set_operstate(wpa_s, 1);
1002#ifndef IEEE8021X_EAPOL
1003 wpa_drv_set_supp_port(wpa_s, 1);
1004#endif /* IEEE8021X_EAPOL */
1005 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001006 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001008
1009 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001010
1011#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1012 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001013 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001014#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001015#ifdef CONFIG_OWE
1016 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1017 wpas_update_owe_connect_params(wpa_s);
1018#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001019#ifdef CONFIG_HS20
1020 hs20_configure_frame_filters(wpa_s);
1021#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1023 state == WPA_ASSOCIATED) {
1024 wpa_s->new_connection = 1;
1025 wpa_drv_set_operstate(wpa_s, 0);
1026#ifndef IEEE8021X_EAPOL
1027 wpa_drv_set_supp_port(wpa_s, 0);
1028#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001029 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 }
1031 wpa_s->wpa_state = state;
1032
1033#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001034 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1035 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001036 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 wpa_supplicant_stop_bgscan(wpa_s);
1038#endif /* CONFIG_BGSCAN */
1039
Hai Shalom5f92bc92019-04-18 11:54:11 -07001040 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001041 wpa_supplicant_stop_autoscan(wpa_s);
1042
1043 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1044 wpa_supplicant_start_autoscan(wpa_s);
1045
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001046 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1047 wmm_ac_notify_disassoc(wpa_s);
1048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 if (wpa_s->wpa_state != old_state) {
1050 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1051
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001052 /*
1053 * Notify the P2P Device interface about a state change in one
1054 * of the interfaces.
1055 */
1056 wpas_p2p_indicate_state_change(wpa_s);
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 if (wpa_s->wpa_state == WPA_COMPLETED ||
1059 old_state == WPA_COMPLETED)
1060 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001061#ifdef CONFIG_DPP2
1062 if (wpa_s->wpa_state == WPA_COMPLETED)
1063 wpas_dpp_connected(wpa_s);
1064#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065 }
Hai Shalomc3565922019-10-28 11:58:20 -07001066#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1067 if (update_fils_connect_params)
1068 wpas_update_fils_connect_params(wpa_s);
1069#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070}
1071
1072
1073void wpa_supplicant_terminate_proc(struct wpa_global *global)
1074{
1075 int pending = 0;
1076#ifdef CONFIG_WPS
1077 struct wpa_supplicant *wpa_s = global->ifaces;
1078 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001079 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001080 if (wpas_wps_terminate_pending(wpa_s) == 1)
1081 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001082#ifdef CONFIG_P2P
1083 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1084 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1085 wpas_p2p_disconnect(wpa_s);
1086#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088 }
1089#endif /* CONFIG_WPS */
1090 if (pending)
1091 return;
1092 eloop_terminate();
1093}
1094
1095
1096static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1097{
1098 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 wpa_supplicant_terminate_proc(global);
1100}
1101
1102
1103void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1104{
1105 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001106 enum wpa_states new_state;
1107
1108 if (old_state == WPA_SCANNING)
1109 new_state = WPA_SCANNING;
1110 else
1111 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112
1113 wpa_s->pairwise_cipher = 0;
1114 wpa_s->group_cipher = 0;
1115 wpa_s->mgmt_group_cipher = 0;
1116 wpa_s->key_mgmt = 0;
1117 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001118 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119
1120 if (wpa_s->wpa_state != old_state)
1121 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1122}
1123
1124
1125/**
1126 * wpa_supplicant_reload_configuration - Reload configuration data
1127 * @wpa_s: Pointer to wpa_supplicant data
1128 * Returns: 0 on success or -1 if configuration parsing failed
1129 *
1130 * This function can be used to request that the configuration data is reloaded
1131 * (e.g., after configuration file change). This function is reloading
1132 * configuration only for one interface, so this may need to be called multiple
1133 * times if %wpa_supplicant is controlling multiple interfaces and all
1134 * interfaces need reconfiguration.
1135 */
1136int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1137{
1138 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 int reconf_ctrl;
1140 int old_ap_scan;
1141
1142 if (wpa_s->confname == NULL)
1143 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001144 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145 if (conf == NULL) {
1146 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1147 "file '%s' - exiting", wpa_s->confname);
1148 return -1;
1149 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001150 if (wpa_s->confanother &&
1151 !wpa_config_read(wpa_s->confanother, conf)) {
1152 wpa_msg(wpa_s, MSG_ERROR,
1153 "Failed to parse the configuration file '%s' - exiting",
1154 wpa_s->confanother);
1155 return -1;
1156 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001157
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 conf->changed_parameters = (unsigned int) -1;
1159
1160 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1161 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1162 os_strcmp(conf->ctrl_interface,
1163 wpa_s->conf->ctrl_interface) != 0);
1164
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001165 if (reconf_ctrl) {
1166 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 wpa_s->ctrl_iface = NULL;
1168 }
1169
1170 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001171 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001172 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1173 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001174 wpa_supplicant_deauthenticate(wpa_s,
1175 WLAN_REASON_DEAUTH_LEAVING);
1176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177
1178 /*
1179 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001182 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1183 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1184 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 /*
1186 * Clear forced success to clear EAP state for next
1187 * authentication.
1188 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001189 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 }
1191 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1192 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001193 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1195 rsn_preauth_deinit(wpa_s->wpa);
1196
1197 old_ap_scan = wpa_s->conf->ap_scan;
1198 wpa_config_free(wpa_s->conf);
1199 wpa_s->conf = conf;
1200 if (old_ap_scan != wpa_s->conf->ap_scan)
1201 wpas_notify_ap_scan_changed(wpa_s);
1202
1203 if (reconf_ctrl)
1204 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1205
1206 wpa_supplicant_update_config(wpa_s);
1207
1208 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001209 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_s->reassociate = 1;
1211 wpa_supplicant_req_scan(wpa_s, 0, 0);
1212 }
Hai Shalom60840252021-02-19 19:02:11 -08001213 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1215 return 0;
1216}
1217
1218
1219static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1220{
1221 struct wpa_global *global = signal_ctx;
1222 struct wpa_supplicant *wpa_s;
1223 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1224 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1225 sig);
1226 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1227 wpa_supplicant_terminate_proc(global);
1228 }
1229 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001230
1231 if (wpa_debug_reopen_file() < 0) {
1232 /* Ignore errors since we cannot really do much to fix this */
1233 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235}
1236
1237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1239 struct wpa_ssid *ssid,
1240 struct wpa_ie_data *ie)
1241{
1242 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1243 if (ret) {
1244 if (ret == -2) {
1245 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1246 "from association info");
1247 }
1248 return -1;
1249 }
1250
1251 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1252 "cipher suites");
1253 if (!(ie->group_cipher & ssid->group_cipher)) {
1254 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1255 "cipher 0x%x (mask 0x%x) - reject",
1256 ie->group_cipher, ssid->group_cipher);
1257 return -1;
1258 }
1259 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1260 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1261 "cipher 0x%x (mask 0x%x) - reject",
1262 ie->pairwise_cipher, ssid->pairwise_cipher);
1263 return -1;
1264 }
1265 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1266 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1267 "management 0x%x (mask 0x%x) - reject",
1268 ie->key_mgmt, ssid->key_mgmt);
1269 return -1;
1270 }
1271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001272 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001273 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1275 "that does not support management frame protection - "
1276 "reject");
1277 return -1;
1278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279
1280 return 0;
1281}
1282
1283
Hai Shalom021b0b52019-04-10 11:17:58 -07001284static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1285 int freq)
1286{
1287 if (!ie->has_group)
1288 ie->group_cipher = wpa_default_rsn_cipher(freq);
1289 if (!ie->has_pairwise)
1290 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1291 return (ie->group_cipher & ssid->group_cipher) &&
1292 (ie->pairwise_cipher & ssid->pairwise_cipher);
1293}
1294
1295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296/**
1297 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1298 * @wpa_s: Pointer to wpa_supplicant data
1299 * @bss: Scan results for the selected BSS, or %NULL if not available
1300 * @ssid: Configuration data for the selected network
1301 * @wpa_ie: Buffer for the WPA/RSN IE
1302 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1303 * used buffer length in case the functions returns success.
1304 * Returns: 0 on success or -1 on failure
1305 *
1306 * This function is used to configure authentication and encryption parameters
1307 * based on the network configuration and scan result for the selected BSS (if
1308 * available).
1309 */
1310int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1311 struct wpa_bss *bss, struct wpa_ssid *ssid,
1312 u8 *wpa_ie, size_t *wpa_ie_len)
1313{
1314 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001315 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001316 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317
1318 if (bss) {
1319 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1320 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001321 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001322 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001323 } else {
1324 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1325 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001326
1327 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1328 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001329 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 (ie.key_mgmt & ssid->key_mgmt)) {
1331 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1332 proto = WPA_PROTO_RSN;
1333 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001334 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335 (ie.group_cipher & ssid->group_cipher) &&
1336 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1337 (ie.key_mgmt & ssid->key_mgmt)) {
1338 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1339 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001340#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001341 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1342 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1343 (ie.group_cipher & ssid->group_cipher) &&
1344 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1345 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001346 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001347 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001348 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1349 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1350 (ie.group_cipher & ssid->group_cipher) &&
1351 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1352 (ie.key_mgmt & ssid->key_mgmt)) {
1353 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1354 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001355#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356 } else if (bss) {
1357 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001358 wpa_dbg(wpa_s, MSG_DEBUG,
1359 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1360 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1361 ssid->key_mgmt);
1362 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1363 MAC2STR(bss->bssid),
1364 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1365 bss_wpa ? " WPA" : "",
1366 bss_rsn ? " RSN" : "",
1367 bss_osen ? " OSEN" : "");
1368 if (bss_rsn) {
1369 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1370 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1371 wpa_dbg(wpa_s, MSG_DEBUG,
1372 "Could not parse RSN element");
1373 } else {
1374 wpa_dbg(wpa_s, MSG_DEBUG,
1375 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1376 ie.pairwise_cipher, ie.group_cipher,
1377 ie.key_mgmt);
1378 }
1379 }
1380 if (bss_wpa) {
1381 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1382 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1383 wpa_dbg(wpa_s, MSG_DEBUG,
1384 "Could not parse WPA element");
1385 } else {
1386 wpa_dbg(wpa_s, MSG_DEBUG,
1387 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1388 ie.pairwise_cipher, ie.group_cipher,
1389 ie.key_mgmt);
1390 }
1391 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 return -1;
1393 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001394 if (ssid->proto & WPA_PROTO_OSEN)
1395 proto = WPA_PROTO_OSEN;
1396 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 proto = WPA_PROTO_RSN;
1398 else
1399 proto = WPA_PROTO_WPA;
1400 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1401 os_memset(&ie, 0, sizeof(ie));
1402 ie.group_cipher = ssid->group_cipher;
1403 ie.pairwise_cipher = ssid->pairwise_cipher;
1404 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405 ie.mgmt_group_cipher = 0;
1406 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1407 if (ssid->group_mgmt_cipher &
1408 WPA_CIPHER_BIP_GMAC_256)
1409 ie.mgmt_group_cipher =
1410 WPA_CIPHER_BIP_GMAC_256;
1411 else if (ssid->group_mgmt_cipher &
1412 WPA_CIPHER_BIP_CMAC_256)
1413 ie.mgmt_group_cipher =
1414 WPA_CIPHER_BIP_CMAC_256;
1415 else if (ssid->group_mgmt_cipher &
1416 WPA_CIPHER_BIP_GMAC_128)
1417 ie.mgmt_group_cipher =
1418 WPA_CIPHER_BIP_GMAC_128;
1419 else
1420 ie.mgmt_group_cipher =
1421 WPA_CIPHER_AES_128_CMAC;
1422 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001423#ifdef CONFIG_OWE
1424 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1425 !ssid->owe_only &&
1426 !bss_wpa && !bss_rsn && !bss_osen) {
1427 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1428 wpa_s->wpa_proto = 0;
1429 *wpa_ie_len = 0;
1430 return 0;
1431 }
1432#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1434 "based on configuration");
1435 } else
1436 proto = ie.proto;
1437 }
1438
1439 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1440 "pairwise %d key_mgmt %d proto %d",
1441 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 if (ssid->ieee80211w) {
1443 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1444 ie.mgmt_group_cipher);
1445 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001447 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001450 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451
1452 if (bss || !wpa_s->ap_ies_from_associnfo) {
1453 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1454 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1455 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001456 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1457 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1458 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 return -1;
1460 }
1461
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001462#ifdef CONFIG_NO_WPA
1463 wpa_s->group_cipher = WPA_CIPHER_NONE;
1464 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1465#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001467 wpa_dbg(wpa_s, MSG_DEBUG,
1468 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1469 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001470 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1471 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1473 "cipher");
1474 return -1;
1475 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001476 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1477 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478
1479 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001480 wpa_dbg(wpa_s, MSG_DEBUG,
1481 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1482 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001483 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1484 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1486 "cipher");
1487 return -1;
1488 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001489 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1490 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001491#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492
1493 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001494#ifdef CONFIG_SAE
1495 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1496 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1497#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001498#ifdef CONFIG_IEEE80211R
1499 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1500 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1501 sel &= ~WPA_KEY_MGMT_FT;
1502#endif /* CONFIG_IEEE80211R */
1503 wpa_dbg(wpa_s, MSG_DEBUG,
1504 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1505 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001507#ifdef CONFIG_IEEE80211R
1508#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001509 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1510 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1512 wpa_dbg(wpa_s, MSG_DEBUG,
1513 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001514 if (!ssid->ft_eap_pmksa_caching &&
1515 pmksa_cache_get_current(wpa_s->wpa)) {
1516 /* PMKSA caching with FT may have interoperability
1517 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001518 wpa_dbg(wpa_s, MSG_DEBUG,
1519 "WPA: Disable PMKSA caching for FT/802.1X connection");
1520 pmksa_cache_clear_current(wpa_s->wpa);
1521 }
1522#endif /* CONFIG_SHA384 */
1523#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001524#ifdef CONFIG_SUITEB192
1525 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1526 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1527 wpa_dbg(wpa_s, MSG_DEBUG,
1528 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1529#endif /* CONFIG_SUITEB192 */
1530#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001531 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1532 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1533 wpa_dbg(wpa_s, MSG_DEBUG,
1534 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001535#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001536#ifdef CONFIG_FILS
1537#ifdef CONFIG_IEEE80211R
1538 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1539 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1540 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1541 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1544#endif /* CONFIG_IEEE80211R */
1545 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1546 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1547 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1548 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1549 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1550 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1551#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001553 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1554 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001557 if (!ssid->ft_eap_pmksa_caching &&
1558 pmksa_cache_get_current(wpa_s->wpa)) {
1559 /* PMKSA caching with FT may have interoperability
1560 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001561 wpa_dbg(wpa_s, MSG_DEBUG,
1562 "WPA: Disable PMKSA caching for FT/802.1X connection");
1563 pmksa_cache_clear_current(wpa_s->wpa);
1564 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001565#endif /* CONFIG_IEEE80211R */
1566#ifdef CONFIG_DPP
1567 } else if (sel & WPA_KEY_MGMT_DPP) {
1568 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1569 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1570#endif /* CONFIG_DPP */
1571#ifdef CONFIG_SAE
1572 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1575 } else if (sel & WPA_KEY_MGMT_SAE) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1577 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1578#endif /* CONFIG_SAE */
1579#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1581 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1582 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1583#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1585 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1586 wpa_dbg(wpa_s, MSG_DEBUG,
1587 "WPA: using KEY_MGMT 802.1X with SHA256");
1588 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1589 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1590 wpa_dbg(wpa_s, MSG_DEBUG,
1591 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1593 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1594 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1595 } else if (sel & WPA_KEY_MGMT_PSK) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1598 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1599 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1600 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001601#ifdef CONFIG_HS20
1602 } else if (sel & WPA_KEY_MGMT_OSEN) {
1603 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1604 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1605#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001606#ifdef CONFIG_OWE
1607 } else if (sel & WPA_KEY_MGMT_OWE) {
1608 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1609 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1610#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 } else {
1612 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1613 "authenticated key management type");
1614 return -1;
1615 }
1616
1617 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1618 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1619 wpa_s->pairwise_cipher);
1620 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1621
Hai Shalomc3565922019-10-28 11:58:20 -07001622 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1623 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1624 wpa_msg(wpa_s, MSG_INFO,
1625 "RSN: Management frame protection required but the selected AP does not enable it");
1626 return -1;
1627 }
1628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001630 if (ssid->group_mgmt_cipher)
1631 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001632 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1634 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001635 wpa_dbg(wpa_s, MSG_DEBUG,
1636 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1637 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001638 if (sel & WPA_CIPHER_AES_128_CMAC) {
1639 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1640 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1641 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001642 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1643 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1644 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1645 "BIP-GMAC-128");
1646 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1647 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1648 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1649 "BIP-GMAC-256");
1650 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1651 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1652 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1653 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 } else {
1655 wpa_s->mgmt_group_cipher = 0;
1656 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1657 }
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1659 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001660 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001661 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001662#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001663 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1664 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001666#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001667 sae_pwe = wpa_s->conf->sae_pwe;
1668 if (ssid->sae_password_id && sae_pwe != 3)
1669 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001670 if (bss && is_6ghz_freq(bss->freq)) {
1671 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1672 sae_pwe = 1;
1673 }
1674#ifdef CONFIG_TESTING_OPTIONS
1675 if (wpa_s->force_hunting_and_pecking_pwe) {
1676 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1677 sae_pwe = 0;
1678 }
1679#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001680 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001681#ifdef CONFIG_SAE_PK
1682 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1683 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1684 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1685 ((ssid->sae_password &&
1686 sae_pk_valid_password(ssid->sae_password)) ||
1687 (!ssid->sae_password && ssid->passphrase &&
1688 sae_pk_valid_password(ssid->passphrase))));
1689#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001690#ifdef CONFIG_TESTING_OPTIONS
1691 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1692 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001693 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1694 wpa_s->oci_freq_override_eapol);
1695 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1696 wpa_s->oci_freq_override_eapol_g2);
1697 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1698 wpa_s->oci_freq_override_ft_assoc);
1699 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1700 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001701#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001702
1703 /* Extended Key ID is only supported in infrastructure BSS so far */
1704 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1705 (ssid->proto & WPA_PROTO_RSN) &&
1706 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1707 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1708 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1709 int use_ext_key_id = 0;
1710
1711 wpa_msg(wpa_s, MSG_DEBUG,
1712 "WPA: Enable Extended Key ID support");
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1714 wpa_s->conf->extended_key_id);
1715 if (bss_rsn &&
1716 wpa_s->conf->extended_key_id &&
1717 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1718 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1719 use_ext_key_id = 1;
1720 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1721 use_ext_key_id);
1722 } else {
1723 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1724 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1725 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726
1727 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1728 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1729 return -1;
1730 }
1731
Hai Shalomc3565922019-10-28 11:58:20 -07001732 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1733 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1734 &wpa_s->rsnxe_len)) {
1735 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1736 return -1;
1737 }
1738
Hai Shalom021b0b52019-04-10 11:17:58 -07001739 if (0) {
1740#ifdef CONFIG_DPP
1741 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1742 /* Use PMK from DPP network introduction (PMKSA entry) */
1743 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001744#ifdef CONFIG_DPP2
1745 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1746#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001747#endif /* CONFIG_DPP */
1748 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001749 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001750 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001751
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1753 WPA_KEY_MGMT_FT_PSK |
1754 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1755
1756 if (ssid->psk_set && !sae_only) {
1757 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1758 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001759 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1760 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001761 psk_set = 1;
1762 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001763
Roshan Pius3a1667e2018-07-03 15:17:14 -07001764 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1765 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001766 psk_set = 1;
1767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001768#ifndef CONFIG_NO_PBKDF2
1769 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001771 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001772 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1773 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001774 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1775 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001776 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001777 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001778 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001779 }
1780#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001781#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001782 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001783 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1784 ssid->ext_psk);
1785 char pw_str[64 + 1];
1786 u8 psk[PMK_LEN];
1787
1788 if (pw == NULL) {
1789 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1790 "found from external storage");
1791 return -1;
1792 }
1793
1794 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1795 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1796 "PSK length %d in external storage",
1797 (int) wpabuf_len(pw));
1798 ext_password_free(pw);
1799 return -1;
1800 }
1801
1802 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1803 pw_str[wpabuf_len(pw)] = '\0';
1804
1805#ifndef CONFIG_NO_PBKDF2
1806 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1807 {
1808 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1809 4096, psk, PMK_LEN);
1810 os_memset(pw_str, 0, sizeof(pw_str));
1811 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1812 "external passphrase)",
1813 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001814 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1815 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001816 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001817 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001818 } else
1819#endif /* CONFIG_NO_PBKDF2 */
1820 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1821 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1822 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1823 "Invalid PSK hex string");
1824 os_memset(pw_str, 0, sizeof(pw_str));
1825 ext_password_free(pw);
1826 return -1;
1827 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001828 wpa_hexdump_key(MSG_MSGDUMP,
1829 "PSK (from external PSK)",
1830 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001831 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1832 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001833 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001834 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001835 } else {
1836 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1837 "PSK available");
1838 os_memset(pw_str, 0, sizeof(pw_str));
1839 ext_password_free(pw);
1840 return -1;
1841 }
1842
1843 os_memset(pw_str, 0, sizeof(pw_str));
1844 ext_password_free(pw);
1845 }
1846#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001847
1848 if (!psk_set) {
1849 wpa_msg(wpa_s, MSG_INFO,
1850 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001851 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001852 return -1;
1853 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001854#ifdef CONFIG_OWE
1855 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1856 /* OWE Diffie-Hellman exchange in (Re)Association
1857 * Request/Response frames set the PMK, so do not override it
1858 * here. */
1859#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001860 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1862
Hai Shalomfdcde762020-04-02 11:19:20 -07001863 if (ssid->mode != WPAS_MODE_IBSS &&
1864 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1865 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1866 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1867 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1868 wpa_msg(wpa_s, MSG_INFO,
1869 "Disable PTK0 rekey support - replaced with reconnect");
1870 wpa_s->deny_ptk0_rekey = 1;
1871 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1872 } else {
1873 wpa_s->deny_ptk0_rekey = 0;
1874 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1875 }
1876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 return 0;
1878}
1879
1880
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001881static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1882{
1883 *pos = 0x00;
1884
1885 switch (idx) {
1886 case 0: /* Bits 0-7 */
1887 break;
1888 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001889 if (wpa_s->conf->coloc_intf_reporting) {
1890 /* Bit 13 - Collocated Interference Reporting */
1891 *pos |= 0x20;
1892 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001893 break;
1894 case 2: /* Bits 16-23 */
1895#ifdef CONFIG_WNM
1896 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001897 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001898 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001899#endif /* CONFIG_WNM */
1900 break;
1901 case 3: /* Bits 24-31 */
1902#ifdef CONFIG_WNM
1903 *pos |= 0x02; /* Bit 25 - SSID List */
1904#endif /* CONFIG_WNM */
1905#ifdef CONFIG_INTERWORKING
1906 if (wpa_s->conf->interworking)
1907 *pos |= 0x80; /* Bit 31 - Interworking */
1908#endif /* CONFIG_INTERWORKING */
1909 break;
1910 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001911#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001912 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001913 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001914#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001915 break;
1916 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001917#ifdef CONFIG_HS20
1918 if (wpa_s->conf->hs20)
1919 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1920#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001921#ifdef CONFIG_MBO
1922 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1923#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001924 break;
1925 case 6: /* Bits 48-55 */
1926 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001927 case 7: /* Bits 56-63 */
1928 break;
1929 case 8: /* Bits 64-71 */
1930 if (wpa_s->conf->ftm_responder)
1931 *pos |= 0x40; /* Bit 70 - FTM responder */
1932 if (wpa_s->conf->ftm_initiator)
1933 *pos |= 0x80; /* Bit 71 - FTM initiator */
1934 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001935 case 9: /* Bits 72-79 */
1936#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001937 if (!wpa_s->disable_fils)
1938 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001939#endif /* CONFIG_FILS */
1940 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001941 case 10: /* Bits 80-87 */
1942 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
1943 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001944 }
1945}
1946
1947
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001948int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001949{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001950 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001951 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001952
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001953 if (len < wpa_s->extended_capa_len)
1954 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001955 if (buflen < (size_t) len + 2) {
1956 wpa_printf(MSG_INFO,
1957 "Not enough room for building extended capabilities element");
1958 return -1;
1959 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001960
1961 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001962 *pos++ = len;
1963 for (i = 0; i < len; i++, pos++) {
1964 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001965
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001966 if (i < wpa_s->extended_capa_len) {
1967 *pos &= ~wpa_s->extended_capa_mask[i];
1968 *pos |= wpa_s->extended_capa[i];
1969 }
1970 }
1971
1972 while (len > 0 && buf[1 + len] == 0) {
1973 len--;
1974 buf[1] = len;
1975 }
1976 if (len == 0)
1977 return 0;
1978
1979 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001980}
1981
1982
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001983static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1984 struct wpa_bss *test_bss)
1985{
1986 struct wpa_bss *bss;
1987
1988 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1989 if (bss == test_bss)
1990 return 1;
1991 }
1992
1993 return 0;
1994}
1995
1996
1997static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1998 struct wpa_ssid *test_ssid)
1999{
2000 struct wpa_ssid *ssid;
2001
2002 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2003 if (ssid == test_ssid)
2004 return 1;
2005 }
2006
2007 return 0;
2008}
2009
2010
2011int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2012 struct wpa_ssid *test_ssid)
2013{
2014 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2015 return 0;
2016
2017 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2018}
2019
2020
2021void wpas_connect_work_free(struct wpa_connect_work *cwork)
2022{
2023 if (cwork == NULL)
2024 return;
2025 os_free(cwork);
2026}
2027
2028
2029void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2030{
2031 struct wpa_connect_work *cwork;
2032 struct wpa_radio_work *work = wpa_s->connect_work;
2033
2034 if (!work)
2035 return;
2036
2037 wpa_s->connect_work = NULL;
2038 cwork = work->ctx;
2039 work->ctx = NULL;
2040 wpas_connect_work_free(cwork);
2041 radio_work_done(work);
2042}
2043
2044
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002045int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2046{
2047 struct os_reltime now;
2048 u8 addr[ETH_ALEN];
2049
2050 os_get_reltime(&now);
2051 if (wpa_s->last_mac_addr_style == style &&
2052 wpa_s->last_mac_addr_change.sec != 0 &&
2053 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2054 wpa_s->conf->rand_addr_lifetime)) {
2055 wpa_msg(wpa_s, MSG_DEBUG,
2056 "Previously selected random MAC address has not yet expired");
2057 return 0;
2058 }
2059
2060 switch (style) {
2061 case 1:
2062 if (random_mac_addr(addr) < 0)
2063 return -1;
2064 break;
2065 case 2:
2066 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2067 if (random_mac_addr_keep_oui(addr) < 0)
2068 return -1;
2069 break;
2070 default:
2071 return -1;
2072 }
2073
2074 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2075 wpa_msg(wpa_s, MSG_INFO,
2076 "Failed to set random MAC address");
2077 return -1;
2078 }
2079
2080 os_get_reltime(&wpa_s->last_mac_addr_change);
2081 wpa_s->mac_addr_changed = 1;
2082 wpa_s->last_mac_addr_style = style;
2083
2084 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2085 wpa_msg(wpa_s, MSG_INFO,
2086 "Could not update MAC address information");
2087 return -1;
2088 }
2089
2090 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2091 MAC2STR(addr));
2092
2093 return 0;
2094}
2095
2096
2097int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2098{
2099 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2100 !wpa_s->conf->preassoc_mac_addr)
2101 return 0;
2102
2103 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2104}
2105
2106
Hai Shalomc3565922019-10-28 11:58:20 -07002107static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2108{
2109#ifdef CONFIG_SAE
2110 int *groups = conf->sae_groups;
2111 int default_groups[] = { 19, 20, 21, 0 };
2112 const char *password;
2113
2114 if (!groups || groups[0] <= 0)
2115 groups = default_groups;
2116
2117 password = ssid->sae_password;
2118 if (!password)
2119 password = ssid->passphrase;
2120
Hai Shalom899fcc72020-10-19 14:38:18 -07002121 if (!password ||
2122 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2123 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002124 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002125 /* PT derivation not needed */
2126 sae_deinit_pt(ssid->pt);
2127 ssid->pt = NULL;
2128 return;
2129 }
2130
2131 if (ssid->pt)
2132 return; /* PT already derived */
2133 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2134 (const u8 *) password, os_strlen(password),
2135 ssid->sae_password_id);
2136#endif /* CONFIG_SAE */
2137}
2138
2139
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002140static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2141{
2142#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2143 os_free(wpa_s->sme.sae_rejected_groups);
2144 wpa_s->sme.sae_rejected_groups = NULL;
2145#ifdef CONFIG_TESTING_OPTIONS
2146 if (wpa_s->extra_sae_rejected_groups) {
2147 int i, *groups = wpa_s->extra_sae_rejected_groups;
2148
2149 for (i = 0; groups[i]; i++) {
2150 wpa_printf(MSG_DEBUG,
2151 "TESTING: Indicate rejection of an extra SAE group %d",
2152 groups[i]);
2153 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2154 groups[i]);
2155 }
2156 }
2157#endif /* CONFIG_TESTING_OPTIONS */
2158#endif /* CONFIG_SAE && CONFIG_SME */
2159}
2160
2161
Hai Shalom60840252021-02-19 19:02:11 -08002162int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2163{
2164 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2165 wpa_msg(wpa_s, MSG_INFO,
2166 "Could not restore permanent MAC address");
2167 return -1;
2168 }
2169 wpa_s->mac_addr_changed = 0;
2170 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2171 wpa_msg(wpa_s, MSG_INFO,
2172 "Could not update MAC address information");
2173 return -1;
2174 }
2175 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2176 return 0;
2177}
2178
2179
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002180static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182/**
2183 * wpa_supplicant_associate - Request association
2184 * @wpa_s: Pointer to wpa_supplicant data
2185 * @bss: Scan results for the selected BSS, or %NULL if not available
2186 * @ssid: Configuration data for the selected network
2187 *
2188 * This function is used to request %wpa_supplicant to associate with a BSS.
2189 */
2190void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2191 struct wpa_bss *bss, struct wpa_ssid *ssid)
2192{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002193 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002194 int rand_style;
2195
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002196 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002197 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002198
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002199 /*
2200 * If we are starting a new connection, any previously pending EAPOL
2201 * RX cannot be valid anymore.
2202 */
2203 wpabuf_free(wpa_s->pending_eapol_rx);
2204 wpa_s->pending_eapol_rx = NULL;
2205
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002206 if (ssid->mac_addr == -1)
2207 rand_style = wpa_s->conf->mac_addr;
2208 else
2209 rand_style = ssid->mac_addr;
2210
Hai Shalomfdcde762020-04-02 11:19:20 -07002211 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002212 wmm_ac_clear_saved_tspecs(wpa_s);
2213 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002214 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002215#ifdef CONFIG_TESTING_OPTIONS
2216 wpa_s->testing_resend_assoc = 0;
2217#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002218
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002219 if (wpa_s->last_ssid == ssid) {
2220 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002221 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002222 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2223 wmm_ac_save_tspecs(wpa_s);
2224 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002225 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2226 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002227 }
Hai Shalomc3565922019-10-28 11:58:20 -07002228 } else {
2229#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002230 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002231 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2232#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002233 }
2234
2235 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002236 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2237 return;
2238 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002239 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002240 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002241 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002242 }
2243 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244
2245#ifdef CONFIG_IBSS_RSN
2246 ibss_rsn_deinit(wpa_s->ibss_rsn);
2247 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002248#else /* CONFIG_IBSS_RSN */
2249 if (ssid->mode == WPAS_MODE_IBSS &&
2250 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2251 wpa_msg(wpa_s, MSG_INFO,
2252 "IBSS RSN not supported in the build");
2253 return;
2254 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255#endif /* CONFIG_IBSS_RSN */
2256
2257 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2258 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2259#ifdef CONFIG_AP
2260 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2261 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2262 "mode");
2263 return;
2264 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002265 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2266 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002267 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2268 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002269 return;
2270 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 wpa_s->current_bss = bss;
2272#else /* CONFIG_AP */
2273 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2274 "the build");
2275#endif /* CONFIG_AP */
2276 return;
2277 }
2278
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002279 if (ssid->mode == WPAS_MODE_MESH) {
2280#ifdef CONFIG_MESH
2281 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2282 wpa_msg(wpa_s, MSG_INFO,
2283 "Driver does not support mesh mode");
2284 return;
2285 }
2286 if (bss)
2287 ssid->frequency = bss->freq;
2288 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2289 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2290 return;
2291 }
2292 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002293#else /* CONFIG_MESH */
2294 wpa_msg(wpa_s, MSG_ERROR,
2295 "mesh mode support not included in the build");
2296#endif /* CONFIG_MESH */
2297 return;
2298 }
2299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002300 /*
2301 * Set WPA state machine configuration to match the selected network now
2302 * so that the information is available before wpas_start_assoc_cb()
2303 * gets called. This is needed at least for RSN pre-authentication where
2304 * candidate APs are added to a list based on scan result processing
2305 * before completion of the first association.
2306 */
2307 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2308
2309#ifdef CONFIG_DPP
2310 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2311 return;
2312#endif /* CONFIG_DPP */
2313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314#ifdef CONFIG_TDLS
2315 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002316 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002317#endif /* CONFIG_TDLS */
2318
Hai Shalomc3565922019-10-28 11:58:20 -07002319#ifdef CONFIG_MBO
2320 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2321#endif /* CONFIG_MBO */
2322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002323 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002324 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325 sme_authenticate(wpa_s, bss, ssid);
2326 return;
2327 }
2328
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002329 if (wpa_s->connect_work) {
2330 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2331 return;
2332 }
2333
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002334 if (radio_work_pending(wpa_s, "connect")) {
2335 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2336 return;
2337 }
2338
Dmitry Shmidt29333592017-01-09 12:27:11 -08002339#ifdef CONFIG_SME
2340 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2341 /* Clear possibly set auth_alg, if any, from last attempt. */
2342 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2343 }
2344#endif /* CONFIG_SME */
2345
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002346 wpas_abort_ongoing_scan(wpa_s);
2347
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002348 cwork = os_zalloc(sizeof(*cwork));
2349 if (cwork == NULL)
2350 return;
2351
2352 cwork->bss = bss;
2353 cwork->ssid = ssid;
2354
2355 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2356 wpas_start_assoc_cb, cwork) < 0) {
2357 os_free(cwork);
2358 }
2359}
2360
2361
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002362static int bss_is_ibss(struct wpa_bss *bss)
2363{
2364 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2365 IEEE80211_CAP_IBSS;
2366}
2367
2368
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002369static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2370 const struct wpa_ssid *ssid)
2371{
2372 enum hostapd_hw_mode hw_mode;
2373 struct hostapd_hw_modes *mode = NULL;
2374 u8 channel;
2375 int i;
2376
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002377 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2378 if (hw_mode == NUM_HOSTAPD_MODES)
2379 return 0;
2380 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2381 if (wpa_s->hw.modes[i].mode == hw_mode) {
2382 mode = &wpa_s->hw.modes[i];
2383 break;
2384 }
2385 }
2386
2387 if (!mode)
2388 return 0;
2389
2390 return mode->vht_capab != 0;
2391}
2392
2393
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002394void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2395 const struct wpa_ssid *ssid,
2396 struct hostapd_freq_params *freq)
2397{
Hai Shalom81f62d82019-07-22 12:10:00 -07002398 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002399 enum hostapd_hw_mode hw_mode;
2400 struct hostapd_hw_modes *mode = NULL;
2401 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2402 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002403 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002404 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2405 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002406 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002407 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002408 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002409 int chwidth, seg0, seg1;
2410 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002411 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002412
2413 freq->freq = ssid->frequency;
2414
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002415 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2416 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2417
2418 if (ssid->mode != WPAS_MODE_IBSS)
2419 break;
2420
2421 /* Don't adjust control freq in case of fixed_freq */
2422 if (ssid->fixed_freq)
2423 break;
2424
2425 if (!bss_is_ibss(bss))
2426 continue;
2427
2428 if (ssid->ssid_len == bss->ssid_len &&
2429 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2430 wpa_printf(MSG_DEBUG,
2431 "IBSS already found in scan results, adjust control freq: %d",
2432 bss->freq);
2433 freq->freq = bss->freq;
2434 obss_scan = 0;
2435 break;
2436 }
2437 }
2438
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002439 /* For IBSS check HT_IBSS flag */
2440 if (ssid->mode == WPAS_MODE_IBSS &&
2441 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2442 return;
2443
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002444 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2445 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2446 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2447 wpa_printf(MSG_DEBUG,
2448 "IBSS: WEP/TKIP detected, do not try to enable HT");
2449 return;
2450 }
2451
2452 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002453 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2454 if (wpa_s->hw.modes[i].mode == hw_mode) {
2455 mode = &wpa_s->hw.modes[i];
2456 break;
2457 }
2458 }
2459
2460 if (!mode)
2461 return;
2462
Hai Shalom60840252021-02-19 19:02:11 -08002463 freq->channel = channel;
2464
Hai Shalomc3565922019-10-28 11:58:20 -07002465 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2466 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002467
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002468#ifdef CONFIG_HT_OVERRIDES
2469 if (ssid->disable_ht) {
2470 freq->ht_enabled = 0;
2471 return;
2472 }
2473#endif /* CONFIG_HT_OVERRIDES */
2474
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002475 freq->ht_enabled = ht_supported(mode);
2476 if (!freq->ht_enabled)
2477 return;
2478
Hai Shalomc3565922019-10-28 11:58:20 -07002479 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2480 if (is_24ghz)
2481 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002482#ifdef CONFIG_HE_OVERRIDES
2483 if (is_24ghz && ssid->disable_he)
2484 freq->he_enabled = 0;
2485#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002486
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002487 /* Setup higher BW only for 5 GHz */
2488 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2489 return;
2490
2491 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2492 pri_chan = &mode->channels[chan_idx];
2493 if (pri_chan->chan == channel)
2494 break;
2495 pri_chan = NULL;
2496 }
2497 if (!pri_chan)
2498 return;
2499
2500 /* Check primary channel flags */
2501 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2502 return;
2503
Hai Shalom74f70d42019-02-11 14:42:39 -08002504 freq->channel = pri_chan->chan;
2505
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002506#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002507 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002508#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002509 if (ssid->disable_vht)
2510 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002511#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002512 goto skip_ht40;
2513 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002514#endif /* CONFIG_HT_OVERRIDES */
2515
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002516 /* Check/setup HT40+/HT40- */
2517 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2518 if (ht40plus[j] == channel) {
2519 ht40 = 1;
2520 break;
2521 }
2522 }
2523
2524 /* Find secondary channel */
2525 for (i = 0; i < mode->num_channels; i++) {
2526 sec_chan = &mode->channels[i];
2527 if (sec_chan->chan == channel + ht40 * 4)
2528 break;
2529 sec_chan = NULL;
2530 }
2531 if (!sec_chan)
2532 return;
2533
2534 /* Check secondary channel flags */
2535 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2536 return;
2537
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002538 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002539 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2540 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002541 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002542 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2543 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002544 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002545 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002546
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002547 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002548 struct wpa_scan_results *scan_res;
2549
2550 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2551 if (scan_res == NULL) {
2552 /* Back to HT20 */
2553 freq->sec_channel_offset = 0;
2554 return;
2555 }
2556
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002557 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002558 switch (res) {
2559 case 0:
2560 /* Back to HT20 */
2561 freq->sec_channel_offset = 0;
2562 break;
2563 case 1:
2564 /* Configuration allowed */
2565 break;
2566 case 2:
2567 /* Switch pri/sec channels */
2568 freq->freq = hw_get_freq(mode, sec_chan->chan);
2569 freq->sec_channel_offset = -freq->sec_channel_offset;
2570 freq->channel = sec_chan->chan;
2571 break;
2572 default:
2573 freq->sec_channel_offset = 0;
2574 break;
2575 }
2576
2577 wpa_scan_results_free(scan_res);
2578 }
2579
Hai Shalom74f70d42019-02-11 14:42:39 -08002580#ifdef CONFIG_HT_OVERRIDES
2581skip_ht40:
2582#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002583 wpa_printf(MSG_DEBUG,
2584 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2585 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002586
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002587 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002588 return;
2589
2590 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002591 if (ssid->mode == WPAS_MODE_IBSS &&
2592 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002593 return;
2594
2595 vht_freq = *freq;
2596
Paul Stewart092955c2017-02-06 09:13:09 -08002597#ifdef CONFIG_VHT_OVERRIDES
2598 if (ssid->disable_vht) {
2599 freq->vht_enabled = 0;
2600 return;
2601 }
2602#endif /* CONFIG_VHT_OVERRIDES */
2603
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002604 vht_freq.vht_enabled = vht_supported(mode);
2605 if (!vht_freq.vht_enabled)
2606 return;
2607
Hai Shalomfdcde762020-04-02 11:19:20 -07002608 /* Enable HE with VHT for 5 GHz */
2609 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002610
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002611 /* setup center_freq1, bandwidth */
2612 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2613 if (freq->channel >= vht80[j] &&
2614 freq->channel < vht80[j] + 16)
2615 break;
2616 }
2617
2618 if (j == ARRAY_SIZE(vht80))
2619 return;
2620
2621 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2622 struct hostapd_channel_data *chan;
2623
2624 chan = hw_get_channel_chan(mode, i, NULL);
2625 if (!chan)
2626 return;
2627
2628 /* Back to HT configuration if channel not usable */
2629 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2630 return;
2631 }
2632
Hai Shalom81f62d82019-07-22 12:10:00 -07002633 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002634 seg0 = vht80[j] + 6;
2635 seg1 = 0;
2636
Hai Shalom81f62d82019-07-22 12:10:00 -07002637 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002638 /* setup center_freq2, bandwidth */
2639 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2640 /* Only accept 80 MHz segments separated by a gap */
2641 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2642 continue;
2643 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2644 struct hostapd_channel_data *chan;
2645
2646 chan = hw_get_channel_chan(mode, i, NULL);
2647 if (!chan)
2648 continue;
2649
2650 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2651 HOSTAPD_CHAN_NO_IR |
2652 HOSTAPD_CHAN_RADAR))
2653 continue;
2654
2655 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002656 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002657 vht_caps |=
2658 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2659 seg1 = vht80[k] + 6;
2660 }
2661
Hai Shalom81f62d82019-07-22 12:10:00 -07002662 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002663 break;
2664 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002665 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002666 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002667 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002668 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2669 seg0 = 50;
2670 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002671 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002672 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2673 seg0 = 114;
2674 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002675 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2676 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002677 seg0 = vht80[j] + 2;
2678#ifdef CONFIG_HT_OVERRIDES
2679 if (ssid->disable_ht40)
2680 seg0 = 0;
2681#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002682 }
2683
Hai Shalomfdcde762020-04-02 11:19:20 -07002684#ifdef CONFIG_HE_OVERRIDES
2685 if (ssid->disable_he) {
2686 vht_freq.he_enabled = 0;
2687 freq->he_enabled = 0;
2688 }
2689#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002690 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002691 freq->channel, ssid->enable_edmg,
2692 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002693 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002694 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002695 chwidth, seg0, seg1, vht_caps,
2696 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002697 return;
2698
2699 *freq = vht_freq;
2700
2701 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2702 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002703}
2704
2705
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002706#ifdef CONFIG_FILS
2707static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2708 size_t ie_buf_len)
2709{
2710 struct fils_hlp_req *req;
2711 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2712 const u8 *pos;
2713 u8 *buf = ie_buf;
2714
2715 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2716 list) {
2717 rem_len = ie_buf_len - ie_len;
2718 pos = wpabuf_head(req->pkt);
2719 hdr_len = 1 + 2 * ETH_ALEN + 6;
2720 hlp_len = wpabuf_len(req->pkt);
2721
2722 if (rem_len < 2 + hdr_len + hlp_len) {
2723 wpa_printf(MSG_ERROR,
2724 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2725 (unsigned long) rem_len,
2726 (unsigned long) (2 + hdr_len + hlp_len));
2727 break;
2728 }
2729
2730 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2731 /* Element ID */
2732 *buf++ = WLAN_EID_EXTENSION;
2733 /* Length */
2734 *buf++ = len;
2735 /* Element ID Extension */
2736 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2737 /* Destination MAC address */
2738 os_memcpy(buf, req->dst, ETH_ALEN);
2739 buf += ETH_ALEN;
2740 /* Source MAC address */
2741 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2742 buf += ETH_ALEN;
2743 /* LLC/SNAP Header */
2744 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2745 buf += 6;
2746 /* HLP Packet */
2747 os_memcpy(buf, pos, len - hdr_len);
2748 buf += len - hdr_len;
2749 pos += len - hdr_len;
2750
2751 hlp_len -= len - hdr_len;
2752 ie_len += 2 + len;
2753 rem_len -= 2 + len;
2754
2755 while (hlp_len) {
2756 len = (hlp_len > 255) ? 255 : hlp_len;
2757 if (rem_len < 2 + len)
2758 break;
2759 *buf++ = WLAN_EID_FRAGMENT;
2760 *buf++ = len;
2761 os_memcpy(buf, pos, len);
2762 buf += len;
2763 pos += len;
2764
2765 hlp_len -= len;
2766 ie_len += 2 + len;
2767 rem_len -= 2 + len;
2768 }
2769 }
2770
2771 return ie_len;
2772}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002773
2774
2775int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2776{
2777 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2778 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2779 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2780 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2781}
2782
2783
2784int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2785{
2786#ifdef CONFIG_FILS_SK_PFS
2787 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2788 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2789#else /* CONFIG_FILS_SK_PFS */
2790 return 0;
2791#endif /* CONFIG_FILS_SK_PFS */
2792}
2793
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002794#endif /* CONFIG_FILS */
2795
2796
2797static u8 * wpas_populate_assoc_ies(
2798 struct wpa_supplicant *wpa_s,
2799 struct wpa_bss *bss, struct wpa_ssid *ssid,
2800 struct wpa_driver_associate_params *params,
2801 enum wpa_drv_update_connect_params_mask *mask)
2802{
2803 u8 *wpa_ie;
2804 size_t max_wpa_ie_len = 500;
2805 size_t wpa_ie_len;
2806 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002807#ifdef CONFIG_MBO
2808 const u8 *mbo_ie;
2809#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302810#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2811 int pmksa_cached = 0;
2812#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002813#ifdef CONFIG_FILS
2814 const u8 *realm, *username, *rrk;
2815 size_t realm_len, username_len, rrk_len;
2816 u16 next_seq_num;
2817 struct fils_hlp_req *req;
2818
2819 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2820 list) {
2821 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2822 2 + 2 * wpabuf_len(req->pkt) / 255;
2823 }
2824#endif /* CONFIG_FILS */
2825
2826 wpa_ie = os_malloc(max_wpa_ie_len);
2827 if (!wpa_ie) {
2828 wpa_printf(MSG_ERROR,
2829 "Failed to allocate connect IE buffer for %lu bytes",
2830 (unsigned long) max_wpa_ie_len);
2831 return NULL;
2832 }
2833
2834 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2835 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2836 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2837 int try_opportunistic;
2838 const u8 *cache_id = NULL;
2839
2840 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2841 wpa_s->conf->okc :
2842 ssid->proactive_key_caching) &&
2843 (ssid->proto & WPA_PROTO_RSN);
2844#ifdef CONFIG_FILS
2845 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2846 cache_id = wpa_bss_get_fils_cache_id(bss);
2847#endif /* CONFIG_FILS */
2848 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2849 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002850 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002851 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302852#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2853 pmksa_cached = 1;
2854#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002855 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002856 wpa_ie_len = max_wpa_ie_len;
2857 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2858 wpa_ie, &wpa_ie_len)) {
2859 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2860 "key management and encryption suites");
2861 os_free(wpa_ie);
2862 return NULL;
2863 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002864#ifdef CONFIG_HS20
2865 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2866 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2867 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2868 wpa_ie_len = max_wpa_ie_len;
2869 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2870 wpa_ie, &wpa_ie_len)) {
2871 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2872 "key management and encryption suites");
2873 os_free(wpa_ie);
2874 return NULL;
2875 }
2876#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2878 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2879 /*
2880 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2881 * use non-WPA since the scan results did not indicate that the
2882 * AP is using WPA or WPA2.
2883 */
2884 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2885 wpa_ie_len = 0;
2886 wpa_s->wpa_proto = 0;
2887 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2888 wpa_ie_len = max_wpa_ie_len;
2889 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2890 wpa_ie, &wpa_ie_len)) {
2891 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2892 "key management and encryption suites (no "
2893 "scan results)");
2894 os_free(wpa_ie);
2895 return NULL;
2896 }
2897#ifdef CONFIG_WPS
2898 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2899 struct wpabuf *wps_ie;
2900 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2901 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2902 wpa_ie_len = wpabuf_len(wps_ie);
2903 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2904 } else
2905 wpa_ie_len = 0;
2906 wpabuf_free(wps_ie);
2907 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2908 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2909 params->wps = WPS_MODE_PRIVACY;
2910 else
2911 params->wps = WPS_MODE_OPEN;
2912 wpa_s->wpa_proto = 0;
2913#endif /* CONFIG_WPS */
2914 } else {
2915 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2916 wpa_ie_len = 0;
2917 wpa_s->wpa_proto = 0;
2918 }
2919
2920#ifdef IEEE8021X_EAPOL
2921 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2922 if (ssid->leap) {
2923 if (ssid->non_leap == 0)
2924 algs = WPA_AUTH_ALG_LEAP;
2925 else
2926 algs |= WPA_AUTH_ALG_LEAP;
2927 }
2928 }
2929
2930#ifdef CONFIG_FILS
2931 /* Clear FILS association */
2932 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2933
2934 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2935 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2936 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2937 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002938 &next_seq_num, &rrk, &rrk_len) == 0 &&
2939 (!wpa_s->last_con_fail_realm ||
2940 wpa_s->last_con_fail_realm_len != realm_len ||
2941 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002942 algs = WPA_AUTH_ALG_FILS;
2943 params->fils_erp_username = username;
2944 params->fils_erp_username_len = username_len;
2945 params->fils_erp_realm = realm;
2946 params->fils_erp_realm_len = realm_len;
2947 params->fils_erp_next_seq_num = next_seq_num;
2948 params->fils_erp_rrk = rrk;
2949 params->fils_erp_rrk_len = rrk_len;
2950
2951 if (mask)
2952 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302953 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2954 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2955 pmksa_cached) {
2956 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002957 }
2958#endif /* CONFIG_FILS */
2959#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002960#ifdef CONFIG_SAE
2961 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2962 algs = WPA_AUTH_ALG_SAE;
2963#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002964
2965 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2966 if (ssid->auth_alg) {
2967 algs = ssid->auth_alg;
2968 wpa_dbg(wpa_s, MSG_DEBUG,
2969 "Overriding auth_alg selection: 0x%x", algs);
2970 }
2971
Hai Shalom5f92bc92019-04-18 11:54:11 -07002972#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302973 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002974 wpa_dbg(wpa_s, MSG_DEBUG,
2975 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2976 algs = WPA_AUTH_ALG_OPEN;
2977 }
2978#endif /* CONFIG_SAE */
2979
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002980#ifdef CONFIG_P2P
2981 if (wpa_s->global->p2p) {
2982 u8 *pos;
2983 size_t len;
2984 int res;
2985 pos = wpa_ie + wpa_ie_len;
2986 len = max_wpa_ie_len - wpa_ie_len;
2987 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2988 ssid->p2p_group);
2989 if (res >= 0)
2990 wpa_ie_len += res;
2991 }
2992
2993 wpa_s->cross_connect_disallowed = 0;
2994 if (bss) {
2995 struct wpabuf *p2p;
2996 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2997 if (p2p) {
2998 wpa_s->cross_connect_disallowed =
2999 p2p_get_cross_connect_disallowed(p2p);
3000 wpabuf_free(p2p);
3001 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3002 "connection",
3003 wpa_s->cross_connect_disallowed ?
3004 "disallows" : "allows");
3005 }
3006 }
3007
3008 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3009#endif /* CONFIG_P2P */
3010
3011 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003012 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003013 wpa_ie + wpa_ie_len,
3014 max_wpa_ie_len -
3015 wpa_ie_len);
3016 }
3017
3018 /*
3019 * Workaround: Add Extended Capabilities element only if the AP
3020 * included this element in Beacon/Probe Response frames. Some older
3021 * APs seem to have interoperability issues if this element is
3022 * included, so while the standard may require us to include the
3023 * element in all cases, it is justifiable to skip it to avoid
3024 * interoperability issues.
3025 */
3026 if (ssid->p2p_group)
3027 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3028 else
3029 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3030
3031 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3032 u8 ext_capab[18];
3033 int ext_capab_len;
3034 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3035 sizeof(ext_capab));
3036 if (ext_capab_len > 0 &&
3037 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3038 u8 *pos = wpa_ie;
3039 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3040 pos += 2 + pos[1];
3041 os_memmove(pos + ext_capab_len, pos,
3042 wpa_ie_len - (pos - wpa_ie));
3043 wpa_ie_len += ext_capab_len;
3044 os_memcpy(pos, ext_capab, ext_capab_len);
3045 }
3046 }
3047
3048#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003049 if (is_hs20_network(wpa_s, ssid, bss)
3050#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3051 && is_hs20_config(wpa_s)
3052#endif /* ANDROID */
3053 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003054 struct wpabuf *hs20;
3055
Roshan Pius3a1667e2018-07-03 15:17:14 -07003056 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003057 if (hs20) {
3058 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3059 size_t len;
3060
Hai Shalom74f70d42019-02-11 14:42:39 -08003061 wpas_hs20_add_indication(hs20, pps_mo_id,
3062 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003063 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003064 len = max_wpa_ie_len - wpa_ie_len;
3065 if (wpabuf_len(hs20) <= len) {
3066 os_memcpy(wpa_ie + wpa_ie_len,
3067 wpabuf_head(hs20), wpabuf_len(hs20));
3068 wpa_ie_len += wpabuf_len(hs20);
3069 }
3070 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003071 }
3072 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003073 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003074#endif /* CONFIG_HS20 */
3075
3076 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3077 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3078 size_t len;
3079
3080 len = max_wpa_ie_len - wpa_ie_len;
3081 if (wpabuf_len(buf) <= len) {
3082 os_memcpy(wpa_ie + wpa_ie_len,
3083 wpabuf_head(buf), wpabuf_len(buf));
3084 wpa_ie_len += wpabuf_len(buf);
3085 }
3086 }
3087
3088#ifdef CONFIG_FST
3089 if (wpa_s->fst_ies) {
3090 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3091
3092 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3093 os_memcpy(wpa_ie + wpa_ie_len,
3094 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3095 wpa_ie_len += fst_ies_len;
3096 }
3097 }
3098#endif /* CONFIG_FST */
3099
3100#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003101 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003102 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003103 int len;
3104
3105 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003106 max_wpa_ie_len - wpa_ie_len,
3107 !!mbo_attr_from_mbo_ie(mbo_ie,
3108 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003109 if (len >= 0)
3110 wpa_ie_len += len;
3111 }
3112#endif /* CONFIG_MBO */
3113
3114#ifdef CONFIG_FILS
3115 if (algs == WPA_AUTH_ALG_FILS) {
3116 size_t len;
3117
3118 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3119 max_wpa_ie_len - wpa_ie_len);
3120 wpa_ie_len += len;
3121 }
3122#endif /* CONFIG_FILS */
3123
3124#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003125#ifdef CONFIG_TESTING_OPTIONS
3126 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3127 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3128 } else
3129#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003130 if (algs == WPA_AUTH_ALG_OPEN &&
3131 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3132 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003133 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003134
Roshan Pius3a1667e2018-07-03 15:17:14 -07003135 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003137 } else if (wpa_s->assoc_status_code ==
3138 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003139 if (wpa_s->last_owe_group == 19)
3140 group = 20;
3141 else if (wpa_s->last_owe_group == 20)
3142 group = 21;
3143 else
3144 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003145 } else {
3146 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003147 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003148
Roshan Pius3a1667e2018-07-03 15:17:14 -07003149 wpa_s->last_owe_group = group;
3150 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003151 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3152 if (owe_ie &&
3153 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3154 os_memcpy(wpa_ie + wpa_ie_len,
3155 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3156 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003157 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003158 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003159 }
3160#endif /* CONFIG_OWE */
3161
Hai Shalom021b0b52019-04-10 11:17:58 -07003162#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003163 if (DPP_VERSION > 1 &&
3164 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003165 ssid->dpp_netaccesskey &&
3166 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003167 struct rsn_pmksa_cache_entry *pmksa;
3168
3169 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3170 if (!pmksa || !pmksa->dpp_pfs)
3171 goto pfs_fail;
3172
Hai Shalom021b0b52019-04-10 11:17:58 -07003173 dpp_pfs_free(wpa_s->dpp_pfs);
3174 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3175 ssid->dpp_netaccesskey_len);
3176 if (!wpa_s->dpp_pfs) {
3177 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3178 /* Try to continue without PFS */
3179 goto pfs_fail;
3180 }
3181 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3182 max_wpa_ie_len - wpa_ie_len) {
3183 os_memcpy(wpa_ie + wpa_ie_len,
3184 wpabuf_head(wpa_s->dpp_pfs->ie),
3185 wpabuf_len(wpa_s->dpp_pfs->ie));
3186 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3187 }
3188 }
3189pfs_fail:
3190#endif /* CONFIG_DPP2 */
3191
Roshan Pius3a1667e2018-07-03 15:17:14 -07003192#ifdef CONFIG_IEEE80211R
3193 /*
3194 * Add MDIE under these conditions: the network profile allows FT,
3195 * the AP supports FT, and the mobility domain ID matches.
3196 */
3197 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3198 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3199
3200 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3201 size_t len = 0;
3202 const u8 *md = mdie + 2;
3203 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3204
3205 if (os_memcmp(md, wpa_md,
3206 MOBILITY_DOMAIN_ID_LEN) == 0) {
3207 /* Add mobility domain IE */
3208 len = wpa_ft_add_mdie(
3209 wpa_s->wpa, wpa_ie + wpa_ie_len,
3210 max_wpa_ie_len - wpa_ie_len, mdie);
3211 wpa_ie_len += len;
3212 }
3213#ifdef CONFIG_SME
3214 if (len > 0 && wpa_s->sme.ft_used &&
3215 wpa_sm_has_ptk(wpa_s->wpa)) {
3216 wpa_dbg(wpa_s, MSG_DEBUG,
3217 "SME: Trying to use FT over-the-air");
3218 algs |= WPA_AUTH_ALG_FT;
3219 }
3220#endif /* CONFIG_SME */
3221 }
3222 }
3223#endif /* CONFIG_IEEE80211R */
3224
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003225#ifdef CONFIG_TESTING_OPTIONS
3226 if (wpa_s->rsnxe_override_assoc &&
3227 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3228 max_wpa_ie_len - wpa_ie_len) {
3229 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3230 os_memcpy(wpa_ie + wpa_ie_len,
3231 wpabuf_head(wpa_s->rsnxe_override_assoc),
3232 wpabuf_len(wpa_s->rsnxe_override_assoc));
3233 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3234 } else
3235#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003236 if (wpa_s->rsnxe_len > 0 &&
3237 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3238 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3239 wpa_ie_len += wpa_s->rsnxe_len;
3240 }
3241
Hai Shalom60840252021-02-19 19:02:11 -08003242 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3243 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003244 struct wpabuf *mscs_ie;
3245 size_t mscs_ie_len, buf_len;
3246
Hai Shalom899fcc72020-10-19 14:38:18 -07003247 buf_len = 3 + /* MSCS descriptor IE header */
3248 1 + /* Request type */
3249 2 + /* User priority control */
3250 4 + /* Stream timeout */
3251 3 + /* TCLAS Mask IE header */
3252 wpa_s->robust_av.frame_classifier_len;
3253 mscs_ie = wpabuf_alloc(buf_len);
3254 if (!mscs_ie) {
3255 wpa_printf(MSG_INFO,
3256 "MSCS: Failed to allocate MSCS IE");
3257 goto mscs_fail;
3258 }
3259
3260 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3261 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3262 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3263 mscs_ie_len = wpabuf_len(mscs_ie);
3264 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3265 mscs_ie_len);
3266 wpa_ie_len += mscs_ie_len;
3267 }
3268
3269 wpabuf_free(mscs_ie);
3270 }
3271mscs_fail:
3272
Hai Shalom74f70d42019-02-11 14:42:39 -08003273 if (ssid->multi_ap_backhaul_sta) {
3274 size_t multi_ap_ie_len;
3275
3276 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3277 max_wpa_ie_len - wpa_ie_len,
3278 MULTI_AP_BACKHAUL_STA);
3279 if (multi_ap_ie_len == 0) {
3280 wpa_printf(MSG_ERROR,
3281 "Multi-AP: Failed to build Multi-AP IE");
3282 os_free(wpa_ie);
3283 return NULL;
3284 }
3285 wpa_ie_len += multi_ap_ie_len;
3286 }
3287
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288 params->wpa_ie = wpa_ie;
3289 params->wpa_ie_len = wpa_ie_len;
3290 params->auth_alg = algs;
3291 if (mask)
3292 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3293
3294 return wpa_ie;
3295}
3296
3297
Hai Shalomc3565922019-10-28 11:58:20 -07003298#ifdef CONFIG_OWE
3299static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3300{
3301 struct wpa_driver_associate_params params;
3302 u8 *wpa_ie;
3303
3304 os_memset(&params, 0, sizeof(params));
3305 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3306 wpa_s->current_ssid, &params, NULL);
3307 if (!wpa_ie)
3308 return;
3309
3310 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3311 os_free(wpa_ie);
3312}
3313#endif /* CONFIG_OWE */
3314
3315
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003316#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3317static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3318{
3319 struct wpa_driver_associate_params params;
3320 enum wpa_drv_update_connect_params_mask mask = 0;
3321 u8 *wpa_ie;
3322
3323 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3324 return; /* nothing to do */
3325
3326 os_memset(&params, 0, sizeof(params));
3327 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3328 wpa_s->current_ssid, &params, &mask);
3329 if (!wpa_ie)
3330 return;
3331
3332 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3333 os_free(wpa_ie);
3334 return;
3335 }
3336
3337 wpa_s->auth_alg = params.auth_alg;
3338 wpa_drv_update_connect_params(wpa_s, &params, mask);
3339 os_free(wpa_ie);
3340}
3341#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3342
3343
Hai Shalomc3565922019-10-28 11:58:20 -07003344static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3345{
3346 if (!edmg_ie || edmg_ie[1] < 6)
3347 return 0;
3348 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3349}
3350
3351
3352static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3353{
3354 if (!edmg_ie || edmg_ie[1] < 6)
3355 return 0;
3356 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3357}
3358
3359
3360/* Returns the intersection of two EDMG configurations.
3361 * Note: The current implementation is limited to CB2 only (CB1 included),
3362 * i.e., the implementation supports up to 2 contiguous channels.
3363 * For supporting non-contiguous (aggregated) channels and for supporting
3364 * CB3 and above, this function will need to be extended.
3365 */
3366static struct ieee80211_edmg_config
3367get_edmg_intersection(struct ieee80211_edmg_config a,
3368 struct ieee80211_edmg_config b,
3369 u8 primary_channel)
3370{
3371 struct ieee80211_edmg_config result;
3372 int i, contiguous = 0;
3373 int max_contiguous = 0;
3374
3375 result.channels = b.channels & a.channels;
3376 if (!result.channels) {
3377 wpa_printf(MSG_DEBUG,
3378 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3379 a.channels, b.channels);
3380 goto fail;
3381 }
3382
3383 if (!(result.channels & BIT(primary_channel - 1))) {
3384 wpa_printf(MSG_DEBUG,
3385 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3386 primary_channel, result.channels);
3387 goto fail;
3388 }
3389
3390 /* Find max contiguous channels */
3391 for (i = 0; i < 6; i++) {
3392 if (result.channels & BIT(i))
3393 contiguous++;
3394 else
3395 contiguous = 0;
3396
3397 if (contiguous > max_contiguous)
3398 max_contiguous = contiguous;
3399 }
3400
3401 /* Assuming AP and STA supports ONLY contiguous channels,
3402 * bw configuration can have value between 4-7.
3403 */
3404 if ((b.bw_config < a.bw_config))
3405 result.bw_config = b.bw_config;
3406 else
3407 result.bw_config = a.bw_config;
3408
3409 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3410 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3411 wpa_printf(MSG_DEBUG,
3412 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3413 max_contiguous);
3414 goto fail;
3415 }
3416
3417 return result;
3418
3419fail:
3420 result.channels = 0;
3421 result.bw_config = 0;
3422 return result;
3423}
3424
3425
3426static struct ieee80211_edmg_config
3427get_supported_edmg(struct wpa_supplicant *wpa_s,
3428 struct hostapd_freq_params *freq,
3429 struct ieee80211_edmg_config request_edmg)
3430{
3431 enum hostapd_hw_mode hw_mode;
3432 struct hostapd_hw_modes *mode = NULL;
3433 u8 primary_channel;
3434
3435 if (!wpa_s->hw.modes)
3436 goto fail;
3437
3438 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3439 if (hw_mode == NUM_HOSTAPD_MODES)
3440 goto fail;
3441
Hai Shalom60840252021-02-19 19:02:11 -08003442 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003443 if (!mode)
3444 goto fail;
3445
3446 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3447
3448fail:
3449 request_edmg.channels = 0;
3450 request_edmg.bw_config = 0;
3451 return request_edmg;
3452}
3453
3454
Hai Shalom021b0b52019-04-10 11:17:58 -07003455#ifdef CONFIG_MBO
3456void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3457{
3458 struct wpa_driver_associate_params params;
3459 u8 *wpa_ie;
3460
3461 /*
3462 * Update MBO connect params only in case of change of MBO attributes
3463 * when connected, if the AP support MBO.
3464 */
3465
3466 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3467 !wpa_s->current_bss ||
3468 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3469 return;
3470
3471 os_memset(&params, 0, sizeof(params));
3472 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3473 wpa_s->current_ssid, &params, NULL);
3474 if (!wpa_ie)
3475 return;
3476
3477 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3478 os_free(wpa_ie);
3479}
3480#endif /* CONFIG_MBO */
3481
3482
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003483static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3484{
3485 struct wpa_connect_work *cwork = work->ctx;
3486 struct wpa_bss *bss = cwork->bss;
3487 struct wpa_ssid *ssid = cwork->ssid;
3488 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003489 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003490 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003491 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003492 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003493 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003494#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003495 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003496#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003497 int assoc_failed = 0;
3498 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003499 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003500#ifdef CONFIG_HT_OVERRIDES
3501 struct ieee80211_ht_capabilities htcaps;
3502 struct ieee80211_ht_capabilities htcaps_mask;
3503#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003504#ifdef CONFIG_VHT_OVERRIDES
3505 struct ieee80211_vht_capabilities vhtcaps;
3506 struct ieee80211_vht_capabilities vhtcaps_mask;
3507#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003508
3509 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003510 if (work->started) {
3511 wpa_s->connect_work = NULL;
3512
3513 /* cancel possible auth. timeout */
3514 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3515 NULL);
3516 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003517 wpas_connect_work_free(cwork);
3518 return;
3519 }
3520
3521 wpa_s->connect_work = work;
3522
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003523 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3524 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003525 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3526 wpas_connect_work_done(wpa_s);
3527 return;
3528 }
3529
Dmitry Shmidte4663042016-04-04 10:07:49 -07003530 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003531 os_memset(&params, 0, sizeof(params));
3532 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003533 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003534
3535 /* Starting new association, so clear the possibly used WPA IE from the
3536 * previous association. */
3537 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3538 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3539 wpa_s->rsnxe_len = 0;
3540 wpa_s->mscs_setup_done = false;
3541
3542 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3543 if (!wpa_ie) {
3544 wpas_connect_work_done(wpa_s);
3545 return;
3546 }
3547
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003548 if (bss &&
3549 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003550#ifdef CONFIG_IEEE80211R
3551 const u8 *ie, *md = NULL;
3552#endif /* CONFIG_IEEE80211R */
3553 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3554 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3555 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3556 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3557 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3558 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3559 if (bssid_changed)
3560 wpas_notify_bssid_changed(wpa_s);
3561#ifdef CONFIG_IEEE80211R
3562 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3563 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3564 md = ie + 2;
3565 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3566 if (md) {
3567 /* Prepare for the next transition */
3568 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3569 }
3570#endif /* CONFIG_IEEE80211R */
3571#ifdef CONFIG_WPS
3572 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3573 wpa_s->conf->ap_scan == 2 &&
3574 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3575 /* Use ap_scan==1 style network selection to find the network
3576 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003577 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003578 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003579 wpa_s->reassociate = 1;
3580 wpa_supplicant_req_scan(wpa_s, 0, 0);
3581 return;
3582#endif /* CONFIG_WPS */
3583 } else {
3584 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3585 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003586 if (bss)
3587 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3588 else
3589 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003591 if (!wpa_s->pno)
3592 wpa_supplicant_cancel_sched_scan(wpa_s);
3593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 wpa_supplicant_cancel_scan(wpa_s);
3595
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3597 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003598 cipher_pairwise = wpa_s->pairwise_cipher;
3599 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003600 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003601 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3602 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3603 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3604 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003605#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003606 if (wpa_set_wep_keys(wpa_s, ssid)) {
3607 use_crypt = 1;
3608 wep_keys_set = 1;
3609 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003610#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 }
3612 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3613 use_crypt = 0;
3614
3615#ifdef IEEE8021X_EAPOL
3616 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3617 if ((ssid->eapol_flags &
3618 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3619 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3620 !wep_keys_set) {
3621 use_crypt = 0;
3622 } else {
3623 /* Assume that dynamic WEP-104 keys will be used and
3624 * set cipher suites in order for drivers to expect
3625 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003626 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627 }
3628 }
3629#endif /* IEEE8021X_EAPOL */
3630
3631 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3632 /* Set the key before (and later after) association */
3633 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3634 }
3635
3636 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3637 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 params.ssid = bss->ssid;
3639 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003640 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3641 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003642 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3643 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003644 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003645 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003646 ssid->bssid_set,
3647 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003648 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003649 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003650 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003651 params.bssid_hint = bss->bssid;
3652 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003653 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003655 if (ssid->bssid_hint_set)
3656 params.bssid_hint = ssid->bssid_hint;
3657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003658 params.ssid = ssid->ssid;
3659 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003660 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003661 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003662
3663 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3664 wpa_s->conf->ap_scan == 2) {
3665 params.bssid = ssid->bssid;
3666 params.fixed_bssid = 1;
3667 }
3668
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003669 /* Initial frequency for IBSS/mesh */
3670 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003671 ssid->frequency > 0 && params.freq.freq == 0)
3672 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003673
3674 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003675 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003676 if (ssid->beacon_int)
3677 params.beacon_int = ssid->beacon_int;
3678 else
3679 params.beacon_int = wpa_s->conf->beacon_int;
3680 }
3681
Hai Shalomc3565922019-10-28 11:58:20 -07003682 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003683 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3684 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003685 else
3686 edmg_ie_oper = NULL;
3687
3688 if (edmg_ie_oper) {
3689 params.freq.edmg.channels =
3690 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3691 params.freq.edmg.bw_config =
3692 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3693 wpa_printf(MSG_DEBUG,
3694 "AP supports EDMG channels 0x%x, bw_config %d",
3695 params.freq.edmg.channels,
3696 params.freq.edmg.bw_config);
3697
3698 /* User may ask for specific EDMG channel for EDMG connection
3699 * (must be supported by AP)
3700 */
3701 if (ssid->edmg_channel) {
3702 struct ieee80211_edmg_config configured_edmg;
3703 enum hostapd_hw_mode hw_mode;
3704 u8 primary_channel;
3705
3706 hw_mode = ieee80211_freq_to_chan(bss->freq,
3707 &primary_channel);
3708 if (hw_mode == NUM_HOSTAPD_MODES)
3709 goto edmg_fail;
3710
3711 hostapd_encode_edmg_chan(ssid->enable_edmg,
3712 ssid->edmg_channel,
3713 primary_channel,
3714 &configured_edmg);
3715
3716 if (ieee802_edmg_is_allowed(params.freq.edmg,
3717 configured_edmg)) {
3718 params.freq.edmg = configured_edmg;
3719 wpa_printf(MSG_DEBUG,
3720 "Use EDMG channel %d for connection",
3721 ssid->edmg_channel);
3722 } else {
3723 edmg_fail:
3724 params.freq.edmg.channels = 0;
3725 params.freq.edmg.bw_config = 0;
3726 wpa_printf(MSG_WARNING,
3727 "EDMG channel %d not supported by AP, fallback to DMG",
3728 ssid->edmg_channel);
3729 }
3730 }
3731
3732 if (params.freq.edmg.channels) {
3733 wpa_printf(MSG_DEBUG,
3734 "EDMG before: channels 0x%x, bw_config %d",
3735 params.freq.edmg.channels,
3736 params.freq.edmg.bw_config);
3737 params.freq.edmg = get_supported_edmg(wpa_s,
3738 &params.freq,
3739 params.freq.edmg);
3740 wpa_printf(MSG_DEBUG,
3741 "EDMG after: channels 0x%x, bw_config %d",
3742 params.freq.edmg.channels,
3743 params.freq.edmg.bw_config);
3744 }
3745 }
3746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 params.pairwise_suite = cipher_pairwise;
3748 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003749 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003750 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003751 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003752 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003754 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003755#ifdef CONFIG_WEP
3756 {
3757 int i;
3758
3759 for (i = 0; i < NUM_WEP_KEYS; i++) {
3760 if (ssid->wep_key_len[i])
3761 params.wep_key[i] = ssid->wep_key[i];
3762 params.wep_key_len[i] = ssid->wep_key_len[i];
3763 }
3764 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003766#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767
Hai Shalom74f70d42019-02-11 14:42:39 -08003768 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003769 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3770 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003771 params.passphrase = ssid->passphrase;
3772 if (ssid->psk_set)
3773 params.psk = ssid->psk;
3774 }
3775
Hai Shalom74f70d42019-02-11 14:42:39 -08003776 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3777 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3778 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3779 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3780 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003781 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003782
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003783 if (wpa_s->conf->key_mgmt_offload) {
3784 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3785 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003786 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3787 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003788 params.req_key_mgmt_offload =
3789 ssid->proactive_key_caching < 0 ?
3790 wpa_s->conf->okc : ssid->proactive_key_caching;
3791 else
3792 params.req_key_mgmt_offload = 1;
3793
3794 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3795 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3796 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3797 ssid->psk_set)
3798 params.psk = ssid->psk;
3799 }
3800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 params.drop_unencrypted = use_crypt;
3802
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003803 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003804 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3806 struct wpa_ie_data ie;
3807 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3808 ie.capabilities &
3809 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3810 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3811 "MFP: require MFP");
3812 params.mgmt_frame_protection =
3813 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003814#ifdef CONFIG_OWE
3815 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3816 !ssid->owe_only) {
3817 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3818#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819 }
3820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003822 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003824 if (wpa_s->p2pdev->set_sta_uapsd)
3825 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003826 else
3827 params.uapsd = -1;
3828
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003829#ifdef CONFIG_HT_OVERRIDES
3830 os_memset(&htcaps, 0, sizeof(htcaps));
3831 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3832 params.htcaps = (u8 *) &htcaps;
3833 params.htcaps_mask = (u8 *) &htcaps_mask;
3834 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3835#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003836#ifdef CONFIG_VHT_OVERRIDES
3837 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3838 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3839 params.vhtcaps = &vhtcaps;
3840 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003841 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003842#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003843#ifdef CONFIG_HE_OVERRIDES
3844 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3845#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003846
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003847#ifdef CONFIG_P2P
3848 /*
3849 * If multi-channel concurrency is not supported, check for any
3850 * frequency conflict. In case of any frequency conflict, remove the
3851 * least prioritized connection.
3852 */
3853 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003854 int freq, num;
3855 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003856 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003857 wpa_printf(MSG_DEBUG,
3858 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003859 freq, params.freq.freq);
3860 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003861 wpa_s, params.freq.freq, ssid) < 0) {
3862 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003863 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003864 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003865 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003866 }
3867 }
3868#endif /* CONFIG_P2P */
3869
Dmitry Shmidte4663042016-04-04 10:07:49 -07003870 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3871 wpa_s->current_ssid)
3872 params.prev_bssid = prev_bssid;
3873
Hai Shalom60840252021-02-19 19:02:11 -08003874#ifdef CONFIG_SAE
3875 params.sae_pwe = wpa_s->conf->sae_pwe;
3876#endif /* CONFIG_SAE */
3877
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003878 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003879 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003880 if (ret < 0) {
3881 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3882 "failed");
3883 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3884 /*
3885 * The driver is known to mean what is saying, so we
3886 * can stop right here; the association will not
3887 * succeed.
3888 */
3889 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08003890 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08003891 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003892 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003893 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3894 return;
3895 }
3896 /* try to continue anyway; new association will be tried again
3897 * after timeout */
3898 assoc_failed = 1;
3899 }
3900
3901 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3902 /* Set the key after the association just in case association
3903 * cleared the previously configured key. */
3904 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3905 /* No need to timeout authentication since there is no key
3906 * management. */
3907 wpa_supplicant_cancel_auth_timeout(wpa_s);
3908 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3909#ifdef CONFIG_IBSS_RSN
3910 } else if (ssid->mode == WPAS_MODE_IBSS &&
3911 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3912 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3913 /*
3914 * RSN IBSS authentication is per-STA and we can disable the
3915 * per-BSSID authentication.
3916 */
3917 wpa_supplicant_cancel_auth_timeout(wpa_s);
3918#endif /* CONFIG_IBSS_RSN */
3919 } else {
3920 /* Timeout for IEEE 802.11 authentication and association */
3921 int timeout = 60;
3922
3923 if (assoc_failed) {
3924 /* give IBSS a bit more time */
3925 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3926 } else if (wpa_s->conf->ap_scan == 1) {
3927 /* give IBSS a bit more time */
3928 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3929 }
3930 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3931 }
3932
Hai Shalomfdcde762020-04-02 11:19:20 -07003933#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003934 if (wep_keys_set &&
3935 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003936 /* Set static WEP keys again */
3937 wpa_set_wep_keys(wpa_s, ssid);
3938 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003939#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940
3941 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3942 /*
3943 * Do not allow EAP session resumption between different
3944 * network configurations.
3945 */
3946 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3947 }
3948 old_ssid = wpa_s->current_ssid;
3949 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003950
3951 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003952 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003953#ifdef CONFIG_HS20
3954 hs20_configure_frame_filters(wpa_s);
3955#endif /* CONFIG_HS20 */
3956 }
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3959 wpa_supplicant_initiate_eapol(wpa_s);
3960 if (old_ssid != wpa_s->current_ssid)
3961 wpas_notify_network_changed(wpa_s);
3962}
3963
3964
3965static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3966 const u8 *addr)
3967{
3968 struct wpa_ssid *old_ssid;
3969
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003970 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003971 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003973 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974 wpa_sm_set_config(wpa_s->wpa, NULL);
3975 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3976 if (old_ssid != wpa_s->current_ssid)
3977 wpas_notify_network_changed(wpa_s);
3978 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3979}
3980
3981
3982/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3984 * @wpa_s: Pointer to wpa_supplicant data
3985 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3986 *
3987 * This function is used to request %wpa_supplicant to deauthenticate from the
3988 * current AP.
3989 */
3990void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003991 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992{
3993 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003994 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003995 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003997 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003998 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003999 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004000 reason_code, reason2str(reason_code),
4001 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004002
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004003 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4004 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4005 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004006 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004007 else if (!is_zero_ether_addr(wpa_s->bssid))
4008 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004009 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4010 /*
4011 * When using driver-based BSS selection, we may not know the
4012 * BSSID with which we are currently trying to associate. We
4013 * need to notify the driver of this disconnection even in such
4014 * a case, so use the all zeros address here.
4015 */
4016 addr = wpa_s->bssid;
4017 zero_addr = 1;
4018 }
4019
Hai Shalom74f70d42019-02-11 14:42:39 -08004020 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4021 wpa_s->enabled_4addr_mode = 0;
4022
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004023#ifdef CONFIG_TDLS
4024 wpa_tdls_teardown_peers(wpa_s->wpa);
4025#endif /* CONFIG_TDLS */
4026
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004027#ifdef CONFIG_MESH
4028 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004029 struct mesh_conf *mconf;
4030
4031 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004032 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4033 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004034 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4035 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004036 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004037 }
4038#endif /* CONFIG_MESH */
4039
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004040 if (addr) {
4041 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004042 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004043 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004044 event.deauth_info.locally_generated = 1;
4045 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004046 if (zero_addr)
4047 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004048 }
4049
4050 wpa_supplicant_clear_connection(wpa_s, addr);
4051}
4052
Hai Shalomfdcde762020-04-02 11:19:20 -07004053
4054void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4055{
4056 wpa_s->own_reconnect_req = 1;
4057 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4058
4059}
4060
4061
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004062static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4063 struct wpa_ssid *ssid)
4064{
4065 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4066 return;
4067
4068 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004069 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004070 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4071 wpas_notify_network_enabled_changed(wpa_s, ssid);
4072
4073 /*
4074 * Try to reassociate since there is no current configuration and a new
4075 * network was made available.
4076 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004077 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004078 wpa_s->reassociate = 1;
4079}
4080
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004081
Roshan Pius950bec92016-07-19 09:49:24 -07004082/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004083 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004084 * @wpa_s: wpa_supplicant structure for a network interface
4085 * Returns: The new network configuration or %NULL if operation failed
4086 *
4087 * This function performs the following operations:
4088 * 1. Adds a new network.
4089 * 2. Send network addition notification.
4090 * 3. Marks the network disabled.
4091 * 4. Set network default parameters.
4092 */
4093struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4094{
4095 struct wpa_ssid *ssid;
4096
4097 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004098 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004099 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004100 wpas_notify_network_added(wpa_s, ssid);
4101 ssid->disabled = 1;
4102 wpa_config_set_network_defaults(ssid);
4103
4104 return ssid;
4105}
4106
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004107
Roshan Pius950bec92016-07-19 09:49:24 -07004108/**
4109 * wpa_supplicant_remove_network - Remove a configured network based on id
4110 * @wpa_s: wpa_supplicant structure for a network interface
4111 * @id: Unique network id to search for
4112 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4113 * could not be removed
4114 *
4115 * This function performs the following operations:
4116 * 1. Removes the network.
4117 * 2. Send network removal notification.
4118 * 3. Update internal state machines.
4119 * 4. Stop any running sched scans.
4120 */
4121int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4122{
4123 struct wpa_ssid *ssid;
4124 int was_disabled;
4125
4126 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004127 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004128 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004129 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004130
4131 if (wpa_s->last_ssid == ssid)
4132 wpa_s->last_ssid = NULL;
4133
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004134 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004135#ifdef CONFIG_SME
4136 wpa_s->sme.prev_bssid_set = 0;
4137#endif /* CONFIG_SME */
4138 /*
4139 * Invalidate the EAP session cache if the current or
4140 * previously used network is removed.
4141 */
4142 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4143 }
4144
4145 if (ssid == wpa_s->current_ssid) {
4146 wpa_sm_set_config(wpa_s->wpa, NULL);
4147 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4148
4149 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4150 wpa_s->own_disconnect_req = 1;
4151 wpa_supplicant_deauthenticate(wpa_s,
4152 WLAN_REASON_DEAUTH_LEAVING);
4153 }
4154
4155 was_disabled = ssid->disabled;
4156
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004157 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004158 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004159
4160 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004161 wpa_printf(MSG_DEBUG,
4162 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004163 wpa_supplicant_cancel_sched_scan(wpa_s);
4164 wpa_supplicant_req_scan(wpa_s, 0, 0);
4165 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004166
Roshan Pius950bec92016-07-19 09:49:24 -07004167 return 0;
4168}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004169
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004172 * wpa_supplicant_remove_all_networks - Remove all configured networks
4173 * @wpa_s: wpa_supplicant structure for a network interface
4174 * Returns: 0 on success (errors are currently ignored)
4175 *
4176 * This function performs the following operations:
4177 * 1. Remove all networks.
4178 * 2. Send network removal notifications.
4179 * 3. Update internal state machines.
4180 * 4. Stop any running sched scans.
4181 */
4182int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4183{
4184 struct wpa_ssid *ssid;
4185
4186 if (wpa_s->sched_scanning)
4187 wpa_supplicant_cancel_sched_scan(wpa_s);
4188
4189 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4190 if (wpa_s->current_ssid) {
4191#ifdef CONFIG_SME
4192 wpa_s->sme.prev_bssid_set = 0;
4193#endif /* CONFIG_SME */
4194 wpa_sm_set_config(wpa_s->wpa, NULL);
4195 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4196 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4197 wpa_s->own_disconnect_req = 1;
4198 wpa_supplicant_deauthenticate(
4199 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4200 }
4201 ssid = wpa_s->conf->ssid;
4202 while (ssid) {
4203 struct wpa_ssid *remove_ssid = ssid;
4204 int id;
4205
4206 id = ssid->id;
4207 ssid = ssid->next;
4208 if (wpa_s->last_ssid == remove_ssid)
4209 wpa_s->last_ssid = NULL;
4210 wpas_notify_network_removed(wpa_s, remove_ssid);
4211 wpa_config_remove_network(wpa_s->conf, id);
4212 }
4213 return 0;
4214}
4215
4216
4217/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004218 * wpa_supplicant_enable_network - Mark a configured network as enabled
4219 * @wpa_s: wpa_supplicant structure for a network interface
4220 * @ssid: wpa_ssid structure for a configured network or %NULL
4221 *
4222 * Enables the specified network or all networks if no network specified.
4223 */
4224void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4225 struct wpa_ssid *ssid)
4226{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004227 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004228 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4229 wpa_supplicant_enable_one_network(wpa_s, ssid);
4230 } else
4231 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004232
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004233 if (wpa_s->reassociate && !wpa_s->disconnected &&
4234 (!wpa_s->current_ssid ||
4235 wpa_s->wpa_state == WPA_DISCONNECTED ||
4236 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004237 if (wpa_s->sched_scanning) {
4238 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4239 "new network to scan filters");
4240 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241 }
4242
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004243 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4244 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004245 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004246 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004247 }
4248}
4249
4250
4251/**
4252 * wpa_supplicant_disable_network - Mark a configured network as disabled
4253 * @wpa_s: wpa_supplicant structure for a network interface
4254 * @ssid: wpa_ssid structure for a configured network or %NULL
4255 *
4256 * Disables the specified network or all networks if no network specified.
4257 */
4258void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4259 struct wpa_ssid *ssid)
4260{
4261 struct wpa_ssid *other_ssid;
4262 int was_disabled;
4263
4264 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004265 if (wpa_s->sched_scanning)
4266 wpa_supplicant_cancel_sched_scan(wpa_s);
4267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004268 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4269 other_ssid = other_ssid->next) {
4270 was_disabled = other_ssid->disabled;
4271 if (was_disabled == 2)
4272 continue; /* do not change persistent P2P group
4273 * data */
4274
4275 other_ssid->disabled = 1;
4276
4277 if (was_disabled != other_ssid->disabled)
4278 wpas_notify_network_enabled_changed(
4279 wpa_s, other_ssid);
4280 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004281 if (wpa_s->current_ssid) {
4282 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4283 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004284 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004286 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004288 if (ssid == wpa_s->current_ssid) {
4289 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4290 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004291 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004293 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004294
4295 was_disabled = ssid->disabled;
4296
4297 ssid->disabled = 1;
4298
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004299 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004301 if (wpa_s->sched_scanning) {
4302 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4303 "to remove network from filters");
4304 wpa_supplicant_cancel_sched_scan(wpa_s);
4305 wpa_supplicant_req_scan(wpa_s, 0, 0);
4306 }
4307 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004308 }
4309}
4310
4311
4312/**
4313 * wpa_supplicant_select_network - Attempt association with a network
4314 * @wpa_s: wpa_supplicant structure for a network interface
4315 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4316 */
4317void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4318 struct wpa_ssid *ssid)
4319{
4320
4321 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004322 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004324 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004325 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4326 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004327 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004328 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004329 disconnected = 1;
4330 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004331
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004332 if (ssid)
4333 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004335 /*
4336 * Mark all other networks disabled or mark all networks enabled if no
4337 * network specified.
4338 */
4339 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4340 other_ssid = other_ssid->next) {
4341 int was_disabled = other_ssid->disabled;
4342 if (was_disabled == 2)
4343 continue; /* do not change persistent P2P group data */
4344
4345 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004346 if (was_disabled && !other_ssid->disabled)
4347 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348
4349 if (was_disabled != other_ssid->disabled)
4350 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4351 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004352
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004353 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4354 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004355 /* We are already associated with the selected network */
4356 wpa_printf(MSG_DEBUG, "Already associated with the "
4357 "selected network - do nothing");
4358 return;
4359 }
4360
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004361 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004362 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004363 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004364 wpa_s->connect_without_scan =
4365 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004366
4367 /*
4368 * Don't optimize next scan freqs since a new ESS has been
4369 * selected.
4370 */
4371 os_free(wpa_s->next_scan_freqs);
4372 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004373 } else {
4374 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004375 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004376
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004377 wpa_s->disconnected = 0;
4378 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004379 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004380 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004381 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004382 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004383 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4384 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004385
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004386 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004387 wpa_supplicant_fast_associate(wpa_s) != 1) {
4388 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004389 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004390 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004391 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392
4393 if (ssid)
4394 wpas_notify_network_selected(wpa_s, ssid);
4395}
4396
4397
4398/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004399 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4400 * @wpa_s: wpa_supplicant structure for a network interface
4401 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4402 * @pkcs11_module_path: PKCS #11 module path or NULL
4403 * Returns: 0 on success; -1 on failure
4404 *
4405 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4406 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4407 * module path fails the paths will be reset to the default value (NULL).
4408 */
4409int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4410 const char *pkcs11_engine_path,
4411 const char *pkcs11_module_path)
4412{
4413 char *pkcs11_engine_path_copy = NULL;
4414 char *pkcs11_module_path_copy = NULL;
4415
4416 if (pkcs11_engine_path != NULL) {
4417 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4418 if (pkcs11_engine_path_copy == NULL)
4419 return -1;
4420 }
4421 if (pkcs11_module_path != NULL) {
4422 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004423 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004424 os_free(pkcs11_engine_path_copy);
4425 return -1;
4426 }
4427 }
4428
4429 os_free(wpa_s->conf->pkcs11_engine_path);
4430 os_free(wpa_s->conf->pkcs11_module_path);
4431 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4432 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4433
4434 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4435 eapol_sm_deinit(wpa_s->eapol);
4436 wpa_s->eapol = NULL;
4437 if (wpa_supplicant_init_eapol(wpa_s)) {
4438 /* Error -> Reset paths to the default value (NULL) once. */
4439 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4440 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4441 NULL);
4442
4443 return -1;
4444 }
4445 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4446
4447 return 0;
4448}
4449
4450
4451/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4453 * @wpa_s: wpa_supplicant structure for a network interface
4454 * @ap_scan: AP scan mode
4455 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4456 *
4457 */
4458int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4459{
4460
4461 int old_ap_scan;
4462
4463 if (ap_scan < 0 || ap_scan > 2)
4464 return -1;
4465
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004466 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4467 wpa_printf(MSG_INFO,
4468 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4469 }
4470
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004471#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004472 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4473 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4474 wpa_s->wpa_state < WPA_COMPLETED) {
4475 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4476 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004477 return 0;
4478 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004479#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004481 old_ap_scan = wpa_s->conf->ap_scan;
4482 wpa_s->conf->ap_scan = ap_scan;
4483
4484 if (old_ap_scan != wpa_s->conf->ap_scan)
4485 wpas_notify_ap_scan_changed(wpa_s);
4486
4487 return 0;
4488}
4489
4490
4491/**
4492 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4493 * @wpa_s: wpa_supplicant structure for a network interface
4494 * @expire_age: Expiration age in seconds
4495 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4496 *
4497 */
4498int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4499 unsigned int bss_expire_age)
4500{
4501 if (bss_expire_age < 10) {
4502 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4503 bss_expire_age);
4504 return -1;
4505 }
4506 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4507 bss_expire_age);
4508 wpa_s->conf->bss_expiration_age = bss_expire_age;
4509
4510 return 0;
4511}
4512
4513
4514/**
4515 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4516 * @wpa_s: wpa_supplicant structure for a network interface
4517 * @expire_count: number of scans after which an unseen BSS is reclaimed
4518 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4519 *
4520 */
4521int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4522 unsigned int bss_expire_count)
4523{
4524 if (bss_expire_count < 1) {
4525 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4526 bss_expire_count);
4527 return -1;
4528 }
4529 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4530 bss_expire_count);
4531 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4532
4533 return 0;
4534}
4535
4536
4537/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004538 * wpa_supplicant_set_scan_interval - Set scan interval
4539 * @wpa_s: wpa_supplicant structure for a network interface
4540 * @scan_interval: scan interval in seconds
4541 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4542 *
4543 */
4544int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4545 int scan_interval)
4546{
4547 if (scan_interval < 0) {
4548 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4549 scan_interval);
4550 return -1;
4551 }
4552 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4553 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004554 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004555
4556 return 0;
4557}
4558
4559
4560/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004561 * wpa_supplicant_set_debug_params - Set global debug params
4562 * @global: wpa_global structure
4563 * @debug_level: debug level
4564 * @debug_timestamp: determines if show timestamp in debug data
4565 * @debug_show_keys: determines if show keys in debug data
4566 * Returns: 0 if succeed or -1 if debug_level has wrong value
4567 */
4568int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4569 int debug_timestamp, int debug_show_keys)
4570{
4571
4572 int old_level, old_timestamp, old_show_keys;
4573
4574 /* check for allowed debuglevels */
4575 if (debug_level != MSG_EXCESSIVE &&
4576 debug_level != MSG_MSGDUMP &&
4577 debug_level != MSG_DEBUG &&
4578 debug_level != MSG_INFO &&
4579 debug_level != MSG_WARNING &&
4580 debug_level != MSG_ERROR)
4581 return -1;
4582
4583 old_level = wpa_debug_level;
4584 old_timestamp = wpa_debug_timestamp;
4585 old_show_keys = wpa_debug_show_keys;
4586
4587 wpa_debug_level = debug_level;
4588 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4589 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4590
4591 if (wpa_debug_level != old_level)
4592 wpas_notify_debug_level_changed(global);
4593 if (wpa_debug_timestamp != old_timestamp)
4594 wpas_notify_debug_timestamp_changed(global);
4595 if (wpa_debug_show_keys != old_show_keys)
4596 wpas_notify_debug_show_keys_changed(global);
4597
4598 return 0;
4599}
4600
4601
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004602#ifdef CONFIG_OWE
4603static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4604 const u8 *entry_ssid, size_t entry_ssid_len)
4605{
4606 const u8 *owe, *pos, *end;
4607 u8 ssid_len;
4608 struct wpa_bss *bss;
4609
4610 /* Check network profile SSID aganst the SSID in the
4611 * OWE Transition Mode element. */
4612
4613 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4614 if (!bss)
4615 return 0;
4616
4617 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4618 if (!owe)
4619 return 0;
4620
4621 pos = owe + 6;
4622 end = owe + 2 + owe[1];
4623
4624 if (end - pos < ETH_ALEN + 1)
4625 return 0;
4626 pos += ETH_ALEN;
4627 ssid_len = *pos++;
4628 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4629 return 0;
4630
4631 return entry_ssid_len == ssid_len &&
4632 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4633}
4634#endif /* CONFIG_OWE */
4635
4636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637/**
4638 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4639 * @wpa_s: Pointer to wpa_supplicant data
4640 * Returns: A pointer to the current network structure or %NULL on failure
4641 */
4642struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4643{
4644 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004645 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004646 int res;
4647 size_t ssid_len;
4648 u8 bssid[ETH_ALEN];
4649 int wired;
4650
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004651 res = wpa_drv_get_ssid(wpa_s, ssid);
4652 if (res < 0) {
4653 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4654 "driver");
4655 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004656 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004657 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004658
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004659 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004660 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4661 "driver");
4662 return NULL;
4663 }
4664
4665 wired = wpa_s->conf->ap_scan == 0 &&
4666 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4667
4668 entry = wpa_s->conf->ssid;
4669 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004670 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004671 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004672 (!entry->ssid ||
4673 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4674 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004675 (!entry->bssid_set ||
4676 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4677 return entry;
4678#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004679 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004680 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4681 (entry->ssid == NULL || entry->ssid_len == 0) &&
4682 (!entry->bssid_set ||
4683 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4684 return entry;
4685#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004686
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004687#ifdef CONFIG_OWE
4688 if (!wpas_network_disabled(wpa_s, entry) &&
4689 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4690 entry->ssid_len) &&
4691 (!entry->bssid_set ||
4692 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4693 return entry;
4694#endif /* CONFIG_OWE */
4695
Dmitry Shmidt04949592012-07-19 12:16:46 -07004696 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004697 entry->ssid_len == 0 &&
4698 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4699 return entry;
4700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004701 entry = entry->next;
4702 }
4703
4704 return NULL;
4705}
4706
4707
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004708static int select_driver(struct wpa_supplicant *wpa_s, int i)
4709{
4710 struct wpa_global *global = wpa_s->global;
4711
4712 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004713 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004714 if (global->drv_priv[i] == NULL) {
4715 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4716 "'%s'", wpa_drivers[i]->name);
4717 return -1;
4718 }
4719 }
4720
4721 wpa_s->driver = wpa_drivers[i];
4722 wpa_s->global_drv_priv = global->drv_priv[i];
4723
4724 return 0;
4725}
4726
4727
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004728static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4729 const char *name)
4730{
4731 int i;
4732 size_t len;
4733 const char *pos, *driver = name;
4734
4735 if (wpa_s == NULL)
4736 return -1;
4737
4738 if (wpa_drivers[0] == NULL) {
4739 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4740 "wpa_supplicant");
4741 return -1;
4742 }
4743
4744 if (name == NULL) {
4745 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004746 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747 }
4748
4749 do {
4750 pos = os_strchr(driver, ',');
4751 if (pos)
4752 len = pos - driver;
4753 else
4754 len = os_strlen(driver);
4755
4756 for (i = 0; wpa_drivers[i]; i++) {
4757 if (os_strlen(wpa_drivers[i]->name) == len &&
4758 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004759 0) {
4760 /* First driver that succeeds wins */
4761 if (select_driver(wpa_s, i) == 0)
4762 return 0;
4763 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004764 }
4765
4766 driver = pos + 1;
4767 } while (pos);
4768
4769 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4770 return -1;
4771}
4772
4773
4774/**
4775 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4776 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4777 * with struct wpa_driver_ops::init()
4778 * @src_addr: Source address of the EAPOL frame
4779 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4780 * @len: Length of the EAPOL data
4781 *
4782 * This function is called for each received EAPOL frame. Most driver
4783 * interfaces rely on more generic OS mechanism for receiving frames through
4784 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4785 * take care of received EAPOL frames and deliver them to the core supplicant
4786 * code by calling this function.
4787 */
4788void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4789 const u8 *buf, size_t len)
4790{
4791 struct wpa_supplicant *wpa_s = ctx;
4792
4793 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4794 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4795
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004796#ifdef CONFIG_TESTING_OPTIONS
4797 if (wpa_s->ignore_auth_resp) {
4798 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4799 return;
4800 }
4801#endif /* CONFIG_TESTING_OPTIONS */
4802
Jouni Malinena05074c2012-12-21 21:35:35 +02004803 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4804 (wpa_s->last_eapol_matches_bssid &&
4805#ifdef CONFIG_AP
4806 !wpa_s->ap_iface &&
4807#endif /* CONFIG_AP */
4808 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 /*
4810 * There is possible race condition between receiving the
4811 * association event and the EAPOL frame since they are coming
4812 * through different paths from the driver. In order to avoid
4813 * issues in trying to process the EAPOL frame before receiving
4814 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004815 * the association event is received. This may also be needed in
4816 * driver-based roaming case, so also use src_addr != BSSID as a
4817 * trigger if we have previously confirmed that the
4818 * Authenticator uses BSSID as the src_addr (which is not the
4819 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004820 */
4821 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004822 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4823 wpa_supplicant_state_txt(wpa_s->wpa_state),
4824 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004825 wpabuf_free(wpa_s->pending_eapol_rx);
4826 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4827 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004828 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004829 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4830 ETH_ALEN);
4831 }
4832 return;
4833 }
4834
Jouni Malinena05074c2012-12-21 21:35:35 +02004835 wpa_s->last_eapol_matches_bssid =
4836 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4837
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004838#ifdef CONFIG_AP
4839 if (wpa_s->ap_iface) {
4840 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4841 return;
4842 }
4843#endif /* CONFIG_AP */
4844
4845 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4846 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4847 "no key management is configured");
4848 return;
4849 }
4850
4851 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004852 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004853 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4854 wpa_s->wpa_state != WPA_COMPLETED) &&
4855 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004856 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004857 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004858 int timeout = 10;
4859
4860 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4861 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4862 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4863 /* Use longer timeout for IEEE 802.1X/EAP */
4864 timeout = 70;
4865 }
4866
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004867#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004868 if (wpa_s->current_ssid && wpa_s->current_bss &&
4869 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4870 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4871 /*
4872 * Use shorter timeout if going through WPS AP iteration
4873 * for PIN config method with an AP that does not
4874 * advertise Selected Registrar.
4875 */
4876 struct wpabuf *wps_ie;
4877
4878 wps_ie = wpa_bss_get_vendor_ie_multi(
4879 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4880 if (wps_ie &&
4881 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4882 timeout = 10;
4883 wpabuf_free(wps_ie);
4884 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004885#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004886
4887 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004888 }
4889 wpa_s->eapol_received++;
4890
4891 if (wpa_s->countermeasures) {
4892 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4893 "EAPOL packet");
4894 return;
4895 }
4896
4897#ifdef CONFIG_IBSS_RSN
4898 if (wpa_s->current_ssid &&
4899 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4900 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4901 return;
4902 }
4903#endif /* CONFIG_IBSS_RSN */
4904
4905 /* Source address of the incoming EAPOL frame could be compared to the
4906 * current BSSID. However, it is possible that a centralized
4907 * Authenticator could be using another MAC address than the BSSID of
4908 * an AP, so just allow any address to be used for now. The replies are
4909 * still sent to the current BSSID (if available), though. */
4910
4911 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4912 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004913 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4914 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004915 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4916 return;
4917 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004918 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4920 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4921 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004922 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923 * handshake processing which would normally set portValid. We
4924 * need this to allow the EAPOL state machines to be completed
4925 * without going through EAPOL-Key handshake.
4926 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004927 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004928 }
4929}
4930
4931
Hai Shalomb755a2a2020-04-23 21:49:02 -07004932static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4933{
4934 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4935 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4936}
4937
4938
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004939int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004940{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004941 if ((!wpa_s->p2p_mgmt ||
4942 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4943 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004944 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4946 wpa_drv_get_mac_addr(wpa_s),
4947 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004948 wpas_eapol_needs_l2_packet(wpa_s) ?
4949 wpa_supplicant_rx_eapol : NULL,
4950 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004951 if (wpa_s->l2 == NULL)
4952 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004953
4954 if (l2_packet_set_packet_filter(wpa_s->l2,
4955 L2_PACKET_FILTER_PKTTYPE))
4956 wpa_dbg(wpa_s, MSG_DEBUG,
4957 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004958
4959 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4960 wpa_msg(wpa_s, MSG_ERROR,
4961 "Failed to get own L2 address");
4962 return -1;
4963 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004964 } else {
4965 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4966 if (addr)
4967 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4968 }
4969
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004970 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004971 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004972
Hai Shalomc3565922019-10-28 11:58:20 -07004973#ifdef CONFIG_FST
4974 if (wpa_s->fst)
4975 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4976#endif /* CONFIG_FST */
4977
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004978 return 0;
4979}
4980
4981
Dmitry Shmidt04949592012-07-19 12:16:46 -07004982static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4983 const u8 *buf, size_t len)
4984{
4985 struct wpa_supplicant *wpa_s = ctx;
4986 const struct l2_ethhdr *eth;
4987
4988 if (len < sizeof(*eth))
4989 return;
4990 eth = (const struct l2_ethhdr *) buf;
4991
4992 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4993 !(eth->h_dest[0] & 0x01)) {
4994 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4995 " (bridge - not for this interface - ignore)",
4996 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4997 return;
4998 }
4999
5000 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5001 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5002 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
5003 len - sizeof(*eth));
5004}
5005
5006
Hai Shalom899fcc72020-10-19 14:38:18 -07005007int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5008 const char *bridge_ifname)
5009{
5010 if (wpa_s->wpa_state > WPA_SCANNING)
5011 return -EBUSY;
5012
5013 if (bridge_ifname &&
5014 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5015 return -EINVAL;
5016
5017 if (!bridge_ifname)
5018 bridge_ifname = "";
5019
5020 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5021 return 0;
5022
5023 if (wpa_s->l2_br) {
5024 l2_packet_deinit(wpa_s->l2_br);
5025 wpa_s->l2_br = NULL;
5026 }
5027
5028 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5029 sizeof(wpa_s->bridge_ifname));
5030
5031 if (wpa_s->bridge_ifname[0]) {
5032 wpa_dbg(wpa_s, MSG_DEBUG,
5033 "Receiving packets from bridge interface '%s'",
5034 wpa_s->bridge_ifname);
5035 wpa_s->l2_br = l2_packet_init_bridge(
5036 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5037 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5038 if (!wpa_s->l2_br) {
5039 wpa_msg(wpa_s, MSG_ERROR,
5040 "Failed to open l2_packet connection for the bridge interface '%s'",
5041 wpa_s->bridge_ifname);
5042 goto fail;
5043 }
5044 }
5045
5046#ifdef CONFIG_TDLS
5047 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5048 goto fail;
5049#endif /* CONFIG_TDLS */
5050
5051 return 0;
5052fail:
5053 wpa_s->bridge_ifname[0] = 0;
5054 if (wpa_s->l2_br) {
5055 l2_packet_deinit(wpa_s->l2_br);
5056 wpa_s->l2_br = NULL;
5057 }
5058#ifdef CONFIG_TDLS
5059 if (!wpa_s->p2p_mgmt)
5060 wpa_tdls_init(wpa_s->wpa);
5061#endif /* CONFIG_TDLS */
5062 return -EIO;
5063}
5064
5065
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005066/**
5067 * wpa_supplicant_driver_init - Initialize driver interface parameters
5068 * @wpa_s: Pointer to wpa_supplicant data
5069 * Returns: 0 on success, -1 on failure
5070 *
5071 * This function is called to initialize driver interface parameters.
5072 * wpa_drv_init() must have been called before this function to initialize the
5073 * driver interface.
5074 */
5075int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5076{
5077 static int interface_count = 0;
5078
5079 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5080 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005082 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5083 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005084 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005085 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5086
Hai Shalomb755a2a2020-04-23 21:49:02 -07005087 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005088 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5089 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005090 wpa_s->l2_br = l2_packet_init_bridge(
5091 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5092 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005093 if (wpa_s->l2_br == NULL) {
5094 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5095 "connection for the bridge interface '%s'",
5096 wpa_s->bridge_ifname);
5097 return -1;
5098 }
5099 }
5100
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005101 if (wpa_s->conf->ap_scan == 2 &&
5102 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5103 wpa_printf(MSG_INFO,
5104 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5105 }
5106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107 wpa_clear_keys(wpa_s, NULL);
5108
5109 /* Make sure that TKIP countermeasures are not left enabled (could
5110 * happen if wpa_supplicant is killed during countermeasures. */
5111 wpa_drv_set_countermeasures(wpa_s, 0);
5112
5113 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5114 wpa_drv_flush_pmkid(wpa_s);
5115
5116 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005117 wpa_s->prev_scan_wildcard = 0;
5118
Dmitry Shmidt04949592012-07-19 12:16:46 -07005119 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005120 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5121 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5122 interface_count = 0;
5123 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005124#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005125 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005126 wpa_supplicant_delayed_sched_scan(wpa_s,
5127 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005128 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005129 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005130 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005131#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005132 interface_count++;
5133 } else
5134 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5135
5136 return 0;
5137}
5138
5139
5140static int wpa_supplicant_daemon(const char *pid_file)
5141{
5142 wpa_printf(MSG_DEBUG, "Daemonize..");
5143 return os_daemonize(pid_file);
5144}
5145
5146
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005147static struct wpa_supplicant *
5148wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005149{
5150 struct wpa_supplicant *wpa_s;
5151
5152 wpa_s = os_zalloc(sizeof(*wpa_s));
5153 if (wpa_s == NULL)
5154 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005155 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005156 wpa_s->scan_interval = 5;
5157 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005158 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005159 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005160 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005161 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005162
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005163 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005164 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005165#ifdef CONFIG_TESTING_OPTIONS
5166 dl_list_init(&wpa_s->drv_signal_override);
5167#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169 return wpa_s;
5170}
5171
5172
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005173#ifdef CONFIG_HT_OVERRIDES
5174
5175static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5176 struct ieee80211_ht_capabilities *htcaps,
5177 struct ieee80211_ht_capabilities *htcaps_mask,
5178 const char *ht_mcs)
5179{
5180 /* parse ht_mcs into hex array */
5181 int i;
5182 const char *tmp = ht_mcs;
5183 char *end = NULL;
5184
5185 /* If ht_mcs is null, do not set anything */
5186 if (!ht_mcs)
5187 return 0;
5188
5189 /* This is what we are setting in the kernel */
5190 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5191
5192 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5193
5194 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005195 long v;
5196
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005197 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005198 v = strtol(tmp, &end, 16);
5199
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005200 if (errno == 0) {
5201 wpa_msg(wpa_s, MSG_DEBUG,
5202 "htcap value[%i]: %ld end: %p tmp: %p",
5203 i, v, end, tmp);
5204 if (end == tmp)
5205 break;
5206
5207 htcaps->supported_mcs_set[i] = v;
5208 tmp = end;
5209 } else {
5210 wpa_msg(wpa_s, MSG_ERROR,
5211 "Failed to parse ht-mcs: %s, error: %s\n",
5212 ht_mcs, strerror(errno));
5213 return -1;
5214 }
5215 }
5216
5217 /*
5218 * If we were able to parse any values, then set mask for the MCS set.
5219 */
5220 if (i) {
5221 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5222 IEEE80211_HT_MCS_MASK_LEN - 1);
5223 /* skip the 3 reserved bits */
5224 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5225 0x1f;
5226 }
5227
5228 return 0;
5229}
5230
5231
5232static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5233 struct ieee80211_ht_capabilities *htcaps,
5234 struct ieee80211_ht_capabilities *htcaps_mask,
5235 int disabled)
5236{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005237 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005238
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005239 if (disabled == -1)
5240 return 0;
5241
Hai Shalom74f70d42019-02-11 14:42:39 -08005242 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5243
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005244 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5245 htcaps_mask->ht_capabilities_info |= msk;
5246 if (disabled)
5247 htcaps->ht_capabilities_info &= msk;
5248 else
5249 htcaps->ht_capabilities_info |= msk;
5250
5251 return 0;
5252}
5253
5254
5255static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5256 struct ieee80211_ht_capabilities *htcaps,
5257 struct ieee80211_ht_capabilities *htcaps_mask,
5258 int factor)
5259{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005260 if (factor == -1)
5261 return 0;
5262
Hai Shalom74f70d42019-02-11 14:42:39 -08005263 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5264
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005265 if (factor < 0 || factor > 3) {
5266 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5267 "Must be 0-3 or -1", factor);
5268 return -EINVAL;
5269 }
5270
5271 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5272 htcaps->a_mpdu_params &= ~0x3;
5273 htcaps->a_mpdu_params |= factor & 0x3;
5274
5275 return 0;
5276}
5277
5278
5279static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5280 struct ieee80211_ht_capabilities *htcaps,
5281 struct ieee80211_ht_capabilities *htcaps_mask,
5282 int density)
5283{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005284 if (density == -1)
5285 return 0;
5286
Hai Shalom74f70d42019-02-11 14:42:39 -08005287 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5288
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005289 if (density < 0 || density > 7) {
5290 wpa_msg(wpa_s, MSG_ERROR,
5291 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5292 density);
5293 return -EINVAL;
5294 }
5295
5296 htcaps_mask->a_mpdu_params |= 0x1C;
5297 htcaps->a_mpdu_params &= ~(0x1C);
5298 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5299
5300 return 0;
5301}
5302
5303
5304static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5305 struct ieee80211_ht_capabilities *htcaps,
5306 struct ieee80211_ht_capabilities *htcaps_mask,
5307 int disabled)
5308{
Hai Shalom74f70d42019-02-11 14:42:39 -08005309 if (disabled)
5310 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005311
Paul Stewart092955c2017-02-06 09:13:09 -08005312 set_disable_ht40(htcaps, disabled);
5313 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005314
5315 return 0;
5316}
5317
5318
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005319static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5320 struct ieee80211_ht_capabilities *htcaps,
5321 struct ieee80211_ht_capabilities *htcaps_mask,
5322 int disabled)
5323{
5324 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005325 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5326 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005327
Hai Shalom74f70d42019-02-11 14:42:39 -08005328 if (disabled)
5329 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005330
5331 if (disabled)
5332 htcaps->ht_capabilities_info &= ~msk;
5333 else
5334 htcaps->ht_capabilities_info |= msk;
5335
5336 htcaps_mask->ht_capabilities_info |= msk;
5337
5338 return 0;
5339}
5340
5341
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005342static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5343 struct ieee80211_ht_capabilities *htcaps,
5344 struct ieee80211_ht_capabilities *htcaps_mask,
5345 int disabled)
5346{
5347 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005348 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005349
Hai Shalom74f70d42019-02-11 14:42:39 -08005350 if (disabled)
5351 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005352
5353 if (disabled)
5354 htcaps->ht_capabilities_info &= ~msk;
5355 else
5356 htcaps->ht_capabilities_info |= msk;
5357
5358 htcaps_mask->ht_capabilities_info |= msk;
5359
5360 return 0;
5361}
5362
5363
Hai Shalom74f70d42019-02-11 14:42:39 -08005364static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5365 struct ieee80211_ht_capabilities *htcaps,
5366 struct ieee80211_ht_capabilities *htcaps_mask,
5367 int tx_stbc)
5368{
5369 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5370
5371 if (tx_stbc == -1)
5372 return 0;
5373
5374 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5375
5376 if (tx_stbc < 0 || tx_stbc > 1) {
5377 wpa_msg(wpa_s, MSG_ERROR,
5378 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5379 return -EINVAL;
5380 }
5381
5382 htcaps_mask->ht_capabilities_info |= msk;
5383 htcaps->ht_capabilities_info &= ~msk;
5384 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5385
5386 return 0;
5387}
5388
5389
5390static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5391 struct ieee80211_ht_capabilities *htcaps,
5392 struct ieee80211_ht_capabilities *htcaps_mask,
5393 int rx_stbc)
5394{
5395 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5396
5397 if (rx_stbc == -1)
5398 return 0;
5399
5400 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5401
5402 if (rx_stbc < 0 || rx_stbc > 3) {
5403 wpa_msg(wpa_s, MSG_ERROR,
5404 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5405 return -EINVAL;
5406 }
5407
5408 htcaps_mask->ht_capabilities_info |= msk;
5409 htcaps->ht_capabilities_info &= ~msk;
5410 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5411
5412 return 0;
5413}
5414
5415
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005416void wpa_supplicant_apply_ht_overrides(
5417 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5418 struct wpa_driver_associate_params *params)
5419{
5420 struct ieee80211_ht_capabilities *htcaps;
5421 struct ieee80211_ht_capabilities *htcaps_mask;
5422
5423 if (!ssid)
5424 return;
5425
5426 params->disable_ht = ssid->disable_ht;
5427 if (!params->htcaps || !params->htcaps_mask)
5428 return;
5429
5430 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5431 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5432 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5433 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5434 ssid->disable_max_amsdu);
5435 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5436 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5437 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005438 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005439 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005440 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5441 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005442
5443 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005444 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005445 htcaps->ht_capabilities_info |= bit;
5446 htcaps_mask->ht_capabilities_info |= bit;
5447 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005448}
5449
5450#endif /* CONFIG_HT_OVERRIDES */
5451
5452
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005453#ifdef CONFIG_VHT_OVERRIDES
5454void wpa_supplicant_apply_vht_overrides(
5455 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5456 struct wpa_driver_associate_params *params)
5457{
5458 struct ieee80211_vht_capabilities *vhtcaps;
5459 struct ieee80211_vht_capabilities *vhtcaps_mask;
5460
5461 if (!ssid)
5462 return;
5463
5464 params->disable_vht = ssid->disable_vht;
5465
5466 vhtcaps = (void *) params->vhtcaps;
5467 vhtcaps_mask = (void *) params->vhtcaps_mask;
5468
5469 if (!vhtcaps || !vhtcaps_mask)
5470 return;
5471
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005472 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5473 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005474
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005475#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005476 if (ssid->disable_sgi) {
5477 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5478 VHT_CAP_SHORT_GI_160);
5479 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5480 VHT_CAP_SHORT_GI_160);
5481 wpa_msg(wpa_s, MSG_DEBUG,
5482 "disable-sgi override specified, vht-caps: 0x%x",
5483 vhtcaps->vht_capabilities_info);
5484 }
5485
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005486 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005487 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5488 int max_ampdu;
5489
5490 max_ampdu = (ssid->vht_capa &
5491 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5492 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005493
5494 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5495 wpa_set_ampdu_factor(wpa_s,
5496 (void *) params->htcaps,
5497 (void *) params->htcaps_mask,
5498 max_ampdu);
5499 }
5500#endif /* CONFIG_HT_OVERRIDES */
5501
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005502#define OVERRIDE_MCS(i) \
5503 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5504 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005505 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005506 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005507 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5508 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005509 } \
5510 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5511 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005512 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005513 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005514 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5515 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005516 }
5517
5518 OVERRIDE_MCS(1);
5519 OVERRIDE_MCS(2);
5520 OVERRIDE_MCS(3);
5521 OVERRIDE_MCS(4);
5522 OVERRIDE_MCS(5);
5523 OVERRIDE_MCS(6);
5524 OVERRIDE_MCS(7);
5525 OVERRIDE_MCS(8);
5526}
5527#endif /* CONFIG_VHT_OVERRIDES */
5528
5529
Hai Shalomfdcde762020-04-02 11:19:20 -07005530#ifdef CONFIG_HE_OVERRIDES
5531void wpa_supplicant_apply_he_overrides(
5532 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5533 struct wpa_driver_associate_params *params)
5534{
5535 if (!ssid)
5536 return;
5537
5538 params->disable_he = ssid->disable_he;
5539}
5540#endif /* CONFIG_HE_OVERRIDES */
5541
5542
Dmitry Shmidt04949592012-07-19 12:16:46 -07005543static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5544{
5545#ifdef PCSC_FUNCS
5546 size_t len;
5547
5548 if (!wpa_s->conf->pcsc_reader)
5549 return 0;
5550
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005551 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005552 if (!wpa_s->scard)
5553 return 1;
5554
5555 if (wpa_s->conf->pcsc_pin &&
5556 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5557 scard_deinit(wpa_s->scard);
5558 wpa_s->scard = NULL;
5559 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5560 return -1;
5561 }
5562
5563 len = sizeof(wpa_s->imsi) - 1;
5564 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5565 scard_deinit(wpa_s->scard);
5566 wpa_s->scard = NULL;
5567 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5568 return -1;
5569 }
5570 wpa_s->imsi[len] = '\0';
5571
5572 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5573
5574 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5575 wpa_s->imsi, wpa_s->mnc_len);
5576
5577 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5578 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5579#endif /* PCSC_FUNCS */
5580
5581 return 0;
5582}
5583
5584
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005585int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5586{
5587 char *val, *pos;
5588
5589 ext_password_deinit(wpa_s->ext_pw);
5590 wpa_s->ext_pw = NULL;
5591 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5592
5593 if (!wpa_s->conf->ext_password_backend)
5594 return 0;
5595
5596 val = os_strdup(wpa_s->conf->ext_password_backend);
5597 if (val == NULL)
5598 return -1;
5599 pos = os_strchr(val, ':');
5600 if (pos)
5601 *pos++ = '\0';
5602
5603 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5604
5605 wpa_s->ext_pw = ext_password_init(val, pos);
5606 os_free(val);
5607 if (wpa_s->ext_pw == NULL) {
5608 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5609 return -1;
5610 }
5611 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5612
5613 return 0;
5614}
5615
5616
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005617#ifdef CONFIG_FST
5618
5619static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5620{
5621 struct wpa_supplicant *wpa_s = ctx;
5622
5623 return (is_zero_ether_addr(wpa_s->bssid) ||
5624 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5625}
5626
5627
5628static void wpas_fst_get_channel_info_cb(void *ctx,
5629 enum hostapd_hw_mode *hw_mode,
5630 u8 *channel)
5631{
5632 struct wpa_supplicant *wpa_s = ctx;
5633
5634 if (wpa_s->current_bss) {
5635 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5636 channel);
5637 } else if (wpa_s->hw.num_modes) {
5638 *hw_mode = wpa_s->hw.modes[0].mode;
5639 } else {
5640 WPA_ASSERT(0);
5641 *hw_mode = 0;
5642 }
5643}
5644
5645
5646static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5647{
5648 struct wpa_supplicant *wpa_s = ctx;
5649
5650 *modes = wpa_s->hw.modes;
5651 return wpa_s->hw.num_modes;
5652}
5653
5654
5655static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5656{
5657 struct wpa_supplicant *wpa_s = ctx;
5658
5659 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5660 wpa_s->fst_ies = fst_ies;
5661}
5662
5663
5664static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5665{
5666 struct wpa_supplicant *wpa_s = ctx;
5667
Paul Stewart092955c2017-02-06 09:13:09 -08005668 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5669 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5670 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5671 return -1;
5672 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005673 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005674 wpa_s->own_addr, wpa_s->bssid,
5675 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005676 0);
5677}
5678
5679
5680static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5681{
5682 struct wpa_supplicant *wpa_s = ctx;
5683
5684 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5685 return wpa_s->received_mb_ies;
5686}
5687
5688
5689static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5690 const u8 *buf, size_t size)
5691{
5692 struct wpa_supplicant *wpa_s = ctx;
5693 struct mb_ies_info info;
5694
5695 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5696
5697 if (!mb_ies_info_by_ies(&info, buf, size)) {
5698 wpabuf_free(wpa_s->received_mb_ies);
5699 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5700 }
5701}
5702
5703
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005704static const u8 * wpas_fst_get_peer_first(void *ctx,
5705 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005706 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005707{
5708 struct wpa_supplicant *wpa_s = ctx;
5709
5710 *get_ctx = NULL;
5711 if (!is_zero_ether_addr(wpa_s->bssid))
5712 return (wpa_s->received_mb_ies || !mb_only) ?
5713 wpa_s->bssid : NULL;
5714 return NULL;
5715}
5716
5717
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005718static const u8 * wpas_fst_get_peer_next(void *ctx,
5719 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005720 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005721{
5722 return NULL;
5723}
5724
5725void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5726 struct fst_wpa_obj *iface_obj)
5727{
5728 iface_obj->ctx = wpa_s;
5729 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5730 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5731 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5732 iface_obj->set_ies = wpas_fst_set_ies_cb;
5733 iface_obj->send_action = wpas_fst_send_action_cb;
5734 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5735 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5736 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5737 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5738}
5739#endif /* CONFIG_FST */
5740
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005741static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005742 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005743{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005744 struct wowlan_triggers *triggers;
5745 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005746
5747 if (!wpa_s->conf->wowlan_triggers)
5748 return 0;
5749
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005750 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5751 if (triggers) {
5752 ret = wpa_drv_wowlan(wpa_s, triggers);
5753 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005754 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005755 return ret;
5756}
5757
5758
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005759enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005760{
5761 if (freq < 3000)
5762 return BAND_2_4_GHZ;
5763 if (freq > 50000)
5764 return BAND_60_GHZ;
5765 return BAND_5_GHZ;
5766}
5767
5768
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005769unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005770{
5771 int i;
5772 unsigned int band = 0;
5773
5774 if (freqs) {
5775 /* freqs are specified for the radio work */
5776 for (i = 0; freqs[i]; i++)
5777 band |= wpas_freq_to_band(freqs[i]);
5778 } else {
5779 /*
5780 * freqs are not specified, implies all
5781 * the supported freqs by HW
5782 */
5783 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5784 if (wpa_s->hw.modes[i].num_channels != 0) {
5785 if (wpa_s->hw.modes[i].mode ==
5786 HOSTAPD_MODE_IEEE80211B ||
5787 wpa_s->hw.modes[i].mode ==
5788 HOSTAPD_MODE_IEEE80211G)
5789 band |= BAND_2_4_GHZ;
5790 else if (wpa_s->hw.modes[i].mode ==
5791 HOSTAPD_MODE_IEEE80211A)
5792 band |= BAND_5_GHZ;
5793 else if (wpa_s->hw.modes[i].mode ==
5794 HOSTAPD_MODE_IEEE80211AD)
5795 band |= BAND_60_GHZ;
5796 else if (wpa_s->hw.modes[i].mode ==
5797 HOSTAPD_MODE_IEEE80211ANY)
5798 band = BAND_2_4_GHZ | BAND_5_GHZ |
5799 BAND_60_GHZ;
5800 }
5801 }
5802 }
5803
5804 return band;
5805}
5806
5807
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005808static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5809 const char *rn)
5810{
5811 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5812 struct wpa_radio *radio;
5813
5814 while (rn && iface) {
5815 radio = iface->radio;
5816 if (radio && os_strcmp(rn, radio->name) == 0) {
5817 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5818 wpa_s->ifname, rn);
5819 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5820 return radio;
5821 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005822
5823 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005824 }
5825
5826 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5827 wpa_s->ifname, rn ? rn : "N/A");
5828 radio = os_zalloc(sizeof(*radio));
5829 if (radio == NULL)
5830 return NULL;
5831
5832 if (rn)
5833 os_strlcpy(radio->name, rn, sizeof(radio->name));
5834 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005835 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005836 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5837
5838 return radio;
5839}
5840
5841
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005842static void radio_work_free(struct wpa_radio_work *work)
5843{
5844 if (work->wpa_s->scan_work == work) {
5845 /* This should not really happen. */
5846 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5847 work->type, work, work->started);
5848 work->wpa_s->scan_work = NULL;
5849 }
5850
5851#ifdef CONFIG_P2P
5852 if (work->wpa_s->p2p_scan_work == work) {
5853 /* This should not really happen. */
5854 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5855 work->type, work, work->started);
5856 work->wpa_s->p2p_scan_work = NULL;
5857 }
5858#endif /* CONFIG_P2P */
5859
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005860 if (work->started) {
5861 work->wpa_s->radio->num_active_works--;
5862 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005863 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005864 work->type, work,
5865 work->wpa_s->radio->num_active_works);
5866 }
5867
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005868 dl_list_del(&work->list);
5869 os_free(work);
5870}
5871
5872
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005873static int radio_work_is_connect(struct wpa_radio_work *work)
5874{
5875 return os_strcmp(work->type, "sme-connect") == 0 ||
5876 os_strcmp(work->type, "connect") == 0;
5877}
5878
5879
5880static int radio_work_is_scan(struct wpa_radio_work *work)
5881{
5882 return os_strcmp(work->type, "scan") == 0 ||
5883 os_strcmp(work->type, "p2p-scan") == 0;
5884}
5885
5886
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005887static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5888{
5889 struct wpa_radio_work *active_work = NULL;
5890 struct wpa_radio_work *tmp;
5891
5892 /* Get the active work to know the type and band. */
5893 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5894 if (tmp->started) {
5895 active_work = tmp;
5896 break;
5897 }
5898 }
5899
5900 if (!active_work) {
5901 /* No active work, start one */
5902 radio->num_active_works = 0;
5903 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5904 list) {
5905 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005906 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005907 (((struct wpa_driver_scan_params *)
5908 tmp->ctx)->only_new_results ||
5909 tmp->wpa_s->clear_driver_scan_cache))
5910 continue;
5911 return tmp;
5912 }
5913 return NULL;
5914 }
5915
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005916 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005917 /*
5918 * If the active work is either connect or sme-connect,
5919 * do not parallelize them with other radio works.
5920 */
5921 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5922 "Do not parallelize radio work with %s",
5923 active_work->type);
5924 return NULL;
5925 }
5926
5927 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5928 if (tmp->started)
5929 continue;
5930
5931 /*
5932 * If connect or sme-connect are enqueued, parallelize only
5933 * those operations ahead of them in the queue.
5934 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005935 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005936 break;
5937
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005938 /* Serialize parallel scan and p2p_scan operations on the same
5939 * interface since the driver_nl80211 mechanism for tracking
5940 * scan cookies does not yet have support for this. */
5941 if (active_work->wpa_s == tmp->wpa_s &&
5942 radio_work_is_scan(active_work) &&
5943 radio_work_is_scan(tmp)) {
5944 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5945 "Do not start work '%s' when another work '%s' is already scheduled",
5946 tmp->type, active_work->type);
5947 continue;
5948 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005949 /*
5950 * Check that the radio works are distinct and
5951 * on different bands.
5952 */
5953 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5954 (active_work->bands != tmp->bands)) {
5955 /*
5956 * If a scan has to be scheduled through nl80211 scan
5957 * interface and if an external scan is already running,
5958 * do not schedule the scan since it is likely to get
5959 * rejected by kernel.
5960 */
5961 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005962 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005963 (((struct wpa_driver_scan_params *)
5964 tmp->ctx)->only_new_results ||
5965 tmp->wpa_s->clear_driver_scan_cache))
5966 continue;
5967
5968 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5969 "active_work:%s new_work:%s",
5970 active_work->type, tmp->type);
5971 return tmp;
5972 }
5973 }
5974
5975 /* Did not find a radio work to schedule in parallel. */
5976 return NULL;
5977}
5978
5979
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005980static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5981{
5982 struct wpa_radio *radio = eloop_ctx;
5983 struct wpa_radio_work *work;
5984 struct os_reltime now, diff;
5985 struct wpa_supplicant *wpa_s;
5986
5987 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005988 if (work == NULL) {
5989 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005990 return;
5991 }
5992
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005993 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5994 radio_list);
5995
5996 if (!(wpa_s &&
5997 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5998 if (work->started)
5999 return; /* already started and still in progress */
6000
Hai Shalom60840252021-02-19 19:02:11 -08006001 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006002 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6003 return;
6004 }
6005 } else {
6006 work = NULL;
6007 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6008 /* get the work to schedule next */
6009 work = radio_work_get_next_work(radio);
6010 }
6011 if (!work)
6012 return;
6013 }
6014
6015 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006016 os_get_reltime(&now);
6017 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006018 wpa_dbg(wpa_s, MSG_DEBUG,
6019 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006020 work->type, work, diff.sec, diff.usec);
6021 work->started = 1;
6022 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006023 radio->num_active_works++;
6024
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006025 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006026
6027 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6028 radio->num_active_works < MAX_ACTIVE_WORKS)
6029 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006030}
6031
6032
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006033/*
6034 * This function removes both started and pending radio works running on
6035 * the provided interface's radio.
6036 * Prior to the removal of the radio work, its callback (cb) is called with
6037 * deinit set to be 1. Each work's callback is responsible for clearing its
6038 * internal data and restoring to a correct state.
6039 * @wpa_s: wpa_supplicant data
6040 * @type: type of works to be removed
6041 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6042 * this interface's works.
6043 */
6044void radio_remove_works(struct wpa_supplicant *wpa_s,
6045 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006046{
6047 struct wpa_radio_work *work, *tmp;
6048 struct wpa_radio *radio = wpa_s->radio;
6049
6050 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6051 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006052 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006053 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006054
6055 /* skip other ifaces' works */
6056 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006057 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006058
6059 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6060 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006061 work->cb(work, 1);
6062 radio_work_free(work);
6063 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006064
6065 /* in case we removed the started work */
6066 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006067}
6068
6069
Roshan Pius3a1667e2018-07-03 15:17:14 -07006070void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6071{
6072 struct wpa_radio_work *work;
6073 struct wpa_radio *radio = wpa_s->radio;
6074
6075 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6076 if (work->ctx != ctx)
6077 continue;
6078 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6079 work->type, work, work->started ? " (started)" : "");
6080 radio_work_free(work);
6081 break;
6082 }
6083}
6084
6085
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006086static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6087{
6088 struct wpa_radio *radio = wpa_s->radio;
6089
6090 if (!radio)
6091 return;
6092
6093 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6094 wpa_s->ifname, radio->name);
6095 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006096 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006097 /* If the interface that triggered the external scan was removed, the
6098 * external scan is no longer running. */
6099 if (wpa_s == radio->external_scan_req_interface)
6100 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006101 wpa_s->radio = NULL;
6102 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006103 return; /* Interfaces remain for this radio */
6104
6105 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006106 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006107 os_free(radio);
6108}
6109
6110
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006111void radio_work_check_next(struct wpa_supplicant *wpa_s)
6112{
6113 struct wpa_radio *radio = wpa_s->radio;
6114
6115 if (dl_list_empty(&radio->work))
6116 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006117 if (wpa_s->ext_work_in_progress) {
6118 wpa_printf(MSG_DEBUG,
6119 "External radio work in progress - delay start of pending item");
6120 return;
6121 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006122 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6123 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6124}
6125
6126
6127/**
6128 * radio_add_work - Add a radio work item
6129 * @wpa_s: Pointer to wpa_supplicant data
6130 * @freq: Frequency of the offchannel operation in MHz or 0
6131 * @type: Unique identifier for each type of work
6132 * @next: Force as the next work to be executed
6133 * @cb: Callback function for indicating when radio is available
6134 * @ctx: Context pointer for the work (work->ctx in cb())
6135 * Returns: 0 on success, -1 on failure
6136 *
6137 * This function is used to request time for an operation that requires
6138 * exclusive radio control. Once the radio is available, the registered callback
6139 * function will be called. radio_work_done() must be called once the exclusive
6140 * radio operation has been completed, so that the radio is freed for other
6141 * operations. The special case of deinit=1 is used to free the context data
6142 * during interface removal. That does not allow the callback function to start
6143 * the radio operation, i.e., it must free any resources allocated for the radio
6144 * work and return.
6145 *
6146 * The @freq parameter can be used to indicate a single channel on which the
6147 * offchannel operation will occur. This may allow multiple radio work
6148 * operations to be performed in parallel if they apply for the same channel.
6149 * Setting this to 0 indicates that the work item may use multiple channels or
6150 * requires exclusive control of the radio.
6151 */
6152int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6153 const char *type, int next,
6154 void (*cb)(struct wpa_radio_work *work, int deinit),
6155 void *ctx)
6156{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006157 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006158 struct wpa_radio_work *work;
6159 int was_empty;
6160
6161 work = os_zalloc(sizeof(*work));
6162 if (work == NULL)
6163 return -1;
6164 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6165 os_get_reltime(&work->time);
6166 work->freq = freq;
6167 work->type = type;
6168 work->wpa_s = wpa_s;
6169 work->cb = cb;
6170 work->ctx = ctx;
6171
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006172 if (freq)
6173 work->bands = wpas_freq_to_band(freq);
6174 else if (os_strcmp(type, "scan") == 0 ||
6175 os_strcmp(type, "p2p-scan") == 0)
6176 work->bands = wpas_get_bands(wpa_s,
6177 ((struct wpa_driver_scan_params *)
6178 ctx)->freqs);
6179 else
6180 work->bands = wpas_get_bands(wpa_s, NULL);
6181
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006182 was_empty = dl_list_empty(&wpa_s->radio->work);
6183 if (next)
6184 dl_list_add(&wpa_s->radio->work, &work->list);
6185 else
6186 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6187 if (was_empty) {
6188 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6189 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006190 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6191 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6192 wpa_dbg(wpa_s, MSG_DEBUG,
6193 "Try to schedule a radio work (num_active_works=%u)",
6194 radio->num_active_works);
6195 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006196 }
6197
6198 return 0;
6199}
6200
6201
6202/**
6203 * radio_work_done - Indicate that a radio work item has been completed
6204 * @work: Completed work
6205 *
6206 * This function is called once the callback function registered with
6207 * radio_add_work() has completed its work.
6208 */
6209void radio_work_done(struct wpa_radio_work *work)
6210{
6211 struct wpa_supplicant *wpa_s = work->wpa_s;
6212 struct os_reltime now, diff;
6213 unsigned int started = work->started;
6214
6215 os_get_reltime(&now);
6216 os_reltime_sub(&now, &work->time, &diff);
6217 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6218 work->type, work, started ? "done" : "canceled",
6219 diff.sec, diff.usec);
6220 radio_work_free(work);
6221 if (started)
6222 radio_work_check_next(wpa_s);
6223}
6224
6225
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006226struct wpa_radio_work *
6227radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006228{
6229 struct wpa_radio_work *work;
6230 struct wpa_radio *radio = wpa_s->radio;
6231
6232 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6233 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006234 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006235 }
6236
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006237 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006238}
6239
6240
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006241static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006242 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006243{
6244 const char *ifname, *driver, *rn;
6245
6246 driver = iface->driver;
6247next_driver:
6248 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6249 return -1;
6250
6251 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6252 if (wpa_s->drv_priv == NULL) {
6253 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006254 int level = MSG_ERROR;
6255
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006256 pos = driver ? os_strchr(driver, ',') : NULL;
6257 if (pos) {
6258 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6259 "driver interface - try next driver wrapper");
6260 driver = pos + 1;
6261 goto next_driver;
6262 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006263
6264#ifdef CONFIG_MATCH_IFACE
6265 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6266 level = MSG_DEBUG;
6267#endif /* CONFIG_MATCH_IFACE */
6268 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006269 return -1;
6270 }
6271 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6272 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6273 "driver_param '%s'", wpa_s->conf->driver_param);
6274 return -1;
6275 }
6276
6277 ifname = wpa_drv_get_ifname(wpa_s);
6278 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6279 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6280 "interface name with '%s'", ifname);
6281 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6282 }
6283
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006284 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006285 if (rn && rn[0] == '\0')
6286 rn = NULL;
6287
6288 wpa_s->radio = radio_add_interface(wpa_s, rn);
6289 if (wpa_s->radio == NULL)
6290 return -1;
6291
6292 return 0;
6293}
6294
6295
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006296#ifdef CONFIG_GAS_SERVER
6297
6298static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6299 unsigned int freq, const u8 *dst,
6300 const u8 *src, const u8 *bssid,
6301 const u8 *data, size_t data_len,
6302 enum offchannel_send_action_result result)
6303{
6304 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6305 " result=%s",
6306 freq, MAC2STR(dst),
6307 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6308 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6309 "FAILED"));
6310 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6311 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6312}
6313
6314
6315static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6316 struct wpabuf *buf, unsigned int wait_time)
6317{
6318 struct wpa_supplicant *wpa_s = ctx;
6319 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6320
6321 if (wait_time > wpa_s->max_remain_on_chan)
6322 wait_time = wpa_s->max_remain_on_chan;
6323
6324 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6325 wpabuf_head(buf), wpabuf_len(buf),
6326 wait_time, wpas_gas_server_tx_status, 0);
6327}
6328
6329#endif /* CONFIG_GAS_SERVER */
6330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006331static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006332 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006333{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006334 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006335 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006336 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006337
6338 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6339 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6340 iface->confname ? iface->confname : "N/A",
6341 iface->driver ? iface->driver : "default",
6342 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6343 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6344
6345 if (iface->confname) {
6346#ifdef CONFIG_BACKEND_FILE
6347 wpa_s->confname = os_rel2abs_path(iface->confname);
6348 if (wpa_s->confname == NULL) {
6349 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6350 "for configuration file '%s'.",
6351 iface->confname);
6352 return -1;
6353 }
6354 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6355 iface->confname, wpa_s->confname);
6356#else /* CONFIG_BACKEND_FILE */
6357 wpa_s->confname = os_strdup(iface->confname);
6358#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006359 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006360 if (wpa_s->conf == NULL) {
6361 wpa_printf(MSG_ERROR, "Failed to read or parse "
6362 "configuration '%s'.", wpa_s->confname);
6363 return -1;
6364 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006365 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006366 if (wpa_s->confanother &&
6367 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6368 wpa_printf(MSG_ERROR,
6369 "Failed to read or parse configuration '%s'.",
6370 wpa_s->confanother);
6371 return -1;
6372 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006373
6374 /*
6375 * Override ctrl_interface and driver_param if set on command
6376 * line.
6377 */
6378 if (iface->ctrl_interface) {
6379 os_free(wpa_s->conf->ctrl_interface);
6380 wpa_s->conf->ctrl_interface =
6381 os_strdup(iface->ctrl_interface);
6382 }
6383
6384 if (iface->driver_param) {
6385 os_free(wpa_s->conf->driver_param);
6386 wpa_s->conf->driver_param =
6387 os_strdup(iface->driver_param);
6388 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006389
6390 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6391 os_free(wpa_s->conf->ctrl_interface);
6392 wpa_s->conf->ctrl_interface = NULL;
6393 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006394 } else
6395 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6396 iface->driver_param);
6397
6398 if (wpa_s->conf == NULL) {
6399 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6400 return -1;
6401 }
6402
6403 if (iface->ifname == NULL) {
6404 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6405 return -1;
6406 }
6407 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6408 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6409 iface->ifname);
6410 return -1;
6411 }
6412 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006413#ifdef CONFIG_MATCH_IFACE
6414 wpa_s->matched = iface->matched;
6415#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006416
6417 if (iface->bridge_ifname) {
6418 if (os_strlen(iface->bridge_ifname) >=
6419 sizeof(wpa_s->bridge_ifname)) {
6420 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6421 "name '%s'.", iface->bridge_ifname);
6422 return -1;
6423 }
6424 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6425 sizeof(wpa_s->bridge_ifname));
6426 }
6427
6428 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006429 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6430 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006431
6432 /* Initialize driver interface and register driver event handler before
6433 * L2 receive handler so that association events are processed before
6434 * EAPOL-Key packets if both become available for the same select()
6435 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006436 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006437 return -1;
6438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006439 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6440 return -1;
6441
6442 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6443 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6444 NULL);
6445 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6446
6447 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6448 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6449 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6450 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6451 "dot11RSNAConfigPMKLifetime");
6452 return -1;
6453 }
6454
6455 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6456 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6457 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6458 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6459 "dot11RSNAConfigPMKReauthThreshold");
6460 return -1;
6461 }
6462
6463 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6464 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6465 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6466 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6467 "dot11RSNAConfigSATimeout");
6468 return -1;
6469 }
6470
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006471 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6472 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006473 &wpa_s->hw.flags,
6474 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006475 if (wpa_s->hw.modes) {
6476 u16 i;
6477
6478 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6479 if (wpa_s->hw.modes[i].vht_capab) {
6480 wpa_s->hw_capab = CAPAB_VHT;
6481 break;
6482 }
6483
6484 if (wpa_s->hw.modes[i].ht_capab &
6485 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6486 wpa_s->hw_capab = CAPAB_HT40;
6487 else if (wpa_s->hw.modes[i].ht_capab &&
6488 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6489 wpa_s->hw_capab = CAPAB_HT;
6490 }
6491 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006492
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006493 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6494 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006495 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006497 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006498 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006499 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006500 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006501 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006502 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006503 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6504 wpa_s->max_sched_scan_plan_interval =
6505 capa.max_sched_scan_plan_interval;
6506 wpa_s->max_sched_scan_plan_iterations =
6507 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006508 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6509 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006510 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6511 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006512 wpa_s->extended_capa = capa.extended_capa;
6513 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6514 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006515 wpa_s->num_multichan_concurrent =
6516 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006517 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6518
6519 if (capa.mac_addr_rand_scan_supported)
6520 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6521 if (wpa_s->sched_scan_supported &&
6522 capa.mac_addr_rand_sched_scan_supported)
6523 wpa_s->mac_addr_rand_supported |=
6524 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006525
6526 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6527 if (wpa_s->extended_capa &&
6528 wpa_s->extended_capa_len >= 3 &&
6529 wpa_s->extended_capa[2] & 0x40)
6530 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006531 }
6532 if (wpa_s->max_remain_on_chan == 0)
6533 wpa_s->max_remain_on_chan = 1000;
6534
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006535 /*
6536 * Only take p2p_mgmt parameters when P2P Device is supported.
6537 * Doing it here as it determines whether l2_packet_init() will be done
6538 * during wpa_supplicant_driver_init().
6539 */
6540 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6541 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006542
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006543 if (wpa_s->num_multichan_concurrent == 0)
6544 wpa_s->num_multichan_concurrent = 1;
6545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006546 if (wpa_supplicant_driver_init(wpa_s) < 0)
6547 return -1;
6548
6549#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006550 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006551 return -1;
6552#endif /* CONFIG_TDLS */
6553
6554 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6555 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6556 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6557 return -1;
6558 }
6559
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006560#ifdef CONFIG_FST
6561 if (wpa_s->conf->fst_group_id) {
6562 struct fst_iface_cfg cfg;
6563 struct fst_wpa_obj iface_obj;
6564
6565 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6566 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6567 sizeof(cfg.group_id));
6568 cfg.priority = wpa_s->conf->fst_priority;
6569 cfg.llt = wpa_s->conf->fst_llt;
6570
6571 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6572 &iface_obj, &cfg);
6573 if (!wpa_s->fst) {
6574 wpa_msg(wpa_s, MSG_ERROR,
6575 "FST: Cannot attach iface %s to group %s",
6576 wpa_s->ifname, cfg.group_id);
6577 return -1;
6578 }
6579 }
6580#endif /* CONFIG_FST */
6581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006582 if (wpas_wps_init(wpa_s))
6583 return -1;
6584
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006585#ifdef CONFIG_GAS_SERVER
6586 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6587 if (!wpa_s->gas_server) {
6588 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6589 return -1;
6590 }
6591#endif /* CONFIG_GAS_SERVER */
6592
6593#ifdef CONFIG_DPP
6594 if (wpas_dpp_init(wpa_s) < 0)
6595 return -1;
6596#endif /* CONFIG_DPP */
6597
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006598 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6599 return -1;
6600 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6601
6602 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6603 if (wpa_s->ctrl_iface == NULL) {
6604 wpa_printf(MSG_ERROR,
6605 "Failed to initialize control interface '%s'.\n"
6606 "You may have another wpa_supplicant process "
6607 "already running or the file was\n"
6608 "left by an unclean termination of wpa_supplicant "
6609 "in which case you will need\n"
6610 "to manually remove this file before starting "
6611 "wpa_supplicant again.\n",
6612 wpa_s->conf->ctrl_interface);
6613 return -1;
6614 }
6615
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006616 wpa_s->gas = gas_query_init(wpa_s);
6617 if (wpa_s->gas == NULL) {
6618 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6619 return -1;
6620 }
6621
Roshan Pius3a1667e2018-07-03 15:17:14 -07006622 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6623 wpa_s->p2p_mgmt) &&
6624 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006625 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6626 return -1;
6627 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006628
6629 if (wpa_bss_init(wpa_s) < 0)
6630 return -1;
6631
Paul Stewart092955c2017-02-06 09:13:09 -08006632#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6633#ifdef CONFIG_MESH
6634 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6635#endif /* CONFIG_MESH */
6636#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6637
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006638 /*
6639 * Set Wake-on-WLAN triggers, if configured.
6640 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6641 * have effect anyway when the interface is down).
6642 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006643 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006644 return -1;
6645
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006646#ifdef CONFIG_EAP_PROXY
6647{
6648 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006649 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6650 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006651 if (wpa_s->mnc_len > 0) {
6652 wpa_s->imsi[len] = '\0';
6653 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6654 wpa_s->imsi, wpa_s->mnc_len);
6655 } else {
6656 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6657 }
6658}
6659#endif /* CONFIG_EAP_PROXY */
6660
Dmitry Shmidt04949592012-07-19 12:16:46 -07006661 if (pcsc_reader_init(wpa_s) < 0)
6662 return -1;
6663
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006664 if (wpas_init_ext_pw(wpa_s) < 0)
6665 return -1;
6666
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006667 wpas_rrm_reset(wpa_s);
6668
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006669 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6670
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006671#ifdef CONFIG_HS20
6672 hs20_init(wpa_s);
6673#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006674#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006675 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006676 if ((wpa_s->conf->oce & OCE_STA) &&
6677 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6678 wpa_s->enable_oce = OCE_STA;
6679 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6680 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6681 /* TODO: Need to add STA-CFON support */
6682 wpa_printf(MSG_ERROR,
6683 "OCE STA-CFON feature is not yet supported");
6684 }
6685 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006686 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6687#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006688
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006689 wpa_supplicant_set_default_scan_ies(wpa_s);
6690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006691 return 0;
6692}
6693
6694
6695static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006696 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006697{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006698 struct wpa_global *global = wpa_s->global;
6699 struct wpa_supplicant *iface, *prev;
6700
Jimmy Chen0e73c002021-08-18 13:21:30 +08006701 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006702 wpas_p2p_group_remove(wpa_s, "*");
6703
6704 iface = global->ifaces;
6705 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006706 if (iface->p2pdev == wpa_s)
6707 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006708 if (iface == wpa_s || iface->parent != wpa_s) {
6709 iface = iface->next;
6710 continue;
6711 }
6712 wpa_printf(MSG_DEBUG,
6713 "Remove remaining child interface %s from parent %s",
6714 iface->ifname, wpa_s->ifname);
6715 prev = iface;
6716 iface = iface->next;
6717 wpa_supplicant_remove_iface(global, prev, terminate);
6718 }
6719
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006720 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006721 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006722 /*
6723 * Don't deauthenticate if WoWLAN is enable and not explicitly
6724 * been configured to disconnect.
6725 */
6726 if (!wpa_drv_get_wowlan(wpa_s) ||
6727 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006728 wpa_supplicant_deauthenticate(
6729 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006730
Hai Shalomfdcde762020-04-02 11:19:20 -07006731 wpa_drv_set_countermeasures(wpa_s, 0);
6732 wpa_clear_keys(wpa_s, NULL);
6733 } else {
6734 wpa_msg(wpa_s, MSG_INFO,
6735 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6736 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006737 }
6738
6739 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006740 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006741
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006742 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006743 radio_remove_interface(wpa_s);
6744
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006745#ifdef CONFIG_FST
6746 if (wpa_s->fst) {
6747 fst_detach(wpa_s->fst);
6748 wpa_s->fst = NULL;
6749 }
6750 if (wpa_s->received_mb_ies) {
6751 wpabuf_free(wpa_s->received_mb_ies);
6752 wpa_s->received_mb_ies = NULL;
6753 }
6754#endif /* CONFIG_FST */
6755
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006756 if (wpa_s->drv_priv)
6757 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006758
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006759 if (notify)
6760 wpas_notify_iface_removed(wpa_s);
6761
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006762 if (terminate)
6763 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006764
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02006765 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
6766 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006767
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006768#ifdef CONFIG_MESH
6769 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08006770 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006771 wpa_s->ifmsh = NULL;
6772 }
6773#endif /* CONFIG_MESH */
6774
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006775 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006776 wpa_config_free(wpa_s->conf);
6777 wpa_s->conf = NULL;
6778 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006779
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006780 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006781 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006782
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006783 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006784}
6785
6786
Dmitry Shmidte4663042016-04-04 10:07:49 -07006787#ifdef CONFIG_MATCH_IFACE
6788
6789/**
6790 * wpa_supplicant_match_iface - Match an interface description to a name
6791 * @global: Pointer to global data from wpa_supplicant_init()
6792 * @ifname: Name of the interface to match
6793 * Returns: Pointer to the created interface description or %NULL on failure
6794 */
6795struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6796 const char *ifname)
6797{
6798 int i;
6799 struct wpa_interface *iface, *miface;
6800
6801 for (i = 0; i < global->params.match_iface_count; i++) {
6802 miface = &global->params.match_ifaces[i];
6803 if (!miface->ifname ||
6804 fnmatch(miface->ifname, ifname, 0) == 0) {
6805 iface = os_zalloc(sizeof(*iface));
6806 if (!iface)
6807 return NULL;
6808 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07006809 if (!miface->ifname)
6810 iface->matched = WPA_IFACE_MATCHED_NULL;
6811 else
6812 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006813 iface->ifname = ifname;
6814 return iface;
6815 }
6816 }
6817
6818 return NULL;
6819}
6820
6821
6822/**
6823 * wpa_supplicant_match_existing - Match existing interfaces
6824 * @global: Pointer to global data from wpa_supplicant_init()
6825 * Returns: 0 on success, -1 on failure
6826 */
6827static int wpa_supplicant_match_existing(struct wpa_global *global)
6828{
6829 struct if_nameindex *ifi, *ifp;
6830 struct wpa_supplicant *wpa_s;
6831 struct wpa_interface *iface;
6832
6833 ifp = if_nameindex();
6834 if (!ifp) {
6835 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6836 return -1;
6837 }
6838
6839 for (ifi = ifp; ifi->if_name; ifi++) {
6840 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6841 if (wpa_s)
6842 continue;
6843 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6844 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08006845 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006846 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006847 }
6848 }
6849
6850 if_freenameindex(ifp);
6851 return 0;
6852}
6853
6854#endif /* CONFIG_MATCH_IFACE */
6855
6856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006857/**
6858 * wpa_supplicant_add_iface - Add a new network interface
6859 * @global: Pointer to global data from wpa_supplicant_init()
6860 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006861 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006862 * Returns: Pointer to the created interface or %NULL on failure
6863 *
6864 * This function is used to add new network interfaces for %wpa_supplicant.
6865 * This can be called before wpa_supplicant_run() to add interfaces before the
6866 * main event loop has been started. In addition, new interfaces can be added
6867 * dynamically while %wpa_supplicant is already running. This could happen,
6868 * e.g., when a hotplug network adapter is inserted.
6869 */
6870struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006871 struct wpa_interface *iface,
6872 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006873{
6874 struct wpa_supplicant *wpa_s;
6875 struct wpa_interface t_iface;
6876 struct wpa_ssid *ssid;
6877
6878 if (global == NULL || iface == NULL)
6879 return NULL;
6880
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006881 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006882 if (wpa_s == NULL)
6883 return NULL;
6884
6885 wpa_s->global = global;
6886
6887 t_iface = *iface;
6888 if (global->params.override_driver) {
6889 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6890 "('%s' -> '%s')",
6891 iface->driver, global->params.override_driver);
6892 t_iface.driver = global->params.override_driver;
6893 }
6894 if (global->params.override_ctrl_interface) {
6895 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6896 "ctrl_interface ('%s' -> '%s')",
6897 iface->ctrl_interface,
6898 global->params.override_ctrl_interface);
6899 t_iface.ctrl_interface =
6900 global->params.override_ctrl_interface;
6901 }
6902 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6903 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6904 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006905 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006906 return NULL;
6907 }
6908
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006909 /* Notify the control interfaces about new iface */
6910 if (wpas_notify_iface_added(wpa_s)) {
6911 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6912 return NULL;
6913 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006914
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006915 /* Notify the control interfaces about new networks for non p2p mgmt
6916 * ifaces. */
6917 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006918 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6919 wpas_notify_network_added(wpa_s, ssid);
6920 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006921
6922 wpa_s->next = global->ifaces;
6923 global->ifaces = wpa_s;
6924
6925 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006926 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006927
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006928#ifdef CONFIG_P2P
6929 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006930 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006931 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006932 wpas_p2p_add_p2pdev_interface(
6933 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006934 wpa_printf(MSG_INFO,
6935 "P2P: Failed to enable P2P Device interface");
6936 /* Try to continue without. P2P will be disabled. */
6937 }
6938#endif /* CONFIG_P2P */
6939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006940 return wpa_s;
6941}
6942
6943
6944/**
6945 * wpa_supplicant_remove_iface - Remove a network interface
6946 * @global: Pointer to global data from wpa_supplicant_init()
6947 * @wpa_s: Pointer to the network interface to be removed
6948 * Returns: 0 if interface was removed, -1 if interface was not found
6949 *
6950 * This function can be used to dynamically remove network interfaces from
6951 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6952 * addition, this function is used to remove all remaining interfaces when
6953 * %wpa_supplicant is terminated.
6954 */
6955int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006956 struct wpa_supplicant *wpa_s,
6957 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006958{
6959 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006960#ifdef CONFIG_MESH
6961 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6962 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006963 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006964#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006965
6966 /* Remove interface from the global list of interfaces */
6967 prev = global->ifaces;
6968 if (prev == wpa_s) {
6969 global->ifaces = wpa_s->next;
6970 } else {
6971 while (prev && prev->next != wpa_s)
6972 prev = prev->next;
6973 if (prev == NULL)
6974 return -1;
6975 prev->next = wpa_s->next;
6976 }
6977
6978 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6979
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006980#ifdef CONFIG_MESH
6981 if (mesh_if_created) {
6982 ifname = os_strdup(wpa_s->ifname);
6983 if (ifname == NULL) {
6984 wpa_dbg(wpa_s, MSG_ERROR,
6985 "mesh: Failed to malloc ifname");
6986 return -1;
6987 }
6988 }
6989#endif /* CONFIG_MESH */
6990
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006991 if (global->p2p_group_formation == wpa_s)
6992 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006993 if (global->p2p_invite_group == wpa_s)
6994 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006995 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006996
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006997#ifdef CONFIG_MESH
6998 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006999 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007000 os_free(ifname);
7001 }
7002#endif /* CONFIG_MESH */
7003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007004 return 0;
7005}
7006
7007
7008/**
7009 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7010 * @wpa_s: Pointer to the network interface
7011 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7012 */
7013const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7014{
7015 const char *eapol_method;
7016
7017 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7018 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7019 return "NO-EAP";
7020 }
7021
7022 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7023 if (eapol_method == NULL)
7024 return "UNKNOWN-EAP";
7025
7026 return eapol_method;
7027}
7028
7029
7030/**
7031 * wpa_supplicant_get_iface - Get a new network interface
7032 * @global: Pointer to global data from wpa_supplicant_init()
7033 * @ifname: Interface name
7034 * Returns: Pointer to the interface or %NULL if not found
7035 */
7036struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7037 const char *ifname)
7038{
7039 struct wpa_supplicant *wpa_s;
7040
7041 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7042 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7043 return wpa_s;
7044 }
7045 return NULL;
7046}
7047
7048
7049#ifndef CONFIG_NO_WPA_MSG
7050static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7051{
7052 struct wpa_supplicant *wpa_s = ctx;
7053 if (wpa_s == NULL)
7054 return NULL;
7055 return wpa_s->ifname;
7056}
7057#endif /* CONFIG_NO_WPA_MSG */
7058
7059
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007060#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7061#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7062#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7063
7064/* Periodic cleanup tasks */
7065static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7066{
7067 struct wpa_global *global = eloop_ctx;
7068 struct wpa_supplicant *wpa_s;
7069
7070 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7071 wpas_periodic, global, NULL);
7072
7073#ifdef CONFIG_P2P
7074 if (global->p2p)
7075 p2p_expire_peers(global->p2p);
7076#endif /* CONFIG_P2P */
7077
7078 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7079 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7080#ifdef CONFIG_AP
7081 ap_periodic(wpa_s);
7082#endif /* CONFIG_AP */
7083 }
7084}
7085
7086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007087/**
7088 * wpa_supplicant_init - Initialize %wpa_supplicant
7089 * @params: Parameters for %wpa_supplicant
7090 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7091 *
7092 * This function is used to initialize %wpa_supplicant. After successful
7093 * initialization, the returned data pointer can be used to add and remove
7094 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7095 */
7096struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7097{
7098 struct wpa_global *global;
7099 int ret, i;
7100
7101 if (params == NULL)
7102 return NULL;
7103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007104#ifdef CONFIG_DRIVER_NDIS
7105 {
7106 void driver_ndis_init_ops(void);
7107 driver_ndis_init_ops();
7108 }
7109#endif /* CONFIG_DRIVER_NDIS */
7110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007111#ifndef CONFIG_NO_WPA_MSG
7112 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7113#endif /* CONFIG_NO_WPA_MSG */
7114
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007115 if (params->wpa_debug_file_path)
7116 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007117 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007118 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007119 if (params->wpa_debug_syslog)
7120 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007121 if (params->wpa_debug_tracing) {
7122 ret = wpa_debug_open_linux_tracing();
7123 if (ret) {
7124 wpa_printf(MSG_ERROR,
7125 "Failed to enable trace logging");
7126 return NULL;
7127 }
7128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129
7130 ret = eap_register_methods();
7131 if (ret) {
7132 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7133 if (ret == -2)
7134 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7135 "the same EAP type.");
7136 return NULL;
7137 }
7138
7139 global = os_zalloc(sizeof(*global));
7140 if (global == NULL)
7141 return NULL;
7142 dl_list_init(&global->p2p_srv_bonjour);
7143 dl_list_init(&global->p2p_srv_upnp);
7144 global->params.daemonize = params->daemonize;
7145 global->params.wait_for_monitor = params->wait_for_monitor;
7146 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7147 if (params->pid_file)
7148 global->params.pid_file = os_strdup(params->pid_file);
7149 if (params->ctrl_interface)
7150 global->params.ctrl_interface =
7151 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007152 if (params->ctrl_interface_group)
7153 global->params.ctrl_interface_group =
7154 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007155 if (params->override_driver)
7156 global->params.override_driver =
7157 os_strdup(params->override_driver);
7158 if (params->override_ctrl_interface)
7159 global->params.override_ctrl_interface =
7160 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007161#ifdef CONFIG_MATCH_IFACE
7162 global->params.match_iface_count = params->match_iface_count;
7163 if (params->match_iface_count) {
7164 global->params.match_ifaces =
7165 os_calloc(params->match_iface_count,
7166 sizeof(struct wpa_interface));
7167 os_memcpy(global->params.match_ifaces,
7168 params->match_ifaces,
7169 params->match_iface_count *
7170 sizeof(struct wpa_interface));
7171 }
7172#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007173#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007174 if (params->conf_p2p_dev)
7175 global->params.conf_p2p_dev =
7176 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007177#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007178 wpa_debug_level = global->params.wpa_debug_level =
7179 params->wpa_debug_level;
7180 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7181 params->wpa_debug_show_keys;
7182 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7183 params->wpa_debug_timestamp;
7184
Hai Shalomfdcde762020-04-02 11:19:20 -07007185 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007186
7187 if (eloop_init()) {
7188 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7189 wpa_supplicant_deinit(global);
7190 return NULL;
7191 }
7192
Jouni Malinen75ecf522011-06-27 15:19:46 -07007193 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007194
7195 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7196 if (global->ctrl_iface == NULL) {
7197 wpa_supplicant_deinit(global);
7198 return NULL;
7199 }
7200
7201 if (wpas_notify_supplicant_initialized(global)) {
7202 wpa_supplicant_deinit(global);
7203 return NULL;
7204 }
7205
7206 for (i = 0; wpa_drivers[i]; i++)
7207 global->drv_count++;
7208 if (global->drv_count == 0) {
7209 wpa_printf(MSG_ERROR, "No drivers enabled");
7210 wpa_supplicant_deinit(global);
7211 return NULL;
7212 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007213 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007214 if (global->drv_priv == NULL) {
7215 wpa_supplicant_deinit(global);
7216 return NULL;
7217 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007218
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007219#ifdef CONFIG_WIFI_DISPLAY
7220 if (wifi_display_init(global) < 0) {
7221 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7222 wpa_supplicant_deinit(global);
7223 return NULL;
7224 }
7225#endif /* CONFIG_WIFI_DISPLAY */
7226
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007227 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7228 wpas_periodic, global, NULL);
7229
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007230 return global;
7231}
7232
7233
7234/**
7235 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7236 * @global: Pointer to global data from wpa_supplicant_init()
7237 * Returns: 0 after successful event loop run, -1 on failure
7238 *
7239 * This function starts the main event loop and continues running as long as
7240 * there are any remaining events. In most cases, this function is running as
7241 * long as the %wpa_supplicant process in still in use.
7242 */
7243int wpa_supplicant_run(struct wpa_global *global)
7244{
7245 struct wpa_supplicant *wpa_s;
7246
7247 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007248 (wpa_supplicant_daemon(global->params.pid_file) ||
7249 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007250 return -1;
7251
Dmitry Shmidte4663042016-04-04 10:07:49 -07007252#ifdef CONFIG_MATCH_IFACE
7253 if (wpa_supplicant_match_existing(global))
7254 return -1;
7255#endif
7256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007257 if (global->params.wait_for_monitor) {
7258 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007259 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007260 wpa_supplicant_ctrl_iface_wait(
7261 wpa_s->ctrl_iface);
7262 }
7263
7264 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7265 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7266
7267 eloop_run();
7268
7269 return 0;
7270}
7271
7272
7273/**
7274 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7275 * @global: Pointer to global data from wpa_supplicant_init()
7276 *
7277 * This function is called to deinitialize %wpa_supplicant and to free all
7278 * allocated resources. Remaining network interfaces will also be removed.
7279 */
7280void wpa_supplicant_deinit(struct wpa_global *global)
7281{
7282 int i;
7283
7284 if (global == NULL)
7285 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007286
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007287 eloop_cancel_timeout(wpas_periodic, global, NULL);
7288
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007289#ifdef CONFIG_WIFI_DISPLAY
7290 wifi_display_deinit(global);
7291#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007292
7293 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007294 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295
7296 if (global->ctrl_iface)
7297 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7298
7299 wpas_notify_supplicant_deinitialized(global);
7300
7301 eap_peer_unregister_methods();
7302#ifdef CONFIG_AP
7303 eap_server_unregister_methods();
7304#endif /* CONFIG_AP */
7305
7306 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7307 if (!global->drv_priv[i])
7308 continue;
7309 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7310 }
7311 os_free(global->drv_priv);
7312
7313 random_deinit();
7314
7315 eloop_destroy();
7316
7317 if (global->params.pid_file) {
7318 os_daemonize_terminate(global->params.pid_file);
7319 os_free(global->params.pid_file);
7320 }
7321 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007322 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007323 os_free(global->params.override_driver);
7324 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007325#ifdef CONFIG_MATCH_IFACE
7326 os_free(global->params.match_ifaces);
7327#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007328#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007329 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007330#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007331
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007332 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007333 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007334 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007335
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007336 os_free(global);
7337 wpa_debug_close_syslog();
7338 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007339 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007340}
7341
7342
7343void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7344{
7345 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7346 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7347 char country[3];
7348 country[0] = wpa_s->conf->country[0];
7349 country[1] = wpa_s->conf->country[1];
7350 country[2] = '\0';
7351 if (wpa_drv_set_country(wpa_s, country) < 0) {
7352 wpa_printf(MSG_ERROR, "Failed to set country code "
7353 "'%s'", country);
7354 }
7355 }
7356
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007357 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7358 wpas_init_ext_pw(wpa_s);
7359
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007360 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7361 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7362
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007363 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7364 struct wpa_driver_capa capa;
7365 int res = wpa_drv_get_capa(wpa_s, &capa);
7366
7367 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7368 wpa_printf(MSG_ERROR,
7369 "Failed to update wowlan_triggers to '%s'",
7370 wpa_s->conf->wowlan_triggers);
7371 }
7372
Hai Shalom81f62d82019-07-22 12:10:00 -07007373 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7374 wpa_supplicant_set_default_scan_ies(wpa_s);
7375
Hai Shalom899fcc72020-10-19 14:38:18 -07007376#ifdef CONFIG_BGSCAN
7377 /*
7378 * We default to global bgscan parameters only when per-network bgscan
7379 * parameters aren't set. Only bother resetting bgscan parameters if
7380 * this is the case.
7381 */
7382 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7383 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7384 wpa_s->wpa_state == WPA_COMPLETED)
7385 wpa_supplicant_reset_bgscan(wpa_s);
7386#endif /* CONFIG_BGSCAN */
7387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007388#ifdef CONFIG_WPS
7389 wpas_wps_update_config(wpa_s);
7390#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007391 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007392 wpa_s->conf->changed_parameters = 0;
7393}
7394
7395
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007396void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007397{
7398 int i;
7399
7400 for (i = 0; i < *num_freqs; i++) {
7401 if (freqs[i] == freq)
7402 return;
7403 }
7404
7405 freqs[*num_freqs] = freq;
7406 (*num_freqs)++;
7407}
7408
7409
7410static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7411{
7412 struct wpa_bss *bss, *cbss;
7413 const int max_freqs = 10;
7414 int *freqs;
7415 int num_freqs = 0;
7416
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007417 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007418 if (freqs == NULL)
7419 return NULL;
7420
7421 cbss = wpa_s->current_bss;
7422
7423 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7424 if (bss == cbss)
7425 continue;
7426 if (bss->ssid_len == cbss->ssid_len &&
7427 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007428 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007429 add_freq(freqs, &num_freqs, bss->freq);
7430 if (num_freqs == max_freqs)
7431 break;
7432 }
7433 }
7434
7435 if (num_freqs == 0) {
7436 os_free(freqs);
7437 freqs = NULL;
7438 }
7439
7440 return freqs;
7441}
7442
7443
7444void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7445{
7446 int timeout;
7447 int count;
7448 int *freqs = NULL;
7449
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007450 wpas_connect_work_done(wpa_s);
7451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007452 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007453 * Remove possible authentication timeout since the connection failed.
7454 */
7455 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7456
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007457 /*
Hai Shalom60840252021-02-19 19:02:11 -08007458 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007459 * generated based on local request to disconnect.
7460 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007461 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007462 wpa_s->own_disconnect_req = 0;
7463 wpa_dbg(wpa_s, MSG_DEBUG,
7464 "Ignore connection failure due to local request to disconnect");
7465 return;
7466 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007467 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007468 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7469 "indication since interface has been put into "
7470 "disconnected state");
7471 return;
7472 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007473 if (wpa_s->auto_reconnect_disabled) {
7474 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7475 "indication since auto connect is disabled");
7476 return;
7477 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007478
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007479 /*
Hai Shalom60840252021-02-19 19:02:11 -08007480 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007482 */
Hai Shalom60840252021-02-19 19:02:11 -08007483 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007484 if (count == 1 && wpa_s->current_bss) {
7485 /*
Hai Shalom60840252021-02-19 19:02:11 -08007486 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007487 * another BSS available for the same ESS, we should try that
7488 * next. Otherwise, we may as well try this one once more
7489 * before allowing other, likely worse, ESSes to be considered.
7490 */
7491 freqs = get_bss_freqs_in_ess(wpa_s);
7492 if (freqs) {
7493 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7494 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007495 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007496 /*
7497 * On the next scan, go through only the known channels
7498 * used in this ESS based on previous scans to speed up
7499 * common load balancing use case.
7500 */
7501 os_free(wpa_s->next_scan_freqs);
7502 wpa_s->next_scan_freqs = freqs;
7503 }
7504 }
7505
Hai Shalom899fcc72020-10-19 14:38:18 -07007506 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007507
Hai Shalom899fcc72020-10-19 14:38:18 -07007508 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007509 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7510 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007511 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007512 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007513 /*
7514 * Multiple consecutive connection failures mean that other APs are
7515 * either not available or have already been tried, so we can start
7516 * increasing the delay here to avoid constant scanning.
7517 */
7518 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007519 case 1:
7520 timeout = 100;
7521 break;
7522 case 2:
7523 timeout = 500;
7524 break;
7525 case 3:
7526 timeout = 1000;
7527 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007528 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007529 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007530 break;
7531 default:
7532 timeout = 10000;
7533 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007534 }
7535
Hai Shalom899fcc72020-10-19 14:38:18 -07007536 wpa_dbg(wpa_s, MSG_DEBUG,
7537 "Consecutive connection failures: %d --> request scan in %d ms",
7538 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007540 /*
7541 * TODO: if more than one possible AP is available in scan results,
7542 * could try the other ones before requesting a new scan.
7543 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007544
7545 /* speed up the connection attempt with normal scan */
7546 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007547 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7548 1000 * (timeout % 1000));
7549}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007550
7551
Hai Shalomce48b4a2018-09-05 11:41:35 -07007552#ifdef CONFIG_FILS
7553void fils_connection_failure(struct wpa_supplicant *wpa_s)
7554{
7555 struct wpa_ssid *ssid = wpa_s->current_ssid;
7556 const u8 *realm, *username, *rrk;
7557 size_t realm_len, username_len, rrk_len;
7558 u16 next_seq_num;
7559
7560 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7561 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7562 &username, &username_len,
7563 &realm, &realm_len, &next_seq_num,
7564 &rrk, &rrk_len) != 0 ||
7565 !realm)
7566 return;
7567
7568 wpa_hexdump_ascii(MSG_DEBUG,
7569 "FILS: Store last connection failure realm",
7570 realm, realm_len);
7571 os_free(wpa_s->last_con_fail_realm);
7572 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7573 if (wpa_s->last_con_fail_realm) {
7574 wpa_s->last_con_fail_realm_len = realm_len;
7575 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7576 }
7577}
7578#endif /* CONFIG_FILS */
7579
7580
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007581int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7582{
7583 return wpa_s->conf->ap_scan == 2 ||
7584 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7585}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007586
Dmitry Shmidt04949592012-07-19 12:16:46 -07007587
Gabriel Biren57ededa2021-09-03 16:08:50 +00007588#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007589int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7590 struct wpa_ssid *ssid,
7591 const char *field,
7592 const char *value)
7593{
7594#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007595 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007596
7597 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7598 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7599 (const u8 *) value, os_strlen(value));
7600
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007601 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007602 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007603#else /* IEEE8021X_EAPOL */
7604 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7605 return -1;
7606#endif /* IEEE8021X_EAPOL */
7607}
7608
7609int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7610 struct wpa_ssid *ssid,
7611 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007612 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007613{
7614#ifdef IEEE8021X_EAPOL
7615 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007616 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007617
7618 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007619 case WPA_CTRL_REQ_EAP_IDENTITY:
7620 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007621 os_free(eap->imsi_identity);
7622 if (value == NULL)
7623 return -1;
7624 identity = os_strchr(value, ':');
7625 if (identity == NULL) {
7626 /* plain identity */
7627 eap->identity = (u8 *)os_strdup(value);
7628 eap->identity_len = os_strlen(value);
7629 } else {
7630 /* have both plain identity and encrypted identity */
7631 imsi_identity = value;
7632 *identity++ = '\0';
7633 /* plain identity */
7634 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7635 eap->imsi_identity_len = strlen(imsi_identity);
7636 /* encrypted identity */
7637 eap->identity = (u8 *)dup_binstr(identity,
7638 value_len - strlen(imsi_identity) - 1);
7639 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7640 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007641 eap->pending_req_identity = 0;
7642 if (ssid == wpa_s->current_ssid)
7643 wpa_s->reassociate = 1;
7644 break;
7645 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007646 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007647 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007648 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007649 eap->pending_req_password = 0;
7650 if (ssid == wpa_s->current_ssid)
7651 wpa_s->reassociate = 1;
7652 break;
7653 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007654 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007655 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007656 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007657 eap->pending_req_new_password = 0;
7658 if (ssid == wpa_s->current_ssid)
7659 wpa_s->reassociate = 1;
7660 break;
7661 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007662 str_clear_free(eap->cert.pin);
7663 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007664 eap->pending_req_pin = 0;
7665 if (ssid == wpa_s->current_ssid)
7666 wpa_s->reassociate = 1;
7667 break;
7668 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007669 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007670 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007671 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007672 os_free(eap->pending_req_otp);
7673 eap->pending_req_otp = NULL;
7674 eap->pending_req_otp_len = 0;
7675 break;
7676 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007677 str_clear_free(eap->cert.private_key_passwd);
7678 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007679 eap->pending_req_passphrase = 0;
7680 if (ssid == wpa_s->current_ssid)
7681 wpa_s->reassociate = 1;
7682 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007683 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007684 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007685 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007686 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007687 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007688 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7689 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7690 return -1;
7691 ssid->mem_only_psk = 1;
7692 if (ssid->passphrase)
7693 wpa_config_update_psk(ssid);
7694 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7695 wpa_supplicant_req_scan(wpa_s, 0, 0);
7696 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007697 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7698 if (eap->pending_ext_cert_check != PENDING_CHECK)
7699 return -1;
7700 if (os_strcmp(value, "good") == 0)
7701 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7702 else if (os_strcmp(value, "bad") == 0)
7703 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7704 else
7705 return -1;
7706 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007707 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007708 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007709 return -1;
7710 }
7711
7712 return 0;
7713#else /* IEEE8021X_EAPOL */
7714 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7715 return -1;
7716#endif /* IEEE8021X_EAPOL */
7717}
Gabriel Biren57ededa2021-09-03 16:08:50 +00007718#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007719
7720
7721int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7722{
Hai Shalomfdcde762020-04-02 11:19:20 -07007723#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007724 int i;
7725 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007726#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007727
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007728 if (wpa_s->p2p_mgmt)
7729 return 1; /* no normal network profiles on p2p_mgmt interface */
7730
Dmitry Shmidt04949592012-07-19 12:16:46 -07007731 if (ssid == NULL)
7732 return 1;
7733
7734 if (ssid->disabled)
7735 return 1;
7736
Hai Shalomfdcde762020-04-02 11:19:20 -07007737#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007738 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007739 drv_enc = wpa_s->drv_enc;
7740 else
7741 drv_enc = (unsigned int) -1;
7742
7743 for (i = 0; i < NUM_WEP_KEYS; i++) {
7744 size_t len = ssid->wep_key_len[i];
7745 if (len == 0)
7746 continue;
7747 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7748 continue;
7749 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7750 continue;
7751 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7752 continue;
7753 return 1; /* invalid WEP key */
7754 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007755#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007756
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007757 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007758 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007759 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007760 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007761 return 1;
7762
Dmitry Shmidt04949592012-07-19 12:16:46 -07007763 return 0;
7764}
7765
7766
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007767int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7768{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007769 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7770 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7771 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7772 /*
7773 * Driver does not support BIP -- ignore pmf=1 default
7774 * since the connection with PMF would fail and the
7775 * configuration does not require PMF to be enabled.
7776 */
7777 return NO_MGMT_FRAME_PROTECTION;
7778 }
7779
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007780 if (ssid &&
7781 (ssid->key_mgmt &
7782 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7783 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7784 /*
7785 * Do not use the default PMF value for non-RSN networks
7786 * since PMF is available only with RSN and pmf=2
7787 * configuration would otherwise prevent connections to
7788 * all open networks.
7789 */
7790 return NO_MGMT_FRAME_PROTECTION;
7791 }
7792
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007793 return wpa_s->conf->pmf;
7794 }
7795
7796 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007797}
7798
7799
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007800int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007801{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007802 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007803 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007804 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007805 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007806 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007807}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007808
7809
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007810void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007811{
7812 struct wpa_ssid *ssid = wpa_s->current_ssid;
7813 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007814 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007815
7816 if (ssid == NULL) {
7817 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7818 "SSID block");
7819 return;
7820 }
7821
7822 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7823 return;
7824
7825 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007826
7827#ifdef CONFIG_P2P
7828 if (ssid->p2p_group &&
7829 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7830 /*
7831 * Skip the wait time since there is a short timeout on the
7832 * connection to a P2P group.
7833 */
7834 return;
7835 }
7836#endif /* CONFIG_P2P */
7837
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007838 if (ssid->auth_failures > 50)
7839 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007840 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007841 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007842 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007843 dur = 90;
7844 else if (ssid->auth_failures > 3)
7845 dur = 60;
7846 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007847 dur = 30;
7848 else if (ssid->auth_failures > 1)
7849 dur = 20;
7850 else
7851 dur = 10;
7852
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007853 if (ssid->auth_failures > 1 &&
7854 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7855 dur += os_random() % (ssid->auth_failures * 10);
7856
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007857 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007858 if (now.sec + dur <= ssid->disabled_until.sec)
7859 return;
7860
7861 ssid->disabled_until.sec = now.sec + dur;
7862
7863 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007864 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007865 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007866 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007867}
7868
7869
7870void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7871 struct wpa_ssid *ssid, int clear_failures)
7872{
7873 if (ssid == NULL)
7874 return;
7875
7876 if (ssid->disabled_until.sec) {
7877 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7878 "id=%d ssid=\"%s\"",
7879 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7880 }
7881 ssid->disabled_until.sec = 0;
7882 ssid->disabled_until.usec = 0;
7883 if (clear_failures)
7884 ssid->auth_failures = 0;
7885}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007886
7887
7888int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7889{
7890 size_t i;
7891
7892 if (wpa_s->disallow_aps_bssid == NULL)
7893 return 0;
7894
7895 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7896 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7897 bssid, ETH_ALEN) == 0)
7898 return 1;
7899 }
7900
7901 return 0;
7902}
7903
7904
7905int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7906 size_t ssid_len)
7907{
7908 size_t i;
7909
7910 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7911 return 0;
7912
7913 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7914 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7915 if (ssid_len == s->ssid_len &&
7916 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7917 return 1;
7918 }
7919
7920 return 0;
7921}
7922
7923
7924/**
7925 * wpas_request_connection - Request a new connection
7926 * @wpa_s: Pointer to the network interface
7927 *
7928 * This function is used to request a new connection to be found. It will mark
7929 * the interface to allow reassociation and request a new scan to find a
7930 * suitable network to connect to.
7931 */
7932void wpas_request_connection(struct wpa_supplicant *wpa_s)
7933{
7934 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007935 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007936 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007937 wpa_s->disconnected = 0;
7938 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007939 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007940
7941 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7942 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007943 else
7944 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007945}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007946
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007947
Roshan Pius02242d72016-08-09 15:31:48 -07007948/**
7949 * wpas_request_disconnection - Request disconnection
7950 * @wpa_s: Pointer to the network interface
7951 *
7952 * This function is used to request disconnection from the currently connected
7953 * network. This will stop any ongoing scans and initiate deauthentication.
7954 */
7955void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7956{
7957#ifdef CONFIG_SME
7958 wpa_s->sme.prev_bssid_set = 0;
7959#endif /* CONFIG_SME */
7960 wpa_s->reassociate = 0;
7961 wpa_s->disconnected = 1;
7962 wpa_supplicant_cancel_sched_scan(wpa_s);
7963 wpa_supplicant_cancel_scan(wpa_s);
7964 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7965 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007966 radio_remove_works(wpa_s, "connect", 0);
7967 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007968}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007969
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007970
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007971void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7972 struct wpa_used_freq_data *freqs_data,
7973 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007974{
7975 unsigned int i;
7976
7977 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7978 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007979 for (i = 0; i < len; i++) {
7980 struct wpa_used_freq_data *cur = &freqs_data[i];
7981 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7982 i, cur->freq, cur->flags);
7983 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007984}
7985
7986
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007987/*
7988 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007989 * are using the same radio as the current interface, and in addition, get
7990 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007991 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007992int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7993 struct wpa_used_freq_data *freqs_data,
7994 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007995{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007996 struct wpa_supplicant *ifs;
7997 u8 bssid[ETH_ALEN];
7998 int freq;
7999 unsigned int idx = 0, i;
8000
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008001 wpa_dbg(wpa_s, MSG_DEBUG,
8002 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008003 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008004
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008005 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8006 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008007 if (idx == len)
8008 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008009
8010 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8011 continue;
8012
8013 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008014 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8015 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008016 freq = ifs->current_ssid->frequency;
8017 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8018 freq = ifs->assoc_freq;
8019 else
8020 continue;
8021
8022 /* Hold only distinct freqs */
8023 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008024 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008025 break;
8026
8027 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008028 freqs_data[idx++].freq = freq;
8029
8030 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008031 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008032 WPA_FREQ_USED_BY_P2P_CLIENT :
8033 WPA_FREQ_USED_BY_INFRA_STATION;
8034 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008035 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008036
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008037 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008038 return idx;
8039}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008040
8041
8042/*
8043 * Find the operating frequencies of any of the virtual interfaces that
8044 * are using the same radio as the current interface.
8045 */
8046int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8047 int *freq_array, unsigned int len)
8048{
8049 struct wpa_used_freq_data *freqs_data;
8050 int num, i;
8051
8052 os_memset(freq_array, 0, sizeof(int) * len);
8053
8054 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8055 if (!freqs_data)
8056 return -1;
8057
8058 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8059 for (i = 0; i < num; i++)
8060 freq_array[i] = freqs_data[i].freq;
8061
8062 os_free(freqs_data);
8063
8064 return num;
8065}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008066
8067
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008068struct wpa_supplicant *
8069wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8070{
8071 switch (frame) {
8072#ifdef CONFIG_P2P
8073 case VENDOR_ELEM_PROBE_REQ_P2P:
8074 case VENDOR_ELEM_PROBE_RESP_P2P:
8075 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8076 case VENDOR_ELEM_BEACON_P2P_GO:
8077 case VENDOR_ELEM_P2P_PD_REQ:
8078 case VENDOR_ELEM_P2P_PD_RESP:
8079 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8080 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8081 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8082 case VENDOR_ELEM_P2P_INV_REQ:
8083 case VENDOR_ELEM_P2P_INV_RESP:
8084 case VENDOR_ELEM_P2P_ASSOC_REQ:
8085 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008086 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008087#endif /* CONFIG_P2P */
8088 default:
8089 return wpa_s;
8090 }
8091}
8092
8093
8094void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8095{
8096 unsigned int i;
8097 char buf[30];
8098
8099 wpa_printf(MSG_DEBUG, "Update vendor elements");
8100
8101 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8102 if (wpa_s->vendor_elem[i]) {
8103 int res;
8104
8105 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8106 if (!os_snprintf_error(sizeof(buf), res)) {
8107 wpa_hexdump_buf(MSG_DEBUG, buf,
8108 wpa_s->vendor_elem[i]);
8109 }
8110 }
8111 }
8112
8113#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008114 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008115 wpa_s->global->p2p &&
8116 !wpa_s->global->p2p_disabled)
8117 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8118#endif /* CONFIG_P2P */
8119}
8120
8121
8122int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8123 const u8 *elem, size_t len)
8124{
8125 u8 *ie, *end;
8126
8127 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8128 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8129
8130 for (; ie + 1 < end; ie += 2 + ie[1]) {
8131 if (ie + len > end)
8132 break;
8133 if (os_memcmp(ie, elem, len) != 0)
8134 continue;
8135
8136 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8137 wpabuf_free(wpa_s->vendor_elem[frame]);
8138 wpa_s->vendor_elem[frame] = NULL;
8139 } else {
8140 os_memmove(ie, ie + len, end - (ie + len));
8141 wpa_s->vendor_elem[frame]->used -= len;
8142 }
8143 wpas_vendor_elem_update(wpa_s);
8144 return 0;
8145 }
8146
8147 return -1;
8148}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008149
8150
8151struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008152 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008153 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008154{
8155 u16 i;
8156
8157 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008158 if (modes[i].mode != mode ||
8159 !modes[i].num_channels || !modes[i].channels)
8160 continue;
8161 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8162 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008163 return &modes[i];
8164 }
8165
8166 return NULL;
8167}
8168
8169
8170static struct
8171wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8172 const u8 *bssid)
8173{
8174 struct wpa_bss_tmp_disallowed *bss;
8175
8176 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8177 struct wpa_bss_tmp_disallowed, list) {
8178 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8179 return bss;
8180 }
8181
8182 return NULL;
8183}
8184
8185
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008186static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8187{
8188 struct wpa_bss_tmp_disallowed *tmp;
8189 unsigned int num_bssid = 0;
8190 u8 *bssids;
8191 int ret;
8192
8193 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8194 if (!bssids)
8195 return -1;
8196 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8197 struct wpa_bss_tmp_disallowed, list) {
8198 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8199 ETH_ALEN);
8200 num_bssid++;
8201 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008202 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008203 os_free(bssids);
8204 return ret;
8205}
8206
8207
8208static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8209{
8210 struct wpa_supplicant *wpa_s = eloop_ctx;
8211 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8212
8213 /* Make sure the bss is not already freed */
8214 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8215 struct wpa_bss_tmp_disallowed, list) {
8216 if (bss == tmp) {
8217 dl_list_del(&tmp->list);
8218 os_free(tmp);
8219 wpa_set_driver_tmp_disallow_list(wpa_s);
8220 break;
8221 }
8222 }
8223}
8224
8225
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008226void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008227 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008228{
8229 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008230
8231 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8232 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008233 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008234 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008235 }
8236
8237 bss = os_malloc(sizeof(*bss));
8238 if (!bss) {
8239 wpa_printf(MSG_DEBUG,
8240 "Failed to allocate memory for temp disallow BSS");
8241 return;
8242 }
8243
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008244 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8245 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008246 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008247
8248finish:
8249 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008250 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8251 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008252}
8253
8254
Hai Shalom74f70d42019-02-11 14:42:39 -08008255int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8256 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008257{
Hai Shalom74f70d42019-02-11 14:42:39 -08008258 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008259
8260 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8261 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008262 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8263 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008264 break;
8265 }
8266 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008267 if (!disallowed)
8268 return 0;
8269
8270 if (disallowed->rssi_threshold != 0 &&
8271 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008272 return 0;
8273
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008274 return 1;
8275}
Hai Shalom81f62d82019-07-22 12:10:00 -07008276
8277
8278int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8279 unsigned int type, const u8 *addr,
8280 const u8 *mask)
8281{
8282 if ((addr && !mask) || (!addr && mask)) {
8283 wpa_printf(MSG_INFO,
8284 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8285 return -1;
8286 }
8287
8288 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8289 wpa_printf(MSG_INFO,
8290 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8291 return -1;
8292 }
8293
8294 if (type & MAC_ADDR_RAND_SCAN) {
8295 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8296 addr, mask))
8297 return -1;
8298 }
8299
8300 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8301 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8302 addr, mask))
8303 return -1;
8304
8305 if (wpa_s->sched_scanning && !wpa_s->pno)
8306 wpas_scan_restart_sched_scan(wpa_s);
8307 }
8308
8309 if (type & MAC_ADDR_RAND_PNO) {
8310 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8311 addr, mask))
8312 return -1;
8313
8314 if (wpa_s->pno) {
8315 wpas_stop_pno(wpa_s);
8316 wpas_start_pno(wpa_s);
8317 }
8318 }
8319
8320 return 0;
8321}
8322
8323
8324int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8325 unsigned int type)
8326{
8327 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8328 if (wpa_s->pno) {
8329 if (type & MAC_ADDR_RAND_PNO) {
8330 wpas_stop_pno(wpa_s);
8331 wpas_start_pno(wpa_s);
8332 }
8333 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8334 wpas_scan_restart_sched_scan(wpa_s);
8335 }
8336
8337 return 0;
8338}
Hai Shalomfdcde762020-04-02 11:19:20 -07008339
8340
8341int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8342 struct wpa_signal_info *si)
8343{
8344 int res;
8345
8346 if (!wpa_s->driver->signal_poll)
8347 return -1;
8348
8349 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8350
8351#ifdef CONFIG_TESTING_OPTIONS
8352 if (res == 0) {
8353 struct driver_signal_override *dso;
8354
8355 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8356 struct driver_signal_override, list) {
8357 if (os_memcmp(wpa_s->bssid, dso->bssid,
8358 ETH_ALEN) != 0)
8359 continue;
8360 wpa_printf(MSG_DEBUG,
8361 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8362 si->current_signal,
8363 dso->si_current_signal,
8364 si->avg_signal,
8365 dso->si_avg_signal,
8366 si->avg_beacon_signal,
8367 dso->si_avg_beacon_signal,
8368 si->current_noise,
8369 dso->si_current_noise);
8370 si->current_signal = dso->si_current_signal;
8371 si->avg_signal = dso->si_avg_signal;
8372 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8373 si->current_noise = dso->si_current_noise;
8374 break;
8375 }
8376 }
8377#endif /* CONFIG_TESTING_OPTIONS */
8378
8379 return res;
8380}
8381
8382
8383struct wpa_scan_results *
8384wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8385{
8386 struct wpa_scan_results *scan_res;
8387#ifdef CONFIG_TESTING_OPTIONS
8388 size_t idx;
8389#endif /* CONFIG_TESTING_OPTIONS */
8390
8391 if (!wpa_s->driver->get_scan_results2)
8392 return NULL;
8393
8394 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8395
8396#ifdef CONFIG_TESTING_OPTIONS
8397 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8398 struct driver_signal_override *dso;
8399 struct wpa_scan_res *res = scan_res->res[idx];
8400
8401 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8402 struct driver_signal_override, list) {
8403 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8404 continue;
8405 wpa_printf(MSG_DEBUG,
8406 "Override driver scan signal level %d->%d for "
8407 MACSTR,
8408 res->level, dso->scan_level,
8409 MAC2STR(res->bssid));
8410 res->flags |= WPA_SCAN_QUAL_INVALID;
8411 if (dso->scan_level < 0)
8412 res->flags |= WPA_SCAN_LEVEL_DBM;
8413 else
8414 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8415 res->level = dso->scan_level;
8416 break;
8417 }
8418 }
8419#endif /* CONFIG_TESTING_OPTIONS */
8420
8421 return scan_res;
8422}