blob: ffe162cb4fb5832ca0e8b0263ae4183a1d13ef58 [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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1020 state == WPA_ASSOCIATED) {
1021 wpa_s->new_connection = 1;
1022 wpa_drv_set_operstate(wpa_s, 0);
1023#ifndef IEEE8021X_EAPOL
1024 wpa_drv_set_supp_port(wpa_s, 0);
1025#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001026 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027 }
1028 wpa_s->wpa_state = state;
1029
1030#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001031 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1032 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001033 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 wpa_supplicant_stop_bgscan(wpa_s);
1035#endif /* CONFIG_BGSCAN */
1036
Hai Shalom5f92bc92019-04-18 11:54:11 -07001037 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001038 wpa_supplicant_stop_autoscan(wpa_s);
1039
1040 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1041 wpa_supplicant_start_autoscan(wpa_s);
1042
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001043 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1044 wmm_ac_notify_disassoc(wpa_s);
1045
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 if (wpa_s->wpa_state != old_state) {
1047 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1048
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001049 /*
1050 * Notify the P2P Device interface about a state change in one
1051 * of the interfaces.
1052 */
1053 wpas_p2p_indicate_state_change(wpa_s);
1054
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055 if (wpa_s->wpa_state == WPA_COMPLETED ||
1056 old_state == WPA_COMPLETED)
1057 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001058#ifdef CONFIG_DPP2
1059 if (wpa_s->wpa_state == WPA_COMPLETED)
1060 wpas_dpp_connected(wpa_s);
1061#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 }
Hai Shalomc3565922019-10-28 11:58:20 -07001063#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1064 if (update_fils_connect_params)
1065 wpas_update_fils_connect_params(wpa_s);
1066#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067}
1068
1069
1070void wpa_supplicant_terminate_proc(struct wpa_global *global)
1071{
1072 int pending = 0;
1073#ifdef CONFIG_WPS
1074 struct wpa_supplicant *wpa_s = global->ifaces;
1075 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001076 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001077 if (wpas_wps_terminate_pending(wpa_s) == 1)
1078 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001079#ifdef CONFIG_P2P
1080 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1081 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1082 wpas_p2p_disconnect(wpa_s);
1083#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001084 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085 }
1086#endif /* CONFIG_WPS */
1087 if (pending)
1088 return;
1089 eloop_terminate();
1090}
1091
1092
1093static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1094{
1095 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 wpa_supplicant_terminate_proc(global);
1097}
1098
1099
1100void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1101{
1102 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001103 enum wpa_states new_state;
1104
1105 if (old_state == WPA_SCANNING)
1106 new_state = WPA_SCANNING;
1107 else
1108 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001109
1110 wpa_s->pairwise_cipher = 0;
1111 wpa_s->group_cipher = 0;
1112 wpa_s->mgmt_group_cipher = 0;
1113 wpa_s->key_mgmt = 0;
1114 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001115 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116
1117 if (wpa_s->wpa_state != old_state)
1118 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1119}
1120
1121
1122/**
1123 * wpa_supplicant_reload_configuration - Reload configuration data
1124 * @wpa_s: Pointer to wpa_supplicant data
1125 * Returns: 0 on success or -1 if configuration parsing failed
1126 *
1127 * This function can be used to request that the configuration data is reloaded
1128 * (e.g., after configuration file change). This function is reloading
1129 * configuration only for one interface, so this may need to be called multiple
1130 * times if %wpa_supplicant is controlling multiple interfaces and all
1131 * interfaces need reconfiguration.
1132 */
1133int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1134{
1135 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 int reconf_ctrl;
1137 int old_ap_scan;
1138
1139 if (wpa_s->confname == NULL)
1140 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001141 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 if (conf == NULL) {
1143 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1144 "file '%s' - exiting", wpa_s->confname);
1145 return -1;
1146 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001147 if (wpa_s->confanother &&
1148 !wpa_config_read(wpa_s->confanother, conf)) {
1149 wpa_msg(wpa_s, MSG_ERROR,
1150 "Failed to parse the configuration file '%s' - exiting",
1151 wpa_s->confanother);
1152 return -1;
1153 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001154
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155 conf->changed_parameters = (unsigned int) -1;
1156
1157 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1158 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1159 os_strcmp(conf->ctrl_interface,
1160 wpa_s->conf->ctrl_interface) != 0);
1161
1162 if (reconf_ctrl && wpa_s->ctrl_iface) {
1163 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1164 wpa_s->ctrl_iface = NULL;
1165 }
1166
1167 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001169 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1170 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001171 wpa_supplicant_deauthenticate(wpa_s,
1172 WLAN_REASON_DEAUTH_LEAVING);
1173 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174
1175 /*
1176 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001177 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001178 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001179 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1180 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1181 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001182 /*
1183 * Clear forced success to clear EAP state for next
1184 * authentication.
1185 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001186 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001187 }
1188 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1189 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001190 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1192 rsn_preauth_deinit(wpa_s->wpa);
1193
1194 old_ap_scan = wpa_s->conf->ap_scan;
1195 wpa_config_free(wpa_s->conf);
1196 wpa_s->conf = conf;
1197 if (old_ap_scan != wpa_s->conf->ap_scan)
1198 wpas_notify_ap_scan_changed(wpa_s);
1199
1200 if (reconf_ctrl)
1201 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1202
1203 wpa_supplicant_update_config(wpa_s);
1204
1205 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001206 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 wpa_s->reassociate = 1;
1208 wpa_supplicant_req_scan(wpa_s, 0, 0);
1209 }
Hai Shalom60840252021-02-19 19:02:11 -08001210 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1212 return 0;
1213}
1214
1215
1216static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1217{
1218 struct wpa_global *global = signal_ctx;
1219 struct wpa_supplicant *wpa_s;
1220 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1221 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1222 sig);
1223 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1224 wpa_supplicant_terminate_proc(global);
1225 }
1226 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001227
1228 if (wpa_debug_reopen_file() < 0) {
1229 /* Ignore errors since we cannot really do much to fix this */
1230 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1231 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232}
1233
1234
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1236 struct wpa_ssid *ssid,
1237 struct wpa_ie_data *ie)
1238{
1239 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1240 if (ret) {
1241 if (ret == -2) {
1242 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1243 "from association info");
1244 }
1245 return -1;
1246 }
1247
1248 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1249 "cipher suites");
1250 if (!(ie->group_cipher & ssid->group_cipher)) {
1251 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1252 "cipher 0x%x (mask 0x%x) - reject",
1253 ie->group_cipher, ssid->group_cipher);
1254 return -1;
1255 }
1256 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1257 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1258 "cipher 0x%x (mask 0x%x) - reject",
1259 ie->pairwise_cipher, ssid->pairwise_cipher);
1260 return -1;
1261 }
1262 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1263 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1264 "management 0x%x (mask 0x%x) - reject",
1265 ie->key_mgmt, ssid->key_mgmt);
1266 return -1;
1267 }
1268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001269 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001270 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001271 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1272 "that does not support management frame protection - "
1273 "reject");
1274 return -1;
1275 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276
1277 return 0;
1278}
1279
1280
Hai Shalom021b0b52019-04-10 11:17:58 -07001281static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1282 int freq)
1283{
1284 if (!ie->has_group)
1285 ie->group_cipher = wpa_default_rsn_cipher(freq);
1286 if (!ie->has_pairwise)
1287 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1288 return (ie->group_cipher & ssid->group_cipher) &&
1289 (ie->pairwise_cipher & ssid->pairwise_cipher);
1290}
1291
1292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293/**
1294 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1295 * @wpa_s: Pointer to wpa_supplicant data
1296 * @bss: Scan results for the selected BSS, or %NULL if not available
1297 * @ssid: Configuration data for the selected network
1298 * @wpa_ie: Buffer for the WPA/RSN IE
1299 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1300 * used buffer length in case the functions returns success.
1301 * Returns: 0 on success or -1 on failure
1302 *
1303 * This function is used to configure authentication and encryption parameters
1304 * based on the network configuration and scan result for the selected BSS (if
1305 * available).
1306 */
1307int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1308 struct wpa_bss *bss, struct wpa_ssid *ssid,
1309 u8 *wpa_ie, size_t *wpa_ie_len)
1310{
1311 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001312 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001313 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001314
1315 if (bss) {
1316 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1317 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001318 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001319 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001320 } else {
1321 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1322 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323
1324 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1325 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001326 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 (ie.key_mgmt & ssid->key_mgmt)) {
1328 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1329 proto = WPA_PROTO_RSN;
1330 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001331 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332 (ie.group_cipher & ssid->group_cipher) &&
1333 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1334 (ie.key_mgmt & ssid->key_mgmt)) {
1335 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1336 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001337#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001338 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1339 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1340 (ie.group_cipher & ssid->group_cipher) &&
1341 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1342 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001343 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001344 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001345 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1346 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1347 (ie.group_cipher & ssid->group_cipher) &&
1348 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1349 (ie.key_mgmt & ssid->key_mgmt)) {
1350 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1351 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001352#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353 } else if (bss) {
1354 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001355 wpa_dbg(wpa_s, MSG_DEBUG,
1356 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1357 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1358 ssid->key_mgmt);
1359 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1360 MAC2STR(bss->bssid),
1361 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1362 bss_wpa ? " WPA" : "",
1363 bss_rsn ? " RSN" : "",
1364 bss_osen ? " OSEN" : "");
1365 if (bss_rsn) {
1366 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1367 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1368 wpa_dbg(wpa_s, MSG_DEBUG,
1369 "Could not parse RSN element");
1370 } else {
1371 wpa_dbg(wpa_s, MSG_DEBUG,
1372 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1373 ie.pairwise_cipher, ie.group_cipher,
1374 ie.key_mgmt);
1375 }
1376 }
1377 if (bss_wpa) {
1378 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1379 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1380 wpa_dbg(wpa_s, MSG_DEBUG,
1381 "Could not parse WPA element");
1382 } else {
1383 wpa_dbg(wpa_s, MSG_DEBUG,
1384 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1385 ie.pairwise_cipher, ie.group_cipher,
1386 ie.key_mgmt);
1387 }
1388 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 return -1;
1390 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001391 if (ssid->proto & WPA_PROTO_OSEN)
1392 proto = WPA_PROTO_OSEN;
1393 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001394 proto = WPA_PROTO_RSN;
1395 else
1396 proto = WPA_PROTO_WPA;
1397 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1398 os_memset(&ie, 0, sizeof(ie));
1399 ie.group_cipher = ssid->group_cipher;
1400 ie.pairwise_cipher = ssid->pairwise_cipher;
1401 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001402 ie.mgmt_group_cipher = 0;
1403 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1404 if (ssid->group_mgmt_cipher &
1405 WPA_CIPHER_BIP_GMAC_256)
1406 ie.mgmt_group_cipher =
1407 WPA_CIPHER_BIP_GMAC_256;
1408 else if (ssid->group_mgmt_cipher &
1409 WPA_CIPHER_BIP_CMAC_256)
1410 ie.mgmt_group_cipher =
1411 WPA_CIPHER_BIP_CMAC_256;
1412 else if (ssid->group_mgmt_cipher &
1413 WPA_CIPHER_BIP_GMAC_128)
1414 ie.mgmt_group_cipher =
1415 WPA_CIPHER_BIP_GMAC_128;
1416 else
1417 ie.mgmt_group_cipher =
1418 WPA_CIPHER_AES_128_CMAC;
1419 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001420#ifdef CONFIG_OWE
1421 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1422 !ssid->owe_only &&
1423 !bss_wpa && !bss_rsn && !bss_osen) {
1424 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1425 wpa_s->wpa_proto = 0;
1426 *wpa_ie_len = 0;
1427 return 0;
1428 }
1429#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1431 "based on configuration");
1432 } else
1433 proto = ie.proto;
1434 }
1435
1436 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1437 "pairwise %d key_mgmt %d proto %d",
1438 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439 if (ssid->ieee80211w) {
1440 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1441 ie.mgmt_group_cipher);
1442 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001443
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001444 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1446 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001447 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448
1449 if (bss || !wpa_s->ap_ies_from_associnfo) {
1450 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1451 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1452 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001453 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1454 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1455 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001456 return -1;
1457 }
1458
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001459#ifdef CONFIG_NO_WPA
1460 wpa_s->group_cipher = WPA_CIPHER_NONE;
1461 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1462#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001463 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001464 wpa_dbg(wpa_s, MSG_DEBUG,
1465 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1466 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001467 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1468 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001469 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1470 "cipher");
1471 return -1;
1472 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001473 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1474 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001475
1476 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001477 wpa_dbg(wpa_s, MSG_DEBUG,
1478 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1479 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001480 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1481 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1483 "cipher");
1484 return -1;
1485 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001486 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1487 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001488#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489
1490 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001491#ifdef CONFIG_SAE
1492 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1493 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1494#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001495#ifdef CONFIG_IEEE80211R
1496 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1497 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1498 sel &= ~WPA_KEY_MGMT_FT;
1499#endif /* CONFIG_IEEE80211R */
1500 wpa_dbg(wpa_s, MSG_DEBUG,
1501 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1502 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001503 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001504#ifdef CONFIG_IEEE80211R
1505#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001506 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1507 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001508 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1509 wpa_dbg(wpa_s, MSG_DEBUG,
1510 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001511 if (!ssid->ft_eap_pmksa_caching &&
1512 pmksa_cache_get_current(wpa_s->wpa)) {
1513 /* PMKSA caching with FT may have interoperability
1514 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001515 wpa_dbg(wpa_s, MSG_DEBUG,
1516 "WPA: Disable PMKSA caching for FT/802.1X connection");
1517 pmksa_cache_clear_current(wpa_s->wpa);
1518 }
1519#endif /* CONFIG_SHA384 */
1520#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001521#ifdef CONFIG_SUITEB192
1522 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1523 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1524 wpa_dbg(wpa_s, MSG_DEBUG,
1525 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1526#endif /* CONFIG_SUITEB192 */
1527#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001528 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1529 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1530 wpa_dbg(wpa_s, MSG_DEBUG,
1531 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001532#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001533#ifdef CONFIG_FILS
1534#ifdef CONFIG_IEEE80211R
1535 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1536 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1537 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1538 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1539 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1540 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1541#endif /* CONFIG_IEEE80211R */
1542 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1543 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1544 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1545 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1546 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1547 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1548#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001549#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001550 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1551 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1553 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001554 if (!ssid->ft_eap_pmksa_caching &&
1555 pmksa_cache_get_current(wpa_s->wpa)) {
1556 /* PMKSA caching with FT may have interoperability
1557 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001558 wpa_dbg(wpa_s, MSG_DEBUG,
1559 "WPA: Disable PMKSA caching for FT/802.1X connection");
1560 pmksa_cache_clear_current(wpa_s->wpa);
1561 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001562#endif /* CONFIG_IEEE80211R */
1563#ifdef CONFIG_DPP
1564 } else if (sel & WPA_KEY_MGMT_DPP) {
1565 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1566 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1567#endif /* CONFIG_DPP */
1568#ifdef CONFIG_SAE
1569 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1570 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1571 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1572 } else if (sel & WPA_KEY_MGMT_SAE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1575#endif /* CONFIG_SAE */
1576#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001577 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1578 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1579 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1580#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001581 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1583 wpa_dbg(wpa_s, MSG_DEBUG,
1584 "WPA: using KEY_MGMT 802.1X with SHA256");
1585 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1586 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1587 wpa_dbg(wpa_s, MSG_DEBUG,
1588 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1590 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1591 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1592 } else if (sel & WPA_KEY_MGMT_PSK) {
1593 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1594 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1595 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001598#ifdef CONFIG_HS20
1599 } else if (sel & WPA_KEY_MGMT_OSEN) {
1600 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1601 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1602#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001603#ifdef CONFIG_OWE
1604 } else if (sel & WPA_KEY_MGMT_OWE) {
1605 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1606 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1607#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001608 } else {
1609 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1610 "authenticated key management type");
1611 return -1;
1612 }
1613
1614 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1615 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1616 wpa_s->pairwise_cipher);
1617 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1618
Hai Shalomc3565922019-10-28 11:58:20 -07001619 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1620 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1621 wpa_msg(wpa_s, MSG_INFO,
1622 "RSN: Management frame protection required but the selected AP does not enable it");
1623 return -1;
1624 }
1625
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001626 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001627 if (ssid->group_mgmt_cipher)
1628 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001629 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1631 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001632 wpa_dbg(wpa_s, MSG_DEBUG,
1633 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1634 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 if (sel & WPA_CIPHER_AES_128_CMAC) {
1636 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1637 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1638 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001639 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1640 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1641 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1642 "BIP-GMAC-128");
1643 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1644 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1645 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1646 "BIP-GMAC-256");
1647 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1648 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1649 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1650 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001651 } else {
1652 wpa_s->mgmt_group_cipher = 0;
1653 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1654 }
1655 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1656 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001657 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001658 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001659#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001660 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1661 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1662 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001663#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001664 sae_pwe = wpa_s->conf->sae_pwe;
1665 if (ssid->sae_password_id && sae_pwe != 3)
1666 sae_pwe = 1;
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001668#ifdef CONFIG_SAE_PK
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1670 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1671 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1672 ((ssid->sae_password &&
1673 sae_pk_valid_password(ssid->sae_password)) ||
1674 (!ssid->sae_password && ssid->passphrase &&
1675 sae_pk_valid_password(ssid->passphrase))));
1676#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001677#ifdef CONFIG_TESTING_OPTIONS
1678 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1679 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001680 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1681 wpa_s->oci_freq_override_eapol);
1682 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1683 wpa_s->oci_freq_override_eapol_g2);
1684 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1685 wpa_s->oci_freq_override_ft_assoc);
1686 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1687 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001688#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001689
1690 /* Extended Key ID is only supported in infrastructure BSS so far */
1691 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1692 (ssid->proto & WPA_PROTO_RSN) &&
1693 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1694 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1695 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1696 int use_ext_key_id = 0;
1697
1698 wpa_msg(wpa_s, MSG_DEBUG,
1699 "WPA: Enable Extended Key ID support");
1700 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1701 wpa_s->conf->extended_key_id);
1702 if (bss_rsn &&
1703 wpa_s->conf->extended_key_id &&
1704 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1705 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1706 use_ext_key_id = 1;
1707 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1708 use_ext_key_id);
1709 } else {
1710 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1711 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1712 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001713
1714 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1715 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1716 return -1;
1717 }
1718
Hai Shalomc3565922019-10-28 11:58:20 -07001719 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1720 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1721 &wpa_s->rsnxe_len)) {
1722 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1723 return -1;
1724 }
1725
Hai Shalom021b0b52019-04-10 11:17:58 -07001726 if (0) {
1727#ifdef CONFIG_DPP
1728 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1729 /* Use PMK from DPP network introduction (PMKSA entry) */
1730 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001731#ifdef CONFIG_DPP2
1732 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1733#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001734#endif /* CONFIG_DPP */
1735 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001736 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001737 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001738
Roshan Pius3a1667e2018-07-03 15:17:14 -07001739 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1740 WPA_KEY_MGMT_FT_PSK |
1741 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1742
1743 if (ssid->psk_set && !sae_only) {
1744 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1745 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001746 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1747 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001748 psk_set = 1;
1749 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001750
Roshan Pius3a1667e2018-07-03 15:17:14 -07001751 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1752 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001753 psk_set = 1;
1754
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001755#ifndef CONFIG_NO_PBKDF2
1756 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001757 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001758 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001759 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1760 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001761 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1762 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001763 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001764 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001765 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001766 }
1767#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001768#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001769 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001770 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1771 ssid->ext_psk);
1772 char pw_str[64 + 1];
1773 u8 psk[PMK_LEN];
1774
1775 if (pw == NULL) {
1776 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1777 "found from external storage");
1778 return -1;
1779 }
1780
1781 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1782 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1783 "PSK length %d in external storage",
1784 (int) wpabuf_len(pw));
1785 ext_password_free(pw);
1786 return -1;
1787 }
1788
1789 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1790 pw_str[wpabuf_len(pw)] = '\0';
1791
1792#ifndef CONFIG_NO_PBKDF2
1793 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1794 {
1795 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1796 4096, psk, PMK_LEN);
1797 os_memset(pw_str, 0, sizeof(pw_str));
1798 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1799 "external passphrase)",
1800 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001801 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1802 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001803 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001804 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001805 } else
1806#endif /* CONFIG_NO_PBKDF2 */
1807 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1808 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1809 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1810 "Invalid PSK hex string");
1811 os_memset(pw_str, 0, sizeof(pw_str));
1812 ext_password_free(pw);
1813 return -1;
1814 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001815 wpa_hexdump_key(MSG_MSGDUMP,
1816 "PSK (from external PSK)",
1817 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001818 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1819 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001820 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001821 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001822 } else {
1823 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1824 "PSK available");
1825 os_memset(pw_str, 0, sizeof(pw_str));
1826 ext_password_free(pw);
1827 return -1;
1828 }
1829
1830 os_memset(pw_str, 0, sizeof(pw_str));
1831 ext_password_free(pw);
1832 }
1833#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001834
1835 if (!psk_set) {
1836 wpa_msg(wpa_s, MSG_INFO,
1837 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001838 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001839 return -1;
1840 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001841#ifdef CONFIG_OWE
1842 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1843 /* OWE Diffie-Hellman exchange in (Re)Association
1844 * Request/Response frames set the PMK, so do not override it
1845 * here. */
1846#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001847 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1849
Hai Shalomfdcde762020-04-02 11:19:20 -07001850 if (ssid->mode != WPAS_MODE_IBSS &&
1851 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1852 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1853 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1854 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1855 wpa_msg(wpa_s, MSG_INFO,
1856 "Disable PTK0 rekey support - replaced with reconnect");
1857 wpa_s->deny_ptk0_rekey = 1;
1858 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1859 } else {
1860 wpa_s->deny_ptk0_rekey = 0;
1861 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1862 }
1863
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864 return 0;
1865}
1866
1867
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001868static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1869{
1870 *pos = 0x00;
1871
1872 switch (idx) {
1873 case 0: /* Bits 0-7 */
1874 break;
1875 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001876 if (wpa_s->conf->coloc_intf_reporting) {
1877 /* Bit 13 - Collocated Interference Reporting */
1878 *pos |= 0x20;
1879 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001880 break;
1881 case 2: /* Bits 16-23 */
1882#ifdef CONFIG_WNM
1883 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001884 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001885 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001886#endif /* CONFIG_WNM */
1887 break;
1888 case 3: /* Bits 24-31 */
1889#ifdef CONFIG_WNM
1890 *pos |= 0x02; /* Bit 25 - SSID List */
1891#endif /* CONFIG_WNM */
1892#ifdef CONFIG_INTERWORKING
1893 if (wpa_s->conf->interworking)
1894 *pos |= 0x80; /* Bit 31 - Interworking */
1895#endif /* CONFIG_INTERWORKING */
1896 break;
1897 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001898#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001899 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001900 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001901#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001902 break;
1903 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001904#ifdef CONFIG_HS20
1905 if (wpa_s->conf->hs20)
1906 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1907#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001908#ifdef CONFIG_MBO
1909 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1910#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001911 break;
1912 case 6: /* Bits 48-55 */
1913 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001914 case 7: /* Bits 56-63 */
1915 break;
1916 case 8: /* Bits 64-71 */
1917 if (wpa_s->conf->ftm_responder)
1918 *pos |= 0x40; /* Bit 70 - FTM responder */
1919 if (wpa_s->conf->ftm_initiator)
1920 *pos |= 0x80; /* Bit 71 - FTM initiator */
1921 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001922 case 9: /* Bits 72-79 */
1923#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001924 if (!wpa_s->disable_fils)
1925 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001926#endif /* CONFIG_FILS */
1927 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001928 case 10: /* Bits 80-87 */
1929 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
1930 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001931 }
1932}
1933
1934
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001935int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001936{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001937 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001938 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001939
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001940 if (len < wpa_s->extended_capa_len)
1941 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001942 if (buflen < (size_t) len + 2) {
1943 wpa_printf(MSG_INFO,
1944 "Not enough room for building extended capabilities element");
1945 return -1;
1946 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001947
1948 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001949 *pos++ = len;
1950 for (i = 0; i < len; i++, pos++) {
1951 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001952
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001953 if (i < wpa_s->extended_capa_len) {
1954 *pos &= ~wpa_s->extended_capa_mask[i];
1955 *pos |= wpa_s->extended_capa[i];
1956 }
1957 }
1958
1959 while (len > 0 && buf[1 + len] == 0) {
1960 len--;
1961 buf[1] = len;
1962 }
1963 if (len == 0)
1964 return 0;
1965
1966 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001967}
1968
1969
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001970static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1971 struct wpa_bss *test_bss)
1972{
1973 struct wpa_bss *bss;
1974
1975 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1976 if (bss == test_bss)
1977 return 1;
1978 }
1979
1980 return 0;
1981}
1982
1983
1984static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1985 struct wpa_ssid *test_ssid)
1986{
1987 struct wpa_ssid *ssid;
1988
1989 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1990 if (ssid == test_ssid)
1991 return 1;
1992 }
1993
1994 return 0;
1995}
1996
1997
1998int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1999 struct wpa_ssid *test_ssid)
2000{
2001 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2002 return 0;
2003
2004 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2005}
2006
2007
2008void wpas_connect_work_free(struct wpa_connect_work *cwork)
2009{
2010 if (cwork == NULL)
2011 return;
2012 os_free(cwork);
2013}
2014
2015
2016void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2017{
2018 struct wpa_connect_work *cwork;
2019 struct wpa_radio_work *work = wpa_s->connect_work;
2020
2021 if (!work)
2022 return;
2023
2024 wpa_s->connect_work = NULL;
2025 cwork = work->ctx;
2026 work->ctx = NULL;
2027 wpas_connect_work_free(cwork);
2028 radio_work_done(work);
2029}
2030
2031
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002032int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2033{
2034 struct os_reltime now;
2035 u8 addr[ETH_ALEN];
2036
2037 os_get_reltime(&now);
2038 if (wpa_s->last_mac_addr_style == style &&
2039 wpa_s->last_mac_addr_change.sec != 0 &&
2040 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2041 wpa_s->conf->rand_addr_lifetime)) {
2042 wpa_msg(wpa_s, MSG_DEBUG,
2043 "Previously selected random MAC address has not yet expired");
2044 return 0;
2045 }
2046
2047 switch (style) {
2048 case 1:
2049 if (random_mac_addr(addr) < 0)
2050 return -1;
2051 break;
2052 case 2:
2053 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2054 if (random_mac_addr_keep_oui(addr) < 0)
2055 return -1;
2056 break;
2057 default:
2058 return -1;
2059 }
2060
2061 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2062 wpa_msg(wpa_s, MSG_INFO,
2063 "Failed to set random MAC address");
2064 return -1;
2065 }
2066
2067 os_get_reltime(&wpa_s->last_mac_addr_change);
2068 wpa_s->mac_addr_changed = 1;
2069 wpa_s->last_mac_addr_style = style;
2070
2071 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2072 wpa_msg(wpa_s, MSG_INFO,
2073 "Could not update MAC address information");
2074 return -1;
2075 }
2076
2077 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2078 MAC2STR(addr));
2079
2080 return 0;
2081}
2082
2083
2084int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2085{
2086 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2087 !wpa_s->conf->preassoc_mac_addr)
2088 return 0;
2089
2090 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2091}
2092
2093
Hai Shalomc3565922019-10-28 11:58:20 -07002094static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2095{
2096#ifdef CONFIG_SAE
2097 int *groups = conf->sae_groups;
2098 int default_groups[] = { 19, 20, 21, 0 };
2099 const char *password;
2100
2101 if (!groups || groups[0] <= 0)
2102 groups = default_groups;
2103
2104 password = ssid->sae_password;
2105 if (!password)
2106 password = ssid->passphrase;
2107
Hai Shalom899fcc72020-10-19 14:38:18 -07002108 if (!password ||
2109 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2110 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002111 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002112 /* PT derivation not needed */
2113 sae_deinit_pt(ssid->pt);
2114 ssid->pt = NULL;
2115 return;
2116 }
2117
2118 if (ssid->pt)
2119 return; /* PT already derived */
2120 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2121 (const u8 *) password, os_strlen(password),
2122 ssid->sae_password_id);
2123#endif /* CONFIG_SAE */
2124}
2125
2126
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002127static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2128{
2129#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2130 os_free(wpa_s->sme.sae_rejected_groups);
2131 wpa_s->sme.sae_rejected_groups = NULL;
2132#ifdef CONFIG_TESTING_OPTIONS
2133 if (wpa_s->extra_sae_rejected_groups) {
2134 int i, *groups = wpa_s->extra_sae_rejected_groups;
2135
2136 for (i = 0; groups[i]; i++) {
2137 wpa_printf(MSG_DEBUG,
2138 "TESTING: Indicate rejection of an extra SAE group %d",
2139 groups[i]);
2140 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2141 groups[i]);
2142 }
2143 }
2144#endif /* CONFIG_TESTING_OPTIONS */
2145#endif /* CONFIG_SAE && CONFIG_SME */
2146}
2147
2148
Hai Shalom60840252021-02-19 19:02:11 -08002149int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2150{
2151 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2152 wpa_msg(wpa_s, MSG_INFO,
2153 "Could not restore permanent MAC address");
2154 return -1;
2155 }
2156 wpa_s->mac_addr_changed = 0;
2157 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2158 wpa_msg(wpa_s, MSG_INFO,
2159 "Could not update MAC address information");
2160 return -1;
2161 }
2162 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2163 return 0;
2164}
2165
2166
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002167static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169/**
2170 * wpa_supplicant_associate - Request association
2171 * @wpa_s: Pointer to wpa_supplicant data
2172 * @bss: Scan results for the selected BSS, or %NULL if not available
2173 * @ssid: Configuration data for the selected network
2174 *
2175 * This function is used to request %wpa_supplicant to associate with a BSS.
2176 */
2177void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2178 struct wpa_bss *bss, struct wpa_ssid *ssid)
2179{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002180 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002181 int rand_style;
2182
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002183 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002184 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002185
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002186 /*
2187 * If we are starting a new connection, any previously pending EAPOL
2188 * RX cannot be valid anymore.
2189 */
2190 wpabuf_free(wpa_s->pending_eapol_rx);
2191 wpa_s->pending_eapol_rx = NULL;
2192
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002193 if (ssid->mac_addr == -1)
2194 rand_style = wpa_s->conf->mac_addr;
2195 else
2196 rand_style = ssid->mac_addr;
2197
Hai Shalomfdcde762020-04-02 11:19:20 -07002198 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002199 wmm_ac_clear_saved_tspecs(wpa_s);
2200 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002201 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002202#ifdef CONFIG_TESTING_OPTIONS
2203 wpa_s->testing_resend_assoc = 0;
2204#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002205
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002206 if (wpa_s->last_ssid == ssid) {
2207 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002208 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002209 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2210 wmm_ac_save_tspecs(wpa_s);
2211 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002212 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2213 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002214 }
Hai Shalomc3565922019-10-28 11:58:20 -07002215 } else {
2216#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002217 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002218 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2219#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002220 }
2221
2222 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002223 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2224 return;
2225 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002226 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002227 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002228 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002229 }
2230 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231
2232#ifdef CONFIG_IBSS_RSN
2233 ibss_rsn_deinit(wpa_s->ibss_rsn);
2234 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002235#else /* CONFIG_IBSS_RSN */
2236 if (ssid->mode == WPAS_MODE_IBSS &&
2237 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2238 wpa_msg(wpa_s, MSG_INFO,
2239 "IBSS RSN not supported in the build");
2240 return;
2241 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002242#endif /* CONFIG_IBSS_RSN */
2243
2244 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2245 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2246#ifdef CONFIG_AP
2247 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2248 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2249 "mode");
2250 return;
2251 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002252 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2253 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002254 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2255 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002256 return;
2257 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 wpa_s->current_bss = bss;
2259#else /* CONFIG_AP */
2260 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2261 "the build");
2262#endif /* CONFIG_AP */
2263 return;
2264 }
2265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002266 if (ssid->mode == WPAS_MODE_MESH) {
2267#ifdef CONFIG_MESH
2268 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2269 wpa_msg(wpa_s, MSG_INFO,
2270 "Driver does not support mesh mode");
2271 return;
2272 }
2273 if (bss)
2274 ssid->frequency = bss->freq;
2275 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2276 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2277 return;
2278 }
2279 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002280#else /* CONFIG_MESH */
2281 wpa_msg(wpa_s, MSG_ERROR,
2282 "mesh mode support not included in the build");
2283#endif /* CONFIG_MESH */
2284 return;
2285 }
2286
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002287 /*
2288 * Set WPA state machine configuration to match the selected network now
2289 * so that the information is available before wpas_start_assoc_cb()
2290 * gets called. This is needed at least for RSN pre-authentication where
2291 * candidate APs are added to a list based on scan result processing
2292 * before completion of the first association.
2293 */
2294 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2295
2296#ifdef CONFIG_DPP
2297 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2298 return;
2299#endif /* CONFIG_DPP */
2300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301#ifdef CONFIG_TDLS
2302 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002303 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304#endif /* CONFIG_TDLS */
2305
Hai Shalomc3565922019-10-28 11:58:20 -07002306#ifdef CONFIG_MBO
2307 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2308#endif /* CONFIG_MBO */
2309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002311 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 sme_authenticate(wpa_s, bss, ssid);
2313 return;
2314 }
2315
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002316 if (wpa_s->connect_work) {
2317 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2318 return;
2319 }
2320
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002321 if (radio_work_pending(wpa_s, "connect")) {
2322 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2323 return;
2324 }
2325
Dmitry Shmidt29333592017-01-09 12:27:11 -08002326#ifdef CONFIG_SME
2327 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2328 /* Clear possibly set auth_alg, if any, from last attempt. */
2329 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2330 }
2331#endif /* CONFIG_SME */
2332
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002333 wpas_abort_ongoing_scan(wpa_s);
2334
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002335 cwork = os_zalloc(sizeof(*cwork));
2336 if (cwork == NULL)
2337 return;
2338
2339 cwork->bss = bss;
2340 cwork->ssid = ssid;
2341
2342 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2343 wpas_start_assoc_cb, cwork) < 0) {
2344 os_free(cwork);
2345 }
2346}
2347
2348
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002349static int bss_is_ibss(struct wpa_bss *bss)
2350{
2351 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2352 IEEE80211_CAP_IBSS;
2353}
2354
2355
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002356static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2357 const struct wpa_ssid *ssid)
2358{
2359 enum hostapd_hw_mode hw_mode;
2360 struct hostapd_hw_modes *mode = NULL;
2361 u8 channel;
2362 int i;
2363
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002364 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2365 if (hw_mode == NUM_HOSTAPD_MODES)
2366 return 0;
2367 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2368 if (wpa_s->hw.modes[i].mode == hw_mode) {
2369 mode = &wpa_s->hw.modes[i];
2370 break;
2371 }
2372 }
2373
2374 if (!mode)
2375 return 0;
2376
2377 return mode->vht_capab != 0;
2378}
2379
2380
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002381void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2382 const struct wpa_ssid *ssid,
2383 struct hostapd_freq_params *freq)
2384{
Hai Shalom81f62d82019-07-22 12:10:00 -07002385 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002386 enum hostapd_hw_mode hw_mode;
2387 struct hostapd_hw_modes *mode = NULL;
2388 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2389 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002390 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002391 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2392 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002393 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002394 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002395 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002396 int chwidth, seg0, seg1;
2397 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002398 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002399
2400 freq->freq = ssid->frequency;
2401
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002402 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2403 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2404
2405 if (ssid->mode != WPAS_MODE_IBSS)
2406 break;
2407
2408 /* Don't adjust control freq in case of fixed_freq */
2409 if (ssid->fixed_freq)
2410 break;
2411
2412 if (!bss_is_ibss(bss))
2413 continue;
2414
2415 if (ssid->ssid_len == bss->ssid_len &&
2416 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2417 wpa_printf(MSG_DEBUG,
2418 "IBSS already found in scan results, adjust control freq: %d",
2419 bss->freq);
2420 freq->freq = bss->freq;
2421 obss_scan = 0;
2422 break;
2423 }
2424 }
2425
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002426 /* For IBSS check HT_IBSS flag */
2427 if (ssid->mode == WPAS_MODE_IBSS &&
2428 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2429 return;
2430
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002431 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2432 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2433 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2434 wpa_printf(MSG_DEBUG,
2435 "IBSS: WEP/TKIP detected, do not try to enable HT");
2436 return;
2437 }
2438
2439 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002440 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2441 if (wpa_s->hw.modes[i].mode == hw_mode) {
2442 mode = &wpa_s->hw.modes[i];
2443 break;
2444 }
2445 }
2446
2447 if (!mode)
2448 return;
2449
Hai Shalom60840252021-02-19 19:02:11 -08002450 freq->channel = channel;
2451
Hai Shalomc3565922019-10-28 11:58:20 -07002452 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2453 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002454
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002455#ifdef CONFIG_HT_OVERRIDES
2456 if (ssid->disable_ht) {
2457 freq->ht_enabled = 0;
2458 return;
2459 }
2460#endif /* CONFIG_HT_OVERRIDES */
2461
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002462 freq->ht_enabled = ht_supported(mode);
2463 if (!freq->ht_enabled)
2464 return;
2465
Hai Shalomc3565922019-10-28 11:58:20 -07002466 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2467 if (is_24ghz)
2468 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002469#ifdef CONFIG_HE_OVERRIDES
2470 if (is_24ghz && ssid->disable_he)
2471 freq->he_enabled = 0;
2472#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002473
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474 /* Setup higher BW only for 5 GHz */
2475 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2476 return;
2477
2478 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2479 pri_chan = &mode->channels[chan_idx];
2480 if (pri_chan->chan == channel)
2481 break;
2482 pri_chan = NULL;
2483 }
2484 if (!pri_chan)
2485 return;
2486
2487 /* Check primary channel flags */
2488 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2489 return;
2490
Hai Shalom74f70d42019-02-11 14:42:39 -08002491 freq->channel = pri_chan->chan;
2492
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002493#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002494 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002495#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002496 if (ssid->disable_vht)
2497 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002498#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002499 goto skip_ht40;
2500 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002501#endif /* CONFIG_HT_OVERRIDES */
2502
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002503 /* Check/setup HT40+/HT40- */
2504 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2505 if (ht40plus[j] == channel) {
2506 ht40 = 1;
2507 break;
2508 }
2509 }
2510
2511 /* Find secondary channel */
2512 for (i = 0; i < mode->num_channels; i++) {
2513 sec_chan = &mode->channels[i];
2514 if (sec_chan->chan == channel + ht40 * 4)
2515 break;
2516 sec_chan = NULL;
2517 }
2518 if (!sec_chan)
2519 return;
2520
2521 /* Check secondary channel flags */
2522 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2523 return;
2524
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002525 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002526 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2527 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002528 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002529 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2530 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002531 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002532 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002533
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002534 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002535 struct wpa_scan_results *scan_res;
2536
2537 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2538 if (scan_res == NULL) {
2539 /* Back to HT20 */
2540 freq->sec_channel_offset = 0;
2541 return;
2542 }
2543
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002544 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002545 switch (res) {
2546 case 0:
2547 /* Back to HT20 */
2548 freq->sec_channel_offset = 0;
2549 break;
2550 case 1:
2551 /* Configuration allowed */
2552 break;
2553 case 2:
2554 /* Switch pri/sec channels */
2555 freq->freq = hw_get_freq(mode, sec_chan->chan);
2556 freq->sec_channel_offset = -freq->sec_channel_offset;
2557 freq->channel = sec_chan->chan;
2558 break;
2559 default:
2560 freq->sec_channel_offset = 0;
2561 break;
2562 }
2563
2564 wpa_scan_results_free(scan_res);
2565 }
2566
Hai Shalom74f70d42019-02-11 14:42:39 -08002567#ifdef CONFIG_HT_OVERRIDES
2568skip_ht40:
2569#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002570 wpa_printf(MSG_DEBUG,
2571 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2572 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002573
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002574 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002575 return;
2576
2577 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002578 if (ssid->mode == WPAS_MODE_IBSS &&
2579 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002580 return;
2581
2582 vht_freq = *freq;
2583
Paul Stewart092955c2017-02-06 09:13:09 -08002584#ifdef CONFIG_VHT_OVERRIDES
2585 if (ssid->disable_vht) {
2586 freq->vht_enabled = 0;
2587 return;
2588 }
2589#endif /* CONFIG_VHT_OVERRIDES */
2590
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002591 vht_freq.vht_enabled = vht_supported(mode);
2592 if (!vht_freq.vht_enabled)
2593 return;
2594
Hai Shalomfdcde762020-04-02 11:19:20 -07002595 /* Enable HE with VHT for 5 GHz */
2596 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002597
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002598 /* setup center_freq1, bandwidth */
2599 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2600 if (freq->channel >= vht80[j] &&
2601 freq->channel < vht80[j] + 16)
2602 break;
2603 }
2604
2605 if (j == ARRAY_SIZE(vht80))
2606 return;
2607
2608 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2609 struct hostapd_channel_data *chan;
2610
2611 chan = hw_get_channel_chan(mode, i, NULL);
2612 if (!chan)
2613 return;
2614
2615 /* Back to HT configuration if channel not usable */
2616 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2617 return;
2618 }
2619
Hai Shalom81f62d82019-07-22 12:10:00 -07002620 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002621 seg0 = vht80[j] + 6;
2622 seg1 = 0;
2623
Hai Shalom81f62d82019-07-22 12:10:00 -07002624 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002625 /* setup center_freq2, bandwidth */
2626 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2627 /* Only accept 80 MHz segments separated by a gap */
2628 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2629 continue;
2630 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2631 struct hostapd_channel_data *chan;
2632
2633 chan = hw_get_channel_chan(mode, i, NULL);
2634 if (!chan)
2635 continue;
2636
2637 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2638 HOSTAPD_CHAN_NO_IR |
2639 HOSTAPD_CHAN_RADAR))
2640 continue;
2641
2642 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002643 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002644 vht_caps |=
2645 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2646 seg1 = vht80[k] + 6;
2647 }
2648
Hai Shalom81f62d82019-07-22 12:10:00 -07002649 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002650 break;
2651 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002652 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002653 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002654 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002655 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2656 seg0 = 50;
2657 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002658 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002659 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2660 seg0 = 114;
2661 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002662 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2663 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002664 seg0 = vht80[j] + 2;
2665#ifdef CONFIG_HT_OVERRIDES
2666 if (ssid->disable_ht40)
2667 seg0 = 0;
2668#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002669 }
2670
Hai Shalomfdcde762020-04-02 11:19:20 -07002671#ifdef CONFIG_HE_OVERRIDES
2672 if (ssid->disable_he) {
2673 vht_freq.he_enabled = 0;
2674 freq->he_enabled = 0;
2675 }
2676#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002677 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002678 freq->channel, ssid->enable_edmg,
2679 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002680 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002681 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002682 chwidth, seg0, seg1, vht_caps,
2683 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002684 return;
2685
2686 *freq = vht_freq;
2687
2688 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2689 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002690}
2691
2692
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002693#ifdef CONFIG_FILS
2694static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2695 size_t ie_buf_len)
2696{
2697 struct fils_hlp_req *req;
2698 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2699 const u8 *pos;
2700 u8 *buf = ie_buf;
2701
2702 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2703 list) {
2704 rem_len = ie_buf_len - ie_len;
2705 pos = wpabuf_head(req->pkt);
2706 hdr_len = 1 + 2 * ETH_ALEN + 6;
2707 hlp_len = wpabuf_len(req->pkt);
2708
2709 if (rem_len < 2 + hdr_len + hlp_len) {
2710 wpa_printf(MSG_ERROR,
2711 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2712 (unsigned long) rem_len,
2713 (unsigned long) (2 + hdr_len + hlp_len));
2714 break;
2715 }
2716
2717 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2718 /* Element ID */
2719 *buf++ = WLAN_EID_EXTENSION;
2720 /* Length */
2721 *buf++ = len;
2722 /* Element ID Extension */
2723 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2724 /* Destination MAC address */
2725 os_memcpy(buf, req->dst, ETH_ALEN);
2726 buf += ETH_ALEN;
2727 /* Source MAC address */
2728 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2729 buf += ETH_ALEN;
2730 /* LLC/SNAP Header */
2731 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2732 buf += 6;
2733 /* HLP Packet */
2734 os_memcpy(buf, pos, len - hdr_len);
2735 buf += len - hdr_len;
2736 pos += len - hdr_len;
2737
2738 hlp_len -= len - hdr_len;
2739 ie_len += 2 + len;
2740 rem_len -= 2 + len;
2741
2742 while (hlp_len) {
2743 len = (hlp_len > 255) ? 255 : hlp_len;
2744 if (rem_len < 2 + len)
2745 break;
2746 *buf++ = WLAN_EID_FRAGMENT;
2747 *buf++ = len;
2748 os_memcpy(buf, pos, len);
2749 buf += len;
2750 pos += len;
2751
2752 hlp_len -= len;
2753 ie_len += 2 + len;
2754 rem_len -= 2 + len;
2755 }
2756 }
2757
2758 return ie_len;
2759}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002760
2761
2762int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2763{
2764 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2765 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2766 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2767 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2768}
2769
2770
2771int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2772{
2773#ifdef CONFIG_FILS_SK_PFS
2774 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2775 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2776#else /* CONFIG_FILS_SK_PFS */
2777 return 0;
2778#endif /* CONFIG_FILS_SK_PFS */
2779}
2780
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002781#endif /* CONFIG_FILS */
2782
2783
2784static u8 * wpas_populate_assoc_ies(
2785 struct wpa_supplicant *wpa_s,
2786 struct wpa_bss *bss, struct wpa_ssid *ssid,
2787 struct wpa_driver_associate_params *params,
2788 enum wpa_drv_update_connect_params_mask *mask)
2789{
2790 u8 *wpa_ie;
2791 size_t max_wpa_ie_len = 500;
2792 size_t wpa_ie_len;
2793 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002794#ifdef CONFIG_MBO
2795 const u8 *mbo_ie;
2796#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302797#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2798 int pmksa_cached = 0;
2799#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002800#ifdef CONFIG_FILS
2801 const u8 *realm, *username, *rrk;
2802 size_t realm_len, username_len, rrk_len;
2803 u16 next_seq_num;
2804 struct fils_hlp_req *req;
2805
2806 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2807 list) {
2808 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2809 2 + 2 * wpabuf_len(req->pkt) / 255;
2810 }
2811#endif /* CONFIG_FILS */
2812
2813 wpa_ie = os_malloc(max_wpa_ie_len);
2814 if (!wpa_ie) {
2815 wpa_printf(MSG_ERROR,
2816 "Failed to allocate connect IE buffer for %lu bytes",
2817 (unsigned long) max_wpa_ie_len);
2818 return NULL;
2819 }
2820
2821 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2822 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2823 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2824 int try_opportunistic;
2825 const u8 *cache_id = NULL;
2826
2827 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2828 wpa_s->conf->okc :
2829 ssid->proactive_key_caching) &&
2830 (ssid->proto & WPA_PROTO_RSN);
2831#ifdef CONFIG_FILS
2832 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2833 cache_id = wpa_bss_get_fils_cache_id(bss);
2834#endif /* CONFIG_FILS */
2835 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2836 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002837 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002838 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302839#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2840 pmksa_cached = 1;
2841#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002842 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002843 wpa_ie_len = max_wpa_ie_len;
2844 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2845 wpa_ie, &wpa_ie_len)) {
2846 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2847 "key management and encryption suites");
2848 os_free(wpa_ie);
2849 return NULL;
2850 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002851#ifdef CONFIG_HS20
2852 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2853 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2854 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2855 wpa_ie_len = max_wpa_ie_len;
2856 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2857 wpa_ie, &wpa_ie_len)) {
2858 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2859 "key management and encryption suites");
2860 os_free(wpa_ie);
2861 return NULL;
2862 }
2863#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002864 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2865 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2866 /*
2867 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2868 * use non-WPA since the scan results did not indicate that the
2869 * AP is using WPA or WPA2.
2870 */
2871 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2872 wpa_ie_len = 0;
2873 wpa_s->wpa_proto = 0;
2874 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2875 wpa_ie_len = max_wpa_ie_len;
2876 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2877 wpa_ie, &wpa_ie_len)) {
2878 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2879 "key management and encryption suites (no "
2880 "scan results)");
2881 os_free(wpa_ie);
2882 return NULL;
2883 }
2884#ifdef CONFIG_WPS
2885 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2886 struct wpabuf *wps_ie;
2887 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2888 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2889 wpa_ie_len = wpabuf_len(wps_ie);
2890 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2891 } else
2892 wpa_ie_len = 0;
2893 wpabuf_free(wps_ie);
2894 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2895 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2896 params->wps = WPS_MODE_PRIVACY;
2897 else
2898 params->wps = WPS_MODE_OPEN;
2899 wpa_s->wpa_proto = 0;
2900#endif /* CONFIG_WPS */
2901 } else {
2902 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2903 wpa_ie_len = 0;
2904 wpa_s->wpa_proto = 0;
2905 }
2906
2907#ifdef IEEE8021X_EAPOL
2908 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2909 if (ssid->leap) {
2910 if (ssid->non_leap == 0)
2911 algs = WPA_AUTH_ALG_LEAP;
2912 else
2913 algs |= WPA_AUTH_ALG_LEAP;
2914 }
2915 }
2916
2917#ifdef CONFIG_FILS
2918 /* Clear FILS association */
2919 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2920
2921 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2922 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2923 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2924 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002925 &next_seq_num, &rrk, &rrk_len) == 0 &&
2926 (!wpa_s->last_con_fail_realm ||
2927 wpa_s->last_con_fail_realm_len != realm_len ||
2928 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002929 algs = WPA_AUTH_ALG_FILS;
2930 params->fils_erp_username = username;
2931 params->fils_erp_username_len = username_len;
2932 params->fils_erp_realm = realm;
2933 params->fils_erp_realm_len = realm_len;
2934 params->fils_erp_next_seq_num = next_seq_num;
2935 params->fils_erp_rrk = rrk;
2936 params->fils_erp_rrk_len = rrk_len;
2937
2938 if (mask)
2939 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302940 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2941 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2942 pmksa_cached) {
2943 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002944 }
2945#endif /* CONFIG_FILS */
2946#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002947#ifdef CONFIG_SAE
2948 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2949 algs = WPA_AUTH_ALG_SAE;
2950#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002951
2952 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2953 if (ssid->auth_alg) {
2954 algs = ssid->auth_alg;
2955 wpa_dbg(wpa_s, MSG_DEBUG,
2956 "Overriding auth_alg selection: 0x%x", algs);
2957 }
2958
Hai Shalom5f92bc92019-04-18 11:54:11 -07002959#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302960 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002961 wpa_dbg(wpa_s, MSG_DEBUG,
2962 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2963 algs = WPA_AUTH_ALG_OPEN;
2964 }
2965#endif /* CONFIG_SAE */
2966
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002967#ifdef CONFIG_P2P
2968 if (wpa_s->global->p2p) {
2969 u8 *pos;
2970 size_t len;
2971 int res;
2972 pos = wpa_ie + wpa_ie_len;
2973 len = max_wpa_ie_len - wpa_ie_len;
2974 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2975 ssid->p2p_group);
2976 if (res >= 0)
2977 wpa_ie_len += res;
2978 }
2979
2980 wpa_s->cross_connect_disallowed = 0;
2981 if (bss) {
2982 struct wpabuf *p2p;
2983 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2984 if (p2p) {
2985 wpa_s->cross_connect_disallowed =
2986 p2p_get_cross_connect_disallowed(p2p);
2987 wpabuf_free(p2p);
2988 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2989 "connection",
2990 wpa_s->cross_connect_disallowed ?
2991 "disallows" : "allows");
2992 }
2993 }
2994
2995 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2996#endif /* CONFIG_P2P */
2997
2998 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002999 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003000 wpa_ie + wpa_ie_len,
3001 max_wpa_ie_len -
3002 wpa_ie_len);
3003 }
3004
3005 /*
3006 * Workaround: Add Extended Capabilities element only if the AP
3007 * included this element in Beacon/Probe Response frames. Some older
3008 * APs seem to have interoperability issues if this element is
3009 * included, so while the standard may require us to include the
3010 * element in all cases, it is justifiable to skip it to avoid
3011 * interoperability issues.
3012 */
3013 if (ssid->p2p_group)
3014 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3015 else
3016 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3017
3018 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3019 u8 ext_capab[18];
3020 int ext_capab_len;
3021 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3022 sizeof(ext_capab));
3023 if (ext_capab_len > 0 &&
3024 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3025 u8 *pos = wpa_ie;
3026 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3027 pos += 2 + pos[1];
3028 os_memmove(pos + ext_capab_len, pos,
3029 wpa_ie_len - (pos - wpa_ie));
3030 wpa_ie_len += ext_capab_len;
3031 os_memcpy(pos, ext_capab, ext_capab_len);
3032 }
3033 }
3034
3035#ifdef CONFIG_HS20
3036 if (is_hs20_network(wpa_s, ssid, bss)) {
3037 struct wpabuf *hs20;
3038
Roshan Pius3a1667e2018-07-03 15:17:14 -07003039 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003040 if (hs20) {
3041 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3042 size_t len;
3043
Hai Shalom74f70d42019-02-11 14:42:39 -08003044 wpas_hs20_add_indication(hs20, pps_mo_id,
3045 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003046 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003047 len = max_wpa_ie_len - wpa_ie_len;
3048 if (wpabuf_len(hs20) <= len) {
3049 os_memcpy(wpa_ie + wpa_ie_len,
3050 wpabuf_head(hs20), wpabuf_len(hs20));
3051 wpa_ie_len += wpabuf_len(hs20);
3052 }
3053 wpabuf_free(hs20);
3054
3055 hs20_configure_frame_filters(wpa_s);
3056 }
3057 }
3058#endif /* CONFIG_HS20 */
3059
3060 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3061 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3062 size_t len;
3063
3064 len = max_wpa_ie_len - wpa_ie_len;
3065 if (wpabuf_len(buf) <= len) {
3066 os_memcpy(wpa_ie + wpa_ie_len,
3067 wpabuf_head(buf), wpabuf_len(buf));
3068 wpa_ie_len += wpabuf_len(buf);
3069 }
3070 }
3071
3072#ifdef CONFIG_FST
3073 if (wpa_s->fst_ies) {
3074 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3075
3076 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3077 os_memcpy(wpa_ie + wpa_ie_len,
3078 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3079 wpa_ie_len += fst_ies_len;
3080 }
3081 }
3082#endif /* CONFIG_FST */
3083
3084#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003085 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003086 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 int len;
3088
3089 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003090 max_wpa_ie_len - wpa_ie_len,
3091 !!mbo_attr_from_mbo_ie(mbo_ie,
3092 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003093 if (len >= 0)
3094 wpa_ie_len += len;
3095 }
3096#endif /* CONFIG_MBO */
3097
3098#ifdef CONFIG_FILS
3099 if (algs == WPA_AUTH_ALG_FILS) {
3100 size_t len;
3101
3102 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3103 max_wpa_ie_len - wpa_ie_len);
3104 wpa_ie_len += len;
3105 }
3106#endif /* CONFIG_FILS */
3107
3108#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003109#ifdef CONFIG_TESTING_OPTIONS
3110 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3111 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3112 } else
3113#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003114 if (algs == WPA_AUTH_ALG_OPEN &&
3115 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3116 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003117 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003118
Roshan Pius3a1667e2018-07-03 15:17:14 -07003119 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003120 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003121 } else if (wpa_s->assoc_status_code ==
3122 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003123 if (wpa_s->last_owe_group == 19)
3124 group = 20;
3125 else if (wpa_s->last_owe_group == 20)
3126 group = 21;
3127 else
3128 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003129 } else {
3130 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003131 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003132
Roshan Pius3a1667e2018-07-03 15:17:14 -07003133 wpa_s->last_owe_group = group;
3134 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003135 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3136 if (owe_ie &&
3137 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3138 os_memcpy(wpa_ie + wpa_ie_len,
3139 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3140 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003141 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003142 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003143 }
3144#endif /* CONFIG_OWE */
3145
Hai Shalom021b0b52019-04-10 11:17:58 -07003146#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003147 if (DPP_VERSION > 1 &&
3148 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003149 ssid->dpp_netaccesskey &&
3150 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003151 struct rsn_pmksa_cache_entry *pmksa;
3152
3153 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3154 if (!pmksa || !pmksa->dpp_pfs)
3155 goto pfs_fail;
3156
Hai Shalom021b0b52019-04-10 11:17:58 -07003157 dpp_pfs_free(wpa_s->dpp_pfs);
3158 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3159 ssid->dpp_netaccesskey_len);
3160 if (!wpa_s->dpp_pfs) {
3161 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3162 /* Try to continue without PFS */
3163 goto pfs_fail;
3164 }
3165 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3166 max_wpa_ie_len - wpa_ie_len) {
3167 os_memcpy(wpa_ie + wpa_ie_len,
3168 wpabuf_head(wpa_s->dpp_pfs->ie),
3169 wpabuf_len(wpa_s->dpp_pfs->ie));
3170 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3171 }
3172 }
3173pfs_fail:
3174#endif /* CONFIG_DPP2 */
3175
Roshan Pius3a1667e2018-07-03 15:17:14 -07003176#ifdef CONFIG_IEEE80211R
3177 /*
3178 * Add MDIE under these conditions: the network profile allows FT,
3179 * the AP supports FT, and the mobility domain ID matches.
3180 */
3181 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3182 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3183
3184 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3185 size_t len = 0;
3186 const u8 *md = mdie + 2;
3187 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3188
3189 if (os_memcmp(md, wpa_md,
3190 MOBILITY_DOMAIN_ID_LEN) == 0) {
3191 /* Add mobility domain IE */
3192 len = wpa_ft_add_mdie(
3193 wpa_s->wpa, wpa_ie + wpa_ie_len,
3194 max_wpa_ie_len - wpa_ie_len, mdie);
3195 wpa_ie_len += len;
3196 }
3197#ifdef CONFIG_SME
3198 if (len > 0 && wpa_s->sme.ft_used &&
3199 wpa_sm_has_ptk(wpa_s->wpa)) {
3200 wpa_dbg(wpa_s, MSG_DEBUG,
3201 "SME: Trying to use FT over-the-air");
3202 algs |= WPA_AUTH_ALG_FT;
3203 }
3204#endif /* CONFIG_SME */
3205 }
3206 }
3207#endif /* CONFIG_IEEE80211R */
3208
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003209#ifdef CONFIG_TESTING_OPTIONS
3210 if (wpa_s->rsnxe_override_assoc &&
3211 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3212 max_wpa_ie_len - wpa_ie_len) {
3213 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3214 os_memcpy(wpa_ie + wpa_ie_len,
3215 wpabuf_head(wpa_s->rsnxe_override_assoc),
3216 wpabuf_len(wpa_s->rsnxe_override_assoc));
3217 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3218 } else
3219#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003220 if (wpa_s->rsnxe_len > 0 &&
3221 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3222 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3223 wpa_ie_len += wpa_s->rsnxe_len;
3224 }
3225
Hai Shalom60840252021-02-19 19:02:11 -08003226 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3227 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003228 struct wpabuf *mscs_ie;
3229 size_t mscs_ie_len, buf_len;
3230
Hai Shalom899fcc72020-10-19 14:38:18 -07003231 buf_len = 3 + /* MSCS descriptor IE header */
3232 1 + /* Request type */
3233 2 + /* User priority control */
3234 4 + /* Stream timeout */
3235 3 + /* TCLAS Mask IE header */
3236 wpa_s->robust_av.frame_classifier_len;
3237 mscs_ie = wpabuf_alloc(buf_len);
3238 if (!mscs_ie) {
3239 wpa_printf(MSG_INFO,
3240 "MSCS: Failed to allocate MSCS IE");
3241 goto mscs_fail;
3242 }
3243
3244 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3245 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3246 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3247 mscs_ie_len = wpabuf_len(mscs_ie);
3248 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3249 mscs_ie_len);
3250 wpa_ie_len += mscs_ie_len;
3251 }
3252
3253 wpabuf_free(mscs_ie);
3254 }
3255mscs_fail:
3256
Hai Shalom74f70d42019-02-11 14:42:39 -08003257 if (ssid->multi_ap_backhaul_sta) {
3258 size_t multi_ap_ie_len;
3259
3260 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3261 max_wpa_ie_len - wpa_ie_len,
3262 MULTI_AP_BACKHAUL_STA);
3263 if (multi_ap_ie_len == 0) {
3264 wpa_printf(MSG_ERROR,
3265 "Multi-AP: Failed to build Multi-AP IE");
3266 os_free(wpa_ie);
3267 return NULL;
3268 }
3269 wpa_ie_len += multi_ap_ie_len;
3270 }
3271
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003272 params->wpa_ie = wpa_ie;
3273 params->wpa_ie_len = wpa_ie_len;
3274 params->auth_alg = algs;
3275 if (mask)
3276 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3277
3278 return wpa_ie;
3279}
3280
3281
Hai Shalomc3565922019-10-28 11:58:20 -07003282#ifdef CONFIG_OWE
3283static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3284{
3285 struct wpa_driver_associate_params params;
3286 u8 *wpa_ie;
3287
3288 os_memset(&params, 0, sizeof(params));
3289 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3290 wpa_s->current_ssid, &params, NULL);
3291 if (!wpa_ie)
3292 return;
3293
3294 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3295 os_free(wpa_ie);
3296}
3297#endif /* CONFIG_OWE */
3298
3299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003300#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3301static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3302{
3303 struct wpa_driver_associate_params params;
3304 enum wpa_drv_update_connect_params_mask mask = 0;
3305 u8 *wpa_ie;
3306
3307 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3308 return; /* nothing to do */
3309
3310 os_memset(&params, 0, sizeof(params));
3311 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3312 wpa_s->current_ssid, &params, &mask);
3313 if (!wpa_ie)
3314 return;
3315
3316 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3317 os_free(wpa_ie);
3318 return;
3319 }
3320
3321 wpa_s->auth_alg = params.auth_alg;
3322 wpa_drv_update_connect_params(wpa_s, &params, mask);
3323 os_free(wpa_ie);
3324}
3325#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3326
3327
Hai Shalomc3565922019-10-28 11:58:20 -07003328static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3329{
3330 if (!edmg_ie || edmg_ie[1] < 6)
3331 return 0;
3332 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3333}
3334
3335
3336static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3337{
3338 if (!edmg_ie || edmg_ie[1] < 6)
3339 return 0;
3340 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3341}
3342
3343
3344/* Returns the intersection of two EDMG configurations.
3345 * Note: The current implementation is limited to CB2 only (CB1 included),
3346 * i.e., the implementation supports up to 2 contiguous channels.
3347 * For supporting non-contiguous (aggregated) channels and for supporting
3348 * CB3 and above, this function will need to be extended.
3349 */
3350static struct ieee80211_edmg_config
3351get_edmg_intersection(struct ieee80211_edmg_config a,
3352 struct ieee80211_edmg_config b,
3353 u8 primary_channel)
3354{
3355 struct ieee80211_edmg_config result;
3356 int i, contiguous = 0;
3357 int max_contiguous = 0;
3358
3359 result.channels = b.channels & a.channels;
3360 if (!result.channels) {
3361 wpa_printf(MSG_DEBUG,
3362 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3363 a.channels, b.channels);
3364 goto fail;
3365 }
3366
3367 if (!(result.channels & BIT(primary_channel - 1))) {
3368 wpa_printf(MSG_DEBUG,
3369 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3370 primary_channel, result.channels);
3371 goto fail;
3372 }
3373
3374 /* Find max contiguous channels */
3375 for (i = 0; i < 6; i++) {
3376 if (result.channels & BIT(i))
3377 contiguous++;
3378 else
3379 contiguous = 0;
3380
3381 if (contiguous > max_contiguous)
3382 max_contiguous = contiguous;
3383 }
3384
3385 /* Assuming AP and STA supports ONLY contiguous channels,
3386 * bw configuration can have value between 4-7.
3387 */
3388 if ((b.bw_config < a.bw_config))
3389 result.bw_config = b.bw_config;
3390 else
3391 result.bw_config = a.bw_config;
3392
3393 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3394 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3395 wpa_printf(MSG_DEBUG,
3396 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3397 max_contiguous);
3398 goto fail;
3399 }
3400
3401 return result;
3402
3403fail:
3404 result.channels = 0;
3405 result.bw_config = 0;
3406 return result;
3407}
3408
3409
3410static struct ieee80211_edmg_config
3411get_supported_edmg(struct wpa_supplicant *wpa_s,
3412 struct hostapd_freq_params *freq,
3413 struct ieee80211_edmg_config request_edmg)
3414{
3415 enum hostapd_hw_mode hw_mode;
3416 struct hostapd_hw_modes *mode = NULL;
3417 u8 primary_channel;
3418
3419 if (!wpa_s->hw.modes)
3420 goto fail;
3421
3422 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3423 if (hw_mode == NUM_HOSTAPD_MODES)
3424 goto fail;
3425
Hai Shalom60840252021-02-19 19:02:11 -08003426 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003427 if (!mode)
3428 goto fail;
3429
3430 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3431
3432fail:
3433 request_edmg.channels = 0;
3434 request_edmg.bw_config = 0;
3435 return request_edmg;
3436}
3437
3438
Hai Shalom021b0b52019-04-10 11:17:58 -07003439#ifdef CONFIG_MBO
3440void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3441{
3442 struct wpa_driver_associate_params params;
3443 u8 *wpa_ie;
3444
3445 /*
3446 * Update MBO connect params only in case of change of MBO attributes
3447 * when connected, if the AP support MBO.
3448 */
3449
3450 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3451 !wpa_s->current_bss ||
3452 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3453 return;
3454
3455 os_memset(&params, 0, sizeof(params));
3456 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3457 wpa_s->current_ssid, &params, NULL);
3458 if (!wpa_ie)
3459 return;
3460
3461 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3462 os_free(wpa_ie);
3463}
3464#endif /* CONFIG_MBO */
3465
3466
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003467static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3468{
3469 struct wpa_connect_work *cwork = work->ctx;
3470 struct wpa_bss *bss = cwork->bss;
3471 struct wpa_ssid *ssid = cwork->ssid;
3472 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003473 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003474 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003475 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003476 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003477 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003478#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003479 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003480#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003481 int assoc_failed = 0;
3482 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003483 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003484#ifdef CONFIG_HT_OVERRIDES
3485 struct ieee80211_ht_capabilities htcaps;
3486 struct ieee80211_ht_capabilities htcaps_mask;
3487#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003488#ifdef CONFIG_VHT_OVERRIDES
3489 struct ieee80211_vht_capabilities vhtcaps;
3490 struct ieee80211_vht_capabilities vhtcaps_mask;
3491#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003492
3493 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003494 if (work->started) {
3495 wpa_s->connect_work = NULL;
3496
3497 /* cancel possible auth. timeout */
3498 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3499 NULL);
3500 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003501 wpas_connect_work_free(cwork);
3502 return;
3503 }
3504
3505 wpa_s->connect_work = work;
3506
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003507 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3508 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003509 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3510 wpas_connect_work_done(wpa_s);
3511 return;
3512 }
3513
Dmitry Shmidte4663042016-04-04 10:07:49 -07003514 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515 os_memset(&params, 0, sizeof(params));
3516 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003517 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003518
3519 /* Starting new association, so clear the possibly used WPA IE from the
3520 * previous association. */
3521 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3522 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3523 wpa_s->rsnxe_len = 0;
3524 wpa_s->mscs_setup_done = false;
3525
3526 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3527 if (!wpa_ie) {
3528 wpas_connect_work_done(wpa_s);
3529 return;
3530 }
3531
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003532 if (bss &&
3533 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003534#ifdef CONFIG_IEEE80211R
3535 const u8 *ie, *md = NULL;
3536#endif /* CONFIG_IEEE80211R */
3537 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3538 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3539 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3540 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3541 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3542 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3543 if (bssid_changed)
3544 wpas_notify_bssid_changed(wpa_s);
3545#ifdef CONFIG_IEEE80211R
3546 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3547 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3548 md = ie + 2;
3549 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3550 if (md) {
3551 /* Prepare for the next transition */
3552 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3553 }
3554#endif /* CONFIG_IEEE80211R */
3555#ifdef CONFIG_WPS
3556 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3557 wpa_s->conf->ap_scan == 2 &&
3558 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3559 /* Use ap_scan==1 style network selection to find the network
3560 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003561 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003562 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003563 wpa_s->reassociate = 1;
3564 wpa_supplicant_req_scan(wpa_s, 0, 0);
3565 return;
3566#endif /* CONFIG_WPS */
3567 } else {
3568 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3569 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003570 if (bss)
3571 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3572 else
3573 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003574 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003575 if (!wpa_s->pno)
3576 wpa_supplicant_cancel_sched_scan(wpa_s);
3577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003578 wpa_supplicant_cancel_scan(wpa_s);
3579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003580 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3581 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003582 cipher_pairwise = wpa_s->pairwise_cipher;
3583 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003584 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003585 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3586 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3587 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3588 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003589#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 if (wpa_set_wep_keys(wpa_s, ssid)) {
3591 use_crypt = 1;
3592 wep_keys_set = 1;
3593 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003594#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595 }
3596 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3597 use_crypt = 0;
3598
3599#ifdef IEEE8021X_EAPOL
3600 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3601 if ((ssid->eapol_flags &
3602 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3603 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3604 !wep_keys_set) {
3605 use_crypt = 0;
3606 } else {
3607 /* Assume that dynamic WEP-104 keys will be used and
3608 * set cipher suites in order for drivers to expect
3609 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003610 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 }
3612 }
3613#endif /* IEEE8021X_EAPOL */
3614
3615 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3616 /* Set the key before (and later after) association */
3617 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3618 }
3619
3620 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3621 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003622 params.ssid = bss->ssid;
3623 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003624 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3625 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003626 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3627 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003628 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003629 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003630 ssid->bssid_set,
3631 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003632 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003633 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003634 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003635 params.bssid_hint = bss->bssid;
3636 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003637 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003639 if (ssid->bssid_hint_set)
3640 params.bssid_hint = ssid->bssid_hint;
3641
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642 params.ssid = ssid->ssid;
3643 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003644 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003645 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003646
3647 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3648 wpa_s->conf->ap_scan == 2) {
3649 params.bssid = ssid->bssid;
3650 params.fixed_bssid = 1;
3651 }
3652
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003653 /* Initial frequency for IBSS/mesh */
3654 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003655 ssid->frequency > 0 && params.freq.freq == 0)
3656 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003657
3658 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003659 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003660 if (ssid->beacon_int)
3661 params.beacon_int = ssid->beacon_int;
3662 else
3663 params.beacon_int = wpa_s->conf->beacon_int;
3664 }
3665
Hai Shalomc3565922019-10-28 11:58:20 -07003666 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003667 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3668 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003669 else
3670 edmg_ie_oper = NULL;
3671
3672 if (edmg_ie_oper) {
3673 params.freq.edmg.channels =
3674 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3675 params.freq.edmg.bw_config =
3676 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3677 wpa_printf(MSG_DEBUG,
3678 "AP supports EDMG channels 0x%x, bw_config %d",
3679 params.freq.edmg.channels,
3680 params.freq.edmg.bw_config);
3681
3682 /* User may ask for specific EDMG channel for EDMG connection
3683 * (must be supported by AP)
3684 */
3685 if (ssid->edmg_channel) {
3686 struct ieee80211_edmg_config configured_edmg;
3687 enum hostapd_hw_mode hw_mode;
3688 u8 primary_channel;
3689
3690 hw_mode = ieee80211_freq_to_chan(bss->freq,
3691 &primary_channel);
3692 if (hw_mode == NUM_HOSTAPD_MODES)
3693 goto edmg_fail;
3694
3695 hostapd_encode_edmg_chan(ssid->enable_edmg,
3696 ssid->edmg_channel,
3697 primary_channel,
3698 &configured_edmg);
3699
3700 if (ieee802_edmg_is_allowed(params.freq.edmg,
3701 configured_edmg)) {
3702 params.freq.edmg = configured_edmg;
3703 wpa_printf(MSG_DEBUG,
3704 "Use EDMG channel %d for connection",
3705 ssid->edmg_channel);
3706 } else {
3707 edmg_fail:
3708 params.freq.edmg.channels = 0;
3709 params.freq.edmg.bw_config = 0;
3710 wpa_printf(MSG_WARNING,
3711 "EDMG channel %d not supported by AP, fallback to DMG",
3712 ssid->edmg_channel);
3713 }
3714 }
3715
3716 if (params.freq.edmg.channels) {
3717 wpa_printf(MSG_DEBUG,
3718 "EDMG before: channels 0x%x, bw_config %d",
3719 params.freq.edmg.channels,
3720 params.freq.edmg.bw_config);
3721 params.freq.edmg = get_supported_edmg(wpa_s,
3722 &params.freq,
3723 params.freq.edmg);
3724 wpa_printf(MSG_DEBUG,
3725 "EDMG after: channels 0x%x, bw_config %d",
3726 params.freq.edmg.channels,
3727 params.freq.edmg.bw_config);
3728 }
3729 }
3730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 params.pairwise_suite = cipher_pairwise;
3732 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003733 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003734 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003735 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003736 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003737 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003738 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003739#ifdef CONFIG_WEP
3740 {
3741 int i;
3742
3743 for (i = 0; i < NUM_WEP_KEYS; i++) {
3744 if (ssid->wep_key_len[i])
3745 params.wep_key[i] = ssid->wep_key[i];
3746 params.wep_key_len[i] = ssid->wep_key_len[i];
3747 }
3748 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003750#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751
Hai Shalom74f70d42019-02-11 14:42:39 -08003752 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003753 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3754 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755 params.passphrase = ssid->passphrase;
3756 if (ssid->psk_set)
3757 params.psk = ssid->psk;
3758 }
3759
Hai Shalom74f70d42019-02-11 14:42:39 -08003760 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3761 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3762 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3763 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3764 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003765 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003766
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003767 if (wpa_s->conf->key_mgmt_offload) {
3768 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3769 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003770 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3771 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003772 params.req_key_mgmt_offload =
3773 ssid->proactive_key_caching < 0 ?
3774 wpa_s->conf->okc : ssid->proactive_key_caching;
3775 else
3776 params.req_key_mgmt_offload = 1;
3777
3778 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3779 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3780 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3781 ssid->psk_set)
3782 params.psk = ssid->psk;
3783 }
3784
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003785 params.drop_unencrypted = use_crypt;
3786
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003787 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003788 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003789 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3790 struct wpa_ie_data ie;
3791 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3792 ie.capabilities &
3793 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3794 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3795 "MFP: require MFP");
3796 params.mgmt_frame_protection =
3797 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003798#ifdef CONFIG_OWE
3799 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3800 !ssid->owe_only) {
3801 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3802#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003803 }
3804 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003806 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003807
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003808 if (wpa_s->p2pdev->set_sta_uapsd)
3809 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 else
3811 params.uapsd = -1;
3812
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003813#ifdef CONFIG_HT_OVERRIDES
3814 os_memset(&htcaps, 0, sizeof(htcaps));
3815 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3816 params.htcaps = (u8 *) &htcaps;
3817 params.htcaps_mask = (u8 *) &htcaps_mask;
3818 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3819#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003820#ifdef CONFIG_VHT_OVERRIDES
3821 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3822 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3823 params.vhtcaps = &vhtcaps;
3824 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003825 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003826#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003827#ifdef CONFIG_HE_OVERRIDES
3828 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3829#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003830
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003831#ifdef CONFIG_P2P
3832 /*
3833 * If multi-channel concurrency is not supported, check for any
3834 * frequency conflict. In case of any frequency conflict, remove the
3835 * least prioritized connection.
3836 */
3837 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003838 int freq, num;
3839 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003840 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003841 wpa_printf(MSG_DEBUG,
3842 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003843 freq, params.freq.freq);
3844 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003845 wpa_s, params.freq.freq, ssid) < 0) {
3846 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003847 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003848 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003849 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003850 }
3851 }
3852#endif /* CONFIG_P2P */
3853
Dmitry Shmidte4663042016-04-04 10:07:49 -07003854 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3855 wpa_s->current_ssid)
3856 params.prev_bssid = prev_bssid;
3857
Hai Shalom60840252021-02-19 19:02:11 -08003858#ifdef CONFIG_SAE
3859 params.sae_pwe = wpa_s->conf->sae_pwe;
3860#endif /* CONFIG_SAE */
3861
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003862 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003863 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003864 if (ret < 0) {
3865 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3866 "failed");
3867 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3868 /*
3869 * The driver is known to mean what is saying, so we
3870 * can stop right here; the association will not
3871 * succeed.
3872 */
3873 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08003874 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08003875 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003876 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3878 return;
3879 }
3880 /* try to continue anyway; new association will be tried again
3881 * after timeout */
3882 assoc_failed = 1;
3883 }
3884
3885 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3886 /* Set the key after the association just in case association
3887 * cleared the previously configured key. */
3888 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3889 /* No need to timeout authentication since there is no key
3890 * management. */
3891 wpa_supplicant_cancel_auth_timeout(wpa_s);
3892 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3893#ifdef CONFIG_IBSS_RSN
3894 } else if (ssid->mode == WPAS_MODE_IBSS &&
3895 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3896 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3897 /*
3898 * RSN IBSS authentication is per-STA and we can disable the
3899 * per-BSSID authentication.
3900 */
3901 wpa_supplicant_cancel_auth_timeout(wpa_s);
3902#endif /* CONFIG_IBSS_RSN */
3903 } else {
3904 /* Timeout for IEEE 802.11 authentication and association */
3905 int timeout = 60;
3906
3907 if (assoc_failed) {
3908 /* give IBSS a bit more time */
3909 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3910 } else if (wpa_s->conf->ap_scan == 1) {
3911 /* give IBSS a bit more time */
3912 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3913 }
3914 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3915 }
3916
Hai Shalomfdcde762020-04-02 11:19:20 -07003917#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003918 if (wep_keys_set &&
3919 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920 /* Set static WEP keys again */
3921 wpa_set_wep_keys(wpa_s, ssid);
3922 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003923#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003924
3925 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3926 /*
3927 * Do not allow EAP session resumption between different
3928 * network configurations.
3929 */
3930 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3931 }
3932 old_ssid = wpa_s->current_ssid;
3933 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003934
3935 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003936 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003937#ifdef CONFIG_HS20
3938 hs20_configure_frame_filters(wpa_s);
3939#endif /* CONFIG_HS20 */
3940 }
3941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003942 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3943 wpa_supplicant_initiate_eapol(wpa_s);
3944 if (old_ssid != wpa_s->current_ssid)
3945 wpas_notify_network_changed(wpa_s);
3946}
3947
3948
3949static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3950 const u8 *addr)
3951{
3952 struct wpa_ssid *old_ssid;
3953
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003954 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003955 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003957 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 wpa_sm_set_config(wpa_s->wpa, NULL);
3959 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3960 if (old_ssid != wpa_s->current_ssid)
3961 wpas_notify_network_changed(wpa_s);
3962 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3963}
3964
3965
3966/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3968 * @wpa_s: Pointer to wpa_supplicant data
3969 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3970 *
3971 * This function is used to request %wpa_supplicant to deauthenticate from the
3972 * current AP.
3973 */
3974void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003975 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003976{
3977 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003978 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003979 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003980
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003981 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003982 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003983 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003984 reason_code, reason2str(reason_code),
3985 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003986
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003987 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3988 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3989 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003990 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003991 else if (!is_zero_ether_addr(wpa_s->bssid))
3992 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003993 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3994 /*
3995 * When using driver-based BSS selection, we may not know the
3996 * BSSID with which we are currently trying to associate. We
3997 * need to notify the driver of this disconnection even in such
3998 * a case, so use the all zeros address here.
3999 */
4000 addr = wpa_s->bssid;
4001 zero_addr = 1;
4002 }
4003
Hai Shalom74f70d42019-02-11 14:42:39 -08004004 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4005 wpa_s->enabled_4addr_mode = 0;
4006
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004007#ifdef CONFIG_TDLS
4008 wpa_tdls_teardown_peers(wpa_s->wpa);
4009#endif /* CONFIG_TDLS */
4010
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004011#ifdef CONFIG_MESH
4012 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004013 struct mesh_conf *mconf;
4014
4015 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004016 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4017 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004018 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4019 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004020 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004021 }
4022#endif /* CONFIG_MESH */
4023
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004024 if (addr) {
4025 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004026 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004027 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004028 event.deauth_info.locally_generated = 1;
4029 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004030 if (zero_addr)
4031 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 }
4033
4034 wpa_supplicant_clear_connection(wpa_s, addr);
4035}
4036
Hai Shalomfdcde762020-04-02 11:19:20 -07004037
4038void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4039{
4040 wpa_s->own_reconnect_req = 1;
4041 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4042
4043}
4044
4045
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004046static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4047 struct wpa_ssid *ssid)
4048{
4049 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4050 return;
4051
4052 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004053 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004054 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4055 wpas_notify_network_enabled_changed(wpa_s, ssid);
4056
4057 /*
4058 * Try to reassociate since there is no current configuration and a new
4059 * network was made available.
4060 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004061 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004062 wpa_s->reassociate = 1;
4063}
4064
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004065
Roshan Pius950bec92016-07-19 09:49:24 -07004066/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004067 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004068 * @wpa_s: wpa_supplicant structure for a network interface
4069 * Returns: The new network configuration or %NULL if operation failed
4070 *
4071 * This function performs the following operations:
4072 * 1. Adds a new network.
4073 * 2. Send network addition notification.
4074 * 3. Marks the network disabled.
4075 * 4. Set network default parameters.
4076 */
4077struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4078{
4079 struct wpa_ssid *ssid;
4080
4081 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004082 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004083 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004084 wpas_notify_network_added(wpa_s, ssid);
4085 ssid->disabled = 1;
4086 wpa_config_set_network_defaults(ssid);
4087
4088 return ssid;
4089}
4090
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004091
Roshan Pius950bec92016-07-19 09:49:24 -07004092/**
4093 * wpa_supplicant_remove_network - Remove a configured network based on id
4094 * @wpa_s: wpa_supplicant structure for a network interface
4095 * @id: Unique network id to search for
4096 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4097 * could not be removed
4098 *
4099 * This function performs the following operations:
4100 * 1. Removes the network.
4101 * 2. Send network removal notification.
4102 * 3. Update internal state machines.
4103 * 4. Stop any running sched scans.
4104 */
4105int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4106{
4107 struct wpa_ssid *ssid;
4108 int was_disabled;
4109
4110 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004111 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004112 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004113 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004114
4115 if (wpa_s->last_ssid == ssid)
4116 wpa_s->last_ssid = NULL;
4117
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004118 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004119#ifdef CONFIG_SME
4120 wpa_s->sme.prev_bssid_set = 0;
4121#endif /* CONFIG_SME */
4122 /*
4123 * Invalidate the EAP session cache if the current or
4124 * previously used network is removed.
4125 */
4126 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4127 }
4128
4129 if (ssid == wpa_s->current_ssid) {
4130 wpa_sm_set_config(wpa_s->wpa, NULL);
4131 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4132
4133 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4134 wpa_s->own_disconnect_req = 1;
4135 wpa_supplicant_deauthenticate(wpa_s,
4136 WLAN_REASON_DEAUTH_LEAVING);
4137 }
4138
4139 was_disabled = ssid->disabled;
4140
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004141 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004142 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004143
4144 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004145 wpa_printf(MSG_DEBUG,
4146 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004147 wpa_supplicant_cancel_sched_scan(wpa_s);
4148 wpa_supplicant_req_scan(wpa_s, 0, 0);
4149 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004150
Roshan Pius950bec92016-07-19 09:49:24 -07004151 return 0;
4152}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004154
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004156 * wpa_supplicant_remove_all_networks - Remove all configured networks
4157 * @wpa_s: wpa_supplicant structure for a network interface
4158 * Returns: 0 on success (errors are currently ignored)
4159 *
4160 * This function performs the following operations:
4161 * 1. Remove all networks.
4162 * 2. Send network removal notifications.
4163 * 3. Update internal state machines.
4164 * 4. Stop any running sched scans.
4165 */
4166int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4167{
4168 struct wpa_ssid *ssid;
4169
4170 if (wpa_s->sched_scanning)
4171 wpa_supplicant_cancel_sched_scan(wpa_s);
4172
4173 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4174 if (wpa_s->current_ssid) {
4175#ifdef CONFIG_SME
4176 wpa_s->sme.prev_bssid_set = 0;
4177#endif /* CONFIG_SME */
4178 wpa_sm_set_config(wpa_s->wpa, NULL);
4179 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4180 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4181 wpa_s->own_disconnect_req = 1;
4182 wpa_supplicant_deauthenticate(
4183 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4184 }
4185 ssid = wpa_s->conf->ssid;
4186 while (ssid) {
4187 struct wpa_ssid *remove_ssid = ssid;
4188 int id;
4189
4190 id = ssid->id;
4191 ssid = ssid->next;
4192 if (wpa_s->last_ssid == remove_ssid)
4193 wpa_s->last_ssid = NULL;
4194 wpas_notify_network_removed(wpa_s, remove_ssid);
4195 wpa_config_remove_network(wpa_s->conf, id);
4196 }
4197 return 0;
4198}
4199
4200
4201/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202 * wpa_supplicant_enable_network - Mark a configured network as enabled
4203 * @wpa_s: wpa_supplicant structure for a network interface
4204 * @ssid: wpa_ssid structure for a configured network or %NULL
4205 *
4206 * Enables the specified network or all networks if no network specified.
4207 */
4208void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4209 struct wpa_ssid *ssid)
4210{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004211 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004212 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4213 wpa_supplicant_enable_one_network(wpa_s, ssid);
4214 } else
4215 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004216
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004217 if (wpa_s->reassociate && !wpa_s->disconnected &&
4218 (!wpa_s->current_ssid ||
4219 wpa_s->wpa_state == WPA_DISCONNECTED ||
4220 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004221 if (wpa_s->sched_scanning) {
4222 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4223 "new network to scan filters");
4224 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225 }
4226
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004227 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4228 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004229 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004230 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004231 }
4232}
4233
4234
4235/**
4236 * wpa_supplicant_disable_network - Mark a configured network as disabled
4237 * @wpa_s: wpa_supplicant structure for a network interface
4238 * @ssid: wpa_ssid structure for a configured network or %NULL
4239 *
4240 * Disables the specified network or all networks if no network specified.
4241 */
4242void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4243 struct wpa_ssid *ssid)
4244{
4245 struct wpa_ssid *other_ssid;
4246 int was_disabled;
4247
4248 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004249 if (wpa_s->sched_scanning)
4250 wpa_supplicant_cancel_sched_scan(wpa_s);
4251
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004252 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4253 other_ssid = other_ssid->next) {
4254 was_disabled = other_ssid->disabled;
4255 if (was_disabled == 2)
4256 continue; /* do not change persistent P2P group
4257 * data */
4258
4259 other_ssid->disabled = 1;
4260
4261 if (was_disabled != other_ssid->disabled)
4262 wpas_notify_network_enabled_changed(
4263 wpa_s, other_ssid);
4264 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004265 if (wpa_s->current_ssid) {
4266 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4267 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004268 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004270 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004272 if (ssid == wpa_s->current_ssid) {
4273 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4274 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004275 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004277 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004278
4279 was_disabled = ssid->disabled;
4280
4281 ssid->disabled = 1;
4282
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004283 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004285 if (wpa_s->sched_scanning) {
4286 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4287 "to remove network from filters");
4288 wpa_supplicant_cancel_sched_scan(wpa_s);
4289 wpa_supplicant_req_scan(wpa_s, 0, 0);
4290 }
4291 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 }
4293}
4294
4295
4296/**
4297 * wpa_supplicant_select_network - Attempt association with a network
4298 * @wpa_s: wpa_supplicant structure for a network interface
4299 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4300 */
4301void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4302 struct wpa_ssid *ssid)
4303{
4304
4305 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004306 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004307
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004308 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004309 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4310 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004311 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004313 disconnected = 1;
4314 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004315
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004316 if (ssid)
4317 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319 /*
4320 * Mark all other networks disabled or mark all networks enabled if no
4321 * network specified.
4322 */
4323 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4324 other_ssid = other_ssid->next) {
4325 int was_disabled = other_ssid->disabled;
4326 if (was_disabled == 2)
4327 continue; /* do not change persistent P2P group data */
4328
4329 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004330 if (was_disabled && !other_ssid->disabled)
4331 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332
4333 if (was_disabled != other_ssid->disabled)
4334 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4335 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004336
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004337 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4338 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004339 /* We are already associated with the selected network */
4340 wpa_printf(MSG_DEBUG, "Already associated with the "
4341 "selected network - do nothing");
4342 return;
4343 }
4344
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004345 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004346 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004347 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004348 wpa_s->connect_without_scan =
4349 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004350
4351 /*
4352 * Don't optimize next scan freqs since a new ESS has been
4353 * selected.
4354 */
4355 os_free(wpa_s->next_scan_freqs);
4356 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004357 } else {
4358 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004359 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004361 wpa_s->disconnected = 0;
4362 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004363 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004364 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004365 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004366 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004367 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4368 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004369
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004370 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004371 wpa_supplicant_fast_associate(wpa_s) != 1) {
4372 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004373 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004374 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004376
4377 if (ssid)
4378 wpas_notify_network_selected(wpa_s, ssid);
4379}
4380
4381
4382/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004383 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4384 * @wpa_s: wpa_supplicant structure for a network interface
4385 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4386 * @pkcs11_module_path: PKCS #11 module path or NULL
4387 * Returns: 0 on success; -1 on failure
4388 *
4389 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4390 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4391 * module path fails the paths will be reset to the default value (NULL).
4392 */
4393int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4394 const char *pkcs11_engine_path,
4395 const char *pkcs11_module_path)
4396{
4397 char *pkcs11_engine_path_copy = NULL;
4398 char *pkcs11_module_path_copy = NULL;
4399
4400 if (pkcs11_engine_path != NULL) {
4401 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4402 if (pkcs11_engine_path_copy == NULL)
4403 return -1;
4404 }
4405 if (pkcs11_module_path != NULL) {
4406 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004407 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004408 os_free(pkcs11_engine_path_copy);
4409 return -1;
4410 }
4411 }
4412
4413 os_free(wpa_s->conf->pkcs11_engine_path);
4414 os_free(wpa_s->conf->pkcs11_module_path);
4415 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4416 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4417
4418 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4419 eapol_sm_deinit(wpa_s->eapol);
4420 wpa_s->eapol = NULL;
4421 if (wpa_supplicant_init_eapol(wpa_s)) {
4422 /* Error -> Reset paths to the default value (NULL) once. */
4423 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4424 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4425 NULL);
4426
4427 return -1;
4428 }
4429 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4430
4431 return 0;
4432}
4433
4434
4435/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4437 * @wpa_s: wpa_supplicant structure for a network interface
4438 * @ap_scan: AP scan mode
4439 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4440 *
4441 */
4442int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4443{
4444
4445 int old_ap_scan;
4446
4447 if (ap_scan < 0 || ap_scan > 2)
4448 return -1;
4449
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004450 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4451 wpa_printf(MSG_INFO,
4452 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4453 }
4454
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004455#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004456 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4457 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4458 wpa_s->wpa_state < WPA_COMPLETED) {
4459 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4460 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004461 return 0;
4462 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004463#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004464
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004465 old_ap_scan = wpa_s->conf->ap_scan;
4466 wpa_s->conf->ap_scan = ap_scan;
4467
4468 if (old_ap_scan != wpa_s->conf->ap_scan)
4469 wpas_notify_ap_scan_changed(wpa_s);
4470
4471 return 0;
4472}
4473
4474
4475/**
4476 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4477 * @wpa_s: wpa_supplicant structure for a network interface
4478 * @expire_age: Expiration age in seconds
4479 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4480 *
4481 */
4482int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4483 unsigned int bss_expire_age)
4484{
4485 if (bss_expire_age < 10) {
4486 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4487 bss_expire_age);
4488 return -1;
4489 }
4490 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4491 bss_expire_age);
4492 wpa_s->conf->bss_expiration_age = bss_expire_age;
4493
4494 return 0;
4495}
4496
4497
4498/**
4499 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4500 * @wpa_s: wpa_supplicant structure for a network interface
4501 * @expire_count: number of scans after which an unseen BSS is reclaimed
4502 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4503 *
4504 */
4505int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4506 unsigned int bss_expire_count)
4507{
4508 if (bss_expire_count < 1) {
4509 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4510 bss_expire_count);
4511 return -1;
4512 }
4513 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4514 bss_expire_count);
4515 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4516
4517 return 0;
4518}
4519
4520
4521/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004522 * wpa_supplicant_set_scan_interval - Set scan interval
4523 * @wpa_s: wpa_supplicant structure for a network interface
4524 * @scan_interval: scan interval in seconds
4525 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4526 *
4527 */
4528int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4529 int scan_interval)
4530{
4531 if (scan_interval < 0) {
4532 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4533 scan_interval);
4534 return -1;
4535 }
4536 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4537 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004538 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004539
4540 return 0;
4541}
4542
4543
4544/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004545 * wpa_supplicant_set_debug_params - Set global debug params
4546 * @global: wpa_global structure
4547 * @debug_level: debug level
4548 * @debug_timestamp: determines if show timestamp in debug data
4549 * @debug_show_keys: determines if show keys in debug data
4550 * Returns: 0 if succeed or -1 if debug_level has wrong value
4551 */
4552int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4553 int debug_timestamp, int debug_show_keys)
4554{
4555
4556 int old_level, old_timestamp, old_show_keys;
4557
4558 /* check for allowed debuglevels */
4559 if (debug_level != MSG_EXCESSIVE &&
4560 debug_level != MSG_MSGDUMP &&
4561 debug_level != MSG_DEBUG &&
4562 debug_level != MSG_INFO &&
4563 debug_level != MSG_WARNING &&
4564 debug_level != MSG_ERROR)
4565 return -1;
4566
4567 old_level = wpa_debug_level;
4568 old_timestamp = wpa_debug_timestamp;
4569 old_show_keys = wpa_debug_show_keys;
4570
4571 wpa_debug_level = debug_level;
4572 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4573 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4574
4575 if (wpa_debug_level != old_level)
4576 wpas_notify_debug_level_changed(global);
4577 if (wpa_debug_timestamp != old_timestamp)
4578 wpas_notify_debug_timestamp_changed(global);
4579 if (wpa_debug_show_keys != old_show_keys)
4580 wpas_notify_debug_show_keys_changed(global);
4581
4582 return 0;
4583}
4584
4585
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004586#ifdef CONFIG_OWE
4587static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4588 const u8 *entry_ssid, size_t entry_ssid_len)
4589{
4590 const u8 *owe, *pos, *end;
4591 u8 ssid_len;
4592 struct wpa_bss *bss;
4593
4594 /* Check network profile SSID aganst the SSID in the
4595 * OWE Transition Mode element. */
4596
4597 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4598 if (!bss)
4599 return 0;
4600
4601 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4602 if (!owe)
4603 return 0;
4604
4605 pos = owe + 6;
4606 end = owe + 2 + owe[1];
4607
4608 if (end - pos < ETH_ALEN + 1)
4609 return 0;
4610 pos += ETH_ALEN;
4611 ssid_len = *pos++;
4612 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4613 return 0;
4614
4615 return entry_ssid_len == ssid_len &&
4616 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4617}
4618#endif /* CONFIG_OWE */
4619
4620
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004621/**
4622 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4623 * @wpa_s: Pointer to wpa_supplicant data
4624 * Returns: A pointer to the current network structure or %NULL on failure
4625 */
4626struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4627{
4628 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004629 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630 int res;
4631 size_t ssid_len;
4632 u8 bssid[ETH_ALEN];
4633 int wired;
4634
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004635 res = wpa_drv_get_ssid(wpa_s, ssid);
4636 if (res < 0) {
4637 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4638 "driver");
4639 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004640 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004641 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004643 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004644 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4645 "driver");
4646 return NULL;
4647 }
4648
4649 wired = wpa_s->conf->ap_scan == 0 &&
4650 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4651
4652 entry = wpa_s->conf->ssid;
4653 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004654 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004655 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004656 (!entry->ssid ||
4657 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4658 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004659 (!entry->bssid_set ||
4660 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4661 return entry;
4662#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004663 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004664 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4665 (entry->ssid == NULL || entry->ssid_len == 0) &&
4666 (!entry->bssid_set ||
4667 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4668 return entry;
4669#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004670
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004671#ifdef CONFIG_OWE
4672 if (!wpas_network_disabled(wpa_s, entry) &&
4673 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4674 entry->ssid_len) &&
4675 (!entry->bssid_set ||
4676 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4677 return entry;
4678#endif /* CONFIG_OWE */
4679
Dmitry Shmidt04949592012-07-19 12:16:46 -07004680 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004681 entry->ssid_len == 0 &&
4682 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4683 return entry;
4684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004685 entry = entry->next;
4686 }
4687
4688 return NULL;
4689}
4690
4691
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004692static int select_driver(struct wpa_supplicant *wpa_s, int i)
4693{
4694 struct wpa_global *global = wpa_s->global;
4695
4696 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004697 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004698 if (global->drv_priv[i] == NULL) {
4699 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4700 "'%s'", wpa_drivers[i]->name);
4701 return -1;
4702 }
4703 }
4704
4705 wpa_s->driver = wpa_drivers[i];
4706 wpa_s->global_drv_priv = global->drv_priv[i];
4707
4708 return 0;
4709}
4710
4711
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004712static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4713 const char *name)
4714{
4715 int i;
4716 size_t len;
4717 const char *pos, *driver = name;
4718
4719 if (wpa_s == NULL)
4720 return -1;
4721
4722 if (wpa_drivers[0] == NULL) {
4723 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4724 "wpa_supplicant");
4725 return -1;
4726 }
4727
4728 if (name == NULL) {
4729 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004730 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004731 }
4732
4733 do {
4734 pos = os_strchr(driver, ',');
4735 if (pos)
4736 len = pos - driver;
4737 else
4738 len = os_strlen(driver);
4739
4740 for (i = 0; wpa_drivers[i]; i++) {
4741 if (os_strlen(wpa_drivers[i]->name) == len &&
4742 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004743 0) {
4744 /* First driver that succeeds wins */
4745 if (select_driver(wpa_s, i) == 0)
4746 return 0;
4747 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 }
4749
4750 driver = pos + 1;
4751 } while (pos);
4752
4753 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4754 return -1;
4755}
4756
4757
4758/**
4759 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4760 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4761 * with struct wpa_driver_ops::init()
4762 * @src_addr: Source address of the EAPOL frame
4763 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4764 * @len: Length of the EAPOL data
4765 *
4766 * This function is called for each received EAPOL frame. Most driver
4767 * interfaces rely on more generic OS mechanism for receiving frames through
4768 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4769 * take care of received EAPOL frames and deliver them to the core supplicant
4770 * code by calling this function.
4771 */
4772void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4773 const u8 *buf, size_t len)
4774{
4775 struct wpa_supplicant *wpa_s = ctx;
4776
4777 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4778 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4779
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004780#ifdef CONFIG_TESTING_OPTIONS
4781 if (wpa_s->ignore_auth_resp) {
4782 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4783 return;
4784 }
4785#endif /* CONFIG_TESTING_OPTIONS */
4786
Jouni Malinena05074c2012-12-21 21:35:35 +02004787 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4788 (wpa_s->last_eapol_matches_bssid &&
4789#ifdef CONFIG_AP
4790 !wpa_s->ap_iface &&
4791#endif /* CONFIG_AP */
4792 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004793 /*
4794 * There is possible race condition between receiving the
4795 * association event and the EAPOL frame since they are coming
4796 * through different paths from the driver. In order to avoid
4797 * issues in trying to process the EAPOL frame before receiving
4798 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004799 * the association event is received. This may also be needed in
4800 * driver-based roaming case, so also use src_addr != BSSID as a
4801 * trigger if we have previously confirmed that the
4802 * Authenticator uses BSSID as the src_addr (which is not the
4803 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804 */
4805 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004806 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4807 wpa_supplicant_state_txt(wpa_s->wpa_state),
4808 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 wpabuf_free(wpa_s->pending_eapol_rx);
4810 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4811 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004812 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004813 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4814 ETH_ALEN);
4815 }
4816 return;
4817 }
4818
Jouni Malinena05074c2012-12-21 21:35:35 +02004819 wpa_s->last_eapol_matches_bssid =
4820 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004822#ifdef CONFIG_AP
4823 if (wpa_s->ap_iface) {
4824 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4825 return;
4826 }
4827#endif /* CONFIG_AP */
4828
4829 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4830 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4831 "no key management is configured");
4832 return;
4833 }
4834
4835 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004836 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004837 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4838 wpa_s->wpa_state != WPA_COMPLETED) &&
4839 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004840 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004842 int timeout = 10;
4843
4844 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4845 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4846 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4847 /* Use longer timeout for IEEE 802.1X/EAP */
4848 timeout = 70;
4849 }
4850
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004851#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004852 if (wpa_s->current_ssid && wpa_s->current_bss &&
4853 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4854 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4855 /*
4856 * Use shorter timeout if going through WPS AP iteration
4857 * for PIN config method with an AP that does not
4858 * advertise Selected Registrar.
4859 */
4860 struct wpabuf *wps_ie;
4861
4862 wps_ie = wpa_bss_get_vendor_ie_multi(
4863 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4864 if (wps_ie &&
4865 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4866 timeout = 10;
4867 wpabuf_free(wps_ie);
4868 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004869#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004870
4871 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004872 }
4873 wpa_s->eapol_received++;
4874
4875 if (wpa_s->countermeasures) {
4876 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4877 "EAPOL packet");
4878 return;
4879 }
4880
4881#ifdef CONFIG_IBSS_RSN
4882 if (wpa_s->current_ssid &&
4883 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4884 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4885 return;
4886 }
4887#endif /* CONFIG_IBSS_RSN */
4888
4889 /* Source address of the incoming EAPOL frame could be compared to the
4890 * current BSSID. However, it is possible that a centralized
4891 * Authenticator could be using another MAC address than the BSSID of
4892 * an AP, so just allow any address to be used for now. The replies are
4893 * still sent to the current BSSID (if available), though. */
4894
4895 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4896 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004897 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4898 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004899 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4900 return;
4901 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004902 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004903 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4904 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4905 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004906 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 * handshake processing which would normally set portValid. We
4908 * need this to allow the EAPOL state machines to be completed
4909 * without going through EAPOL-Key handshake.
4910 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004911 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912 }
4913}
4914
4915
Hai Shalomb755a2a2020-04-23 21:49:02 -07004916static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4917{
4918 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4919 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4920}
4921
4922
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004923int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004924{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004925 if ((!wpa_s->p2p_mgmt ||
4926 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4927 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004928 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004929 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4930 wpa_drv_get_mac_addr(wpa_s),
4931 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004932 wpas_eapol_needs_l2_packet(wpa_s) ?
4933 wpa_supplicant_rx_eapol : NULL,
4934 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004935 if (wpa_s->l2 == NULL)
4936 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004937
4938 if (l2_packet_set_packet_filter(wpa_s->l2,
4939 L2_PACKET_FILTER_PKTTYPE))
4940 wpa_dbg(wpa_s, MSG_DEBUG,
4941 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004942
4943 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4944 wpa_msg(wpa_s, MSG_ERROR,
4945 "Failed to get own L2 address");
4946 return -1;
4947 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004948 } else {
4949 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4950 if (addr)
4951 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4952 }
4953
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004954 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004955 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004956
Hai Shalomc3565922019-10-28 11:58:20 -07004957#ifdef CONFIG_FST
4958 if (wpa_s->fst)
4959 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4960#endif /* CONFIG_FST */
4961
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004962 return 0;
4963}
4964
4965
Dmitry Shmidt04949592012-07-19 12:16:46 -07004966static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4967 const u8 *buf, size_t len)
4968{
4969 struct wpa_supplicant *wpa_s = ctx;
4970 const struct l2_ethhdr *eth;
4971
4972 if (len < sizeof(*eth))
4973 return;
4974 eth = (const struct l2_ethhdr *) buf;
4975
4976 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4977 !(eth->h_dest[0] & 0x01)) {
4978 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4979 " (bridge - not for this interface - ignore)",
4980 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4981 return;
4982 }
4983
4984 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4985 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4986 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4987 len - sizeof(*eth));
4988}
4989
4990
Hai Shalom899fcc72020-10-19 14:38:18 -07004991int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
4992 const char *bridge_ifname)
4993{
4994 if (wpa_s->wpa_state > WPA_SCANNING)
4995 return -EBUSY;
4996
4997 if (bridge_ifname &&
4998 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
4999 return -EINVAL;
5000
5001 if (!bridge_ifname)
5002 bridge_ifname = "";
5003
5004 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5005 return 0;
5006
5007 if (wpa_s->l2_br) {
5008 l2_packet_deinit(wpa_s->l2_br);
5009 wpa_s->l2_br = NULL;
5010 }
5011
5012 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5013 sizeof(wpa_s->bridge_ifname));
5014
5015 if (wpa_s->bridge_ifname[0]) {
5016 wpa_dbg(wpa_s, MSG_DEBUG,
5017 "Receiving packets from bridge interface '%s'",
5018 wpa_s->bridge_ifname);
5019 wpa_s->l2_br = l2_packet_init_bridge(
5020 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5021 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5022 if (!wpa_s->l2_br) {
5023 wpa_msg(wpa_s, MSG_ERROR,
5024 "Failed to open l2_packet connection for the bridge interface '%s'",
5025 wpa_s->bridge_ifname);
5026 goto fail;
5027 }
5028 }
5029
5030#ifdef CONFIG_TDLS
5031 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5032 goto fail;
5033#endif /* CONFIG_TDLS */
5034
5035 return 0;
5036fail:
5037 wpa_s->bridge_ifname[0] = 0;
5038 if (wpa_s->l2_br) {
5039 l2_packet_deinit(wpa_s->l2_br);
5040 wpa_s->l2_br = NULL;
5041 }
5042#ifdef CONFIG_TDLS
5043 if (!wpa_s->p2p_mgmt)
5044 wpa_tdls_init(wpa_s->wpa);
5045#endif /* CONFIG_TDLS */
5046 return -EIO;
5047}
5048
5049
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005050/**
5051 * wpa_supplicant_driver_init - Initialize driver interface parameters
5052 * @wpa_s: Pointer to wpa_supplicant data
5053 * Returns: 0 on success, -1 on failure
5054 *
5055 * This function is called to initialize driver interface parameters.
5056 * wpa_drv_init() must have been called before this function to initialize the
5057 * driver interface.
5058 */
5059int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5060{
5061 static int interface_count = 0;
5062
5063 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5064 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005065
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005066 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5067 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005068 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005069 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5070
Hai Shalomb755a2a2020-04-23 21:49:02 -07005071 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005072 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5073 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005074 wpa_s->l2_br = l2_packet_init_bridge(
5075 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5076 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005077 if (wpa_s->l2_br == NULL) {
5078 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5079 "connection for the bridge interface '%s'",
5080 wpa_s->bridge_ifname);
5081 return -1;
5082 }
5083 }
5084
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005085 if (wpa_s->conf->ap_scan == 2 &&
5086 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5087 wpa_printf(MSG_INFO,
5088 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5089 }
5090
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005091 wpa_clear_keys(wpa_s, NULL);
5092
5093 /* Make sure that TKIP countermeasures are not left enabled (could
5094 * happen if wpa_supplicant is killed during countermeasures. */
5095 wpa_drv_set_countermeasures(wpa_s, 0);
5096
5097 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5098 wpa_drv_flush_pmkid(wpa_s);
5099
5100 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005101 wpa_s->prev_scan_wildcard = 0;
5102
Dmitry Shmidt04949592012-07-19 12:16:46 -07005103 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005104 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5105 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5106 interface_count = 0;
5107 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005108#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005109 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005110 wpa_supplicant_delayed_sched_scan(wpa_s,
5111 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005112 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005113 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005114 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005115#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116 interface_count++;
5117 } else
5118 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5119
5120 return 0;
5121}
5122
5123
5124static int wpa_supplicant_daemon(const char *pid_file)
5125{
5126 wpa_printf(MSG_DEBUG, "Daemonize..");
5127 return os_daemonize(pid_file);
5128}
5129
5130
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005131static struct wpa_supplicant *
5132wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005133{
5134 struct wpa_supplicant *wpa_s;
5135
5136 wpa_s = os_zalloc(sizeof(*wpa_s));
5137 if (wpa_s == NULL)
5138 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005139 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005140 wpa_s->scan_interval = 5;
5141 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005142 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005143 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005144 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005145 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005146
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005147 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005148 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005149#ifdef CONFIG_TESTING_OPTIONS
5150 dl_list_init(&wpa_s->drv_signal_override);
5151#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005152
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005153 return wpa_s;
5154}
5155
5156
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005157#ifdef CONFIG_HT_OVERRIDES
5158
5159static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5160 struct ieee80211_ht_capabilities *htcaps,
5161 struct ieee80211_ht_capabilities *htcaps_mask,
5162 const char *ht_mcs)
5163{
5164 /* parse ht_mcs into hex array */
5165 int i;
5166 const char *tmp = ht_mcs;
5167 char *end = NULL;
5168
5169 /* If ht_mcs is null, do not set anything */
5170 if (!ht_mcs)
5171 return 0;
5172
5173 /* This is what we are setting in the kernel */
5174 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5175
5176 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5177
5178 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005179 long v;
5180
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005181 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005182 v = strtol(tmp, &end, 16);
5183
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005184 if (errno == 0) {
5185 wpa_msg(wpa_s, MSG_DEBUG,
5186 "htcap value[%i]: %ld end: %p tmp: %p",
5187 i, v, end, tmp);
5188 if (end == tmp)
5189 break;
5190
5191 htcaps->supported_mcs_set[i] = v;
5192 tmp = end;
5193 } else {
5194 wpa_msg(wpa_s, MSG_ERROR,
5195 "Failed to parse ht-mcs: %s, error: %s\n",
5196 ht_mcs, strerror(errno));
5197 return -1;
5198 }
5199 }
5200
5201 /*
5202 * If we were able to parse any values, then set mask for the MCS set.
5203 */
5204 if (i) {
5205 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5206 IEEE80211_HT_MCS_MASK_LEN - 1);
5207 /* skip the 3 reserved bits */
5208 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5209 0x1f;
5210 }
5211
5212 return 0;
5213}
5214
5215
5216static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5217 struct ieee80211_ht_capabilities *htcaps,
5218 struct ieee80211_ht_capabilities *htcaps_mask,
5219 int disabled)
5220{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005221 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005222
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005223 if (disabled == -1)
5224 return 0;
5225
Hai Shalom74f70d42019-02-11 14:42:39 -08005226 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5227
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005228 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5229 htcaps_mask->ht_capabilities_info |= msk;
5230 if (disabled)
5231 htcaps->ht_capabilities_info &= msk;
5232 else
5233 htcaps->ht_capabilities_info |= msk;
5234
5235 return 0;
5236}
5237
5238
5239static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5240 struct ieee80211_ht_capabilities *htcaps,
5241 struct ieee80211_ht_capabilities *htcaps_mask,
5242 int factor)
5243{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005244 if (factor == -1)
5245 return 0;
5246
Hai Shalom74f70d42019-02-11 14:42:39 -08005247 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5248
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005249 if (factor < 0 || factor > 3) {
5250 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5251 "Must be 0-3 or -1", factor);
5252 return -EINVAL;
5253 }
5254
5255 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5256 htcaps->a_mpdu_params &= ~0x3;
5257 htcaps->a_mpdu_params |= factor & 0x3;
5258
5259 return 0;
5260}
5261
5262
5263static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5264 struct ieee80211_ht_capabilities *htcaps,
5265 struct ieee80211_ht_capabilities *htcaps_mask,
5266 int density)
5267{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005268 if (density == -1)
5269 return 0;
5270
Hai Shalom74f70d42019-02-11 14:42:39 -08005271 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5272
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005273 if (density < 0 || density > 7) {
5274 wpa_msg(wpa_s, MSG_ERROR,
5275 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5276 density);
5277 return -EINVAL;
5278 }
5279
5280 htcaps_mask->a_mpdu_params |= 0x1C;
5281 htcaps->a_mpdu_params &= ~(0x1C);
5282 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5283
5284 return 0;
5285}
5286
5287
5288static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5289 struct ieee80211_ht_capabilities *htcaps,
5290 struct ieee80211_ht_capabilities *htcaps_mask,
5291 int disabled)
5292{
Hai Shalom74f70d42019-02-11 14:42:39 -08005293 if (disabled)
5294 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005295
Paul Stewart092955c2017-02-06 09:13:09 -08005296 set_disable_ht40(htcaps, disabled);
5297 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005298
5299 return 0;
5300}
5301
5302
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005303static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5304 struct ieee80211_ht_capabilities *htcaps,
5305 struct ieee80211_ht_capabilities *htcaps_mask,
5306 int disabled)
5307{
5308 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005309 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5310 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005311
Hai Shalom74f70d42019-02-11 14:42:39 -08005312 if (disabled)
5313 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005314
5315 if (disabled)
5316 htcaps->ht_capabilities_info &= ~msk;
5317 else
5318 htcaps->ht_capabilities_info |= msk;
5319
5320 htcaps_mask->ht_capabilities_info |= msk;
5321
5322 return 0;
5323}
5324
5325
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005326static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5327 struct ieee80211_ht_capabilities *htcaps,
5328 struct ieee80211_ht_capabilities *htcaps_mask,
5329 int disabled)
5330{
5331 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005332 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005333
Hai Shalom74f70d42019-02-11 14:42:39 -08005334 if (disabled)
5335 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005336
5337 if (disabled)
5338 htcaps->ht_capabilities_info &= ~msk;
5339 else
5340 htcaps->ht_capabilities_info |= msk;
5341
5342 htcaps_mask->ht_capabilities_info |= msk;
5343
5344 return 0;
5345}
5346
5347
Hai Shalom74f70d42019-02-11 14:42:39 -08005348static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5349 struct ieee80211_ht_capabilities *htcaps,
5350 struct ieee80211_ht_capabilities *htcaps_mask,
5351 int tx_stbc)
5352{
5353 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5354
5355 if (tx_stbc == -1)
5356 return 0;
5357
5358 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5359
5360 if (tx_stbc < 0 || tx_stbc > 1) {
5361 wpa_msg(wpa_s, MSG_ERROR,
5362 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5363 return -EINVAL;
5364 }
5365
5366 htcaps_mask->ht_capabilities_info |= msk;
5367 htcaps->ht_capabilities_info &= ~msk;
5368 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5369
5370 return 0;
5371}
5372
5373
5374static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5375 struct ieee80211_ht_capabilities *htcaps,
5376 struct ieee80211_ht_capabilities *htcaps_mask,
5377 int rx_stbc)
5378{
5379 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5380
5381 if (rx_stbc == -1)
5382 return 0;
5383
5384 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5385
5386 if (rx_stbc < 0 || rx_stbc > 3) {
5387 wpa_msg(wpa_s, MSG_ERROR,
5388 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5389 return -EINVAL;
5390 }
5391
5392 htcaps_mask->ht_capabilities_info |= msk;
5393 htcaps->ht_capabilities_info &= ~msk;
5394 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5395
5396 return 0;
5397}
5398
5399
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005400void wpa_supplicant_apply_ht_overrides(
5401 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5402 struct wpa_driver_associate_params *params)
5403{
5404 struct ieee80211_ht_capabilities *htcaps;
5405 struct ieee80211_ht_capabilities *htcaps_mask;
5406
5407 if (!ssid)
5408 return;
5409
5410 params->disable_ht = ssid->disable_ht;
5411 if (!params->htcaps || !params->htcaps_mask)
5412 return;
5413
5414 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5415 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5416 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5417 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5418 ssid->disable_max_amsdu);
5419 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5420 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5421 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005422 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005423 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005424 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5425 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005426
5427 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005428 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005429 htcaps->ht_capabilities_info |= bit;
5430 htcaps_mask->ht_capabilities_info |= bit;
5431 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005432}
5433
5434#endif /* CONFIG_HT_OVERRIDES */
5435
5436
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005437#ifdef CONFIG_VHT_OVERRIDES
5438void wpa_supplicant_apply_vht_overrides(
5439 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5440 struct wpa_driver_associate_params *params)
5441{
5442 struct ieee80211_vht_capabilities *vhtcaps;
5443 struct ieee80211_vht_capabilities *vhtcaps_mask;
5444
5445 if (!ssid)
5446 return;
5447
5448 params->disable_vht = ssid->disable_vht;
5449
5450 vhtcaps = (void *) params->vhtcaps;
5451 vhtcaps_mask = (void *) params->vhtcaps_mask;
5452
5453 if (!vhtcaps || !vhtcaps_mask)
5454 return;
5455
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005456 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5457 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005458
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005459#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005460 if (ssid->disable_sgi) {
5461 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5462 VHT_CAP_SHORT_GI_160);
5463 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5464 VHT_CAP_SHORT_GI_160);
5465 wpa_msg(wpa_s, MSG_DEBUG,
5466 "disable-sgi override specified, vht-caps: 0x%x",
5467 vhtcaps->vht_capabilities_info);
5468 }
5469
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005470 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005471 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5472 int max_ampdu;
5473
5474 max_ampdu = (ssid->vht_capa &
5475 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5476 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005477
5478 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5479 wpa_set_ampdu_factor(wpa_s,
5480 (void *) params->htcaps,
5481 (void *) params->htcaps_mask,
5482 max_ampdu);
5483 }
5484#endif /* CONFIG_HT_OVERRIDES */
5485
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005486#define OVERRIDE_MCS(i) \
5487 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5488 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005489 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005490 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005491 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5492 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005493 } \
5494 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5495 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005496 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005497 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005498 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5499 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005500 }
5501
5502 OVERRIDE_MCS(1);
5503 OVERRIDE_MCS(2);
5504 OVERRIDE_MCS(3);
5505 OVERRIDE_MCS(4);
5506 OVERRIDE_MCS(5);
5507 OVERRIDE_MCS(6);
5508 OVERRIDE_MCS(7);
5509 OVERRIDE_MCS(8);
5510}
5511#endif /* CONFIG_VHT_OVERRIDES */
5512
5513
Hai Shalomfdcde762020-04-02 11:19:20 -07005514#ifdef CONFIG_HE_OVERRIDES
5515void wpa_supplicant_apply_he_overrides(
5516 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5517 struct wpa_driver_associate_params *params)
5518{
5519 if (!ssid)
5520 return;
5521
5522 params->disable_he = ssid->disable_he;
5523}
5524#endif /* CONFIG_HE_OVERRIDES */
5525
5526
Dmitry Shmidt04949592012-07-19 12:16:46 -07005527static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5528{
5529#ifdef PCSC_FUNCS
5530 size_t len;
5531
5532 if (!wpa_s->conf->pcsc_reader)
5533 return 0;
5534
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005535 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005536 if (!wpa_s->scard)
5537 return 1;
5538
5539 if (wpa_s->conf->pcsc_pin &&
5540 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5541 scard_deinit(wpa_s->scard);
5542 wpa_s->scard = NULL;
5543 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5544 return -1;
5545 }
5546
5547 len = sizeof(wpa_s->imsi) - 1;
5548 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5549 scard_deinit(wpa_s->scard);
5550 wpa_s->scard = NULL;
5551 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5552 return -1;
5553 }
5554 wpa_s->imsi[len] = '\0';
5555
5556 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5557
5558 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5559 wpa_s->imsi, wpa_s->mnc_len);
5560
5561 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5562 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5563#endif /* PCSC_FUNCS */
5564
5565 return 0;
5566}
5567
5568
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005569int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5570{
5571 char *val, *pos;
5572
5573 ext_password_deinit(wpa_s->ext_pw);
5574 wpa_s->ext_pw = NULL;
5575 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5576
5577 if (!wpa_s->conf->ext_password_backend)
5578 return 0;
5579
5580 val = os_strdup(wpa_s->conf->ext_password_backend);
5581 if (val == NULL)
5582 return -1;
5583 pos = os_strchr(val, ':');
5584 if (pos)
5585 *pos++ = '\0';
5586
5587 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5588
5589 wpa_s->ext_pw = ext_password_init(val, pos);
5590 os_free(val);
5591 if (wpa_s->ext_pw == NULL) {
5592 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5593 return -1;
5594 }
5595 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5596
5597 return 0;
5598}
5599
5600
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005601#ifdef CONFIG_FST
5602
5603static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5604{
5605 struct wpa_supplicant *wpa_s = ctx;
5606
5607 return (is_zero_ether_addr(wpa_s->bssid) ||
5608 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5609}
5610
5611
5612static void wpas_fst_get_channel_info_cb(void *ctx,
5613 enum hostapd_hw_mode *hw_mode,
5614 u8 *channel)
5615{
5616 struct wpa_supplicant *wpa_s = ctx;
5617
5618 if (wpa_s->current_bss) {
5619 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5620 channel);
5621 } else if (wpa_s->hw.num_modes) {
5622 *hw_mode = wpa_s->hw.modes[0].mode;
5623 } else {
5624 WPA_ASSERT(0);
5625 *hw_mode = 0;
5626 }
5627}
5628
5629
5630static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5631{
5632 struct wpa_supplicant *wpa_s = ctx;
5633
5634 *modes = wpa_s->hw.modes;
5635 return wpa_s->hw.num_modes;
5636}
5637
5638
5639static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5640{
5641 struct wpa_supplicant *wpa_s = ctx;
5642
5643 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5644 wpa_s->fst_ies = fst_ies;
5645}
5646
5647
5648static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5649{
5650 struct wpa_supplicant *wpa_s = ctx;
5651
Paul Stewart092955c2017-02-06 09:13:09 -08005652 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5653 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5654 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5655 return -1;
5656 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005657 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005658 wpa_s->own_addr, wpa_s->bssid,
5659 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005660 0);
5661}
5662
5663
5664static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5665{
5666 struct wpa_supplicant *wpa_s = ctx;
5667
5668 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5669 return wpa_s->received_mb_ies;
5670}
5671
5672
5673static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5674 const u8 *buf, size_t size)
5675{
5676 struct wpa_supplicant *wpa_s = ctx;
5677 struct mb_ies_info info;
5678
5679 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5680
5681 if (!mb_ies_info_by_ies(&info, buf, size)) {
5682 wpabuf_free(wpa_s->received_mb_ies);
5683 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5684 }
5685}
5686
5687
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005688static const u8 * wpas_fst_get_peer_first(void *ctx,
5689 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005690 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005691{
5692 struct wpa_supplicant *wpa_s = ctx;
5693
5694 *get_ctx = NULL;
5695 if (!is_zero_ether_addr(wpa_s->bssid))
5696 return (wpa_s->received_mb_ies || !mb_only) ?
5697 wpa_s->bssid : NULL;
5698 return NULL;
5699}
5700
5701
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005702static const u8 * wpas_fst_get_peer_next(void *ctx,
5703 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005704 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005705{
5706 return NULL;
5707}
5708
5709void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5710 struct fst_wpa_obj *iface_obj)
5711{
5712 iface_obj->ctx = wpa_s;
5713 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5714 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5715 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5716 iface_obj->set_ies = wpas_fst_set_ies_cb;
5717 iface_obj->send_action = wpas_fst_send_action_cb;
5718 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5719 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5720 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5721 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5722}
5723#endif /* CONFIG_FST */
5724
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005725static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005726 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005727{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005728 struct wowlan_triggers *triggers;
5729 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005730
5731 if (!wpa_s->conf->wowlan_triggers)
5732 return 0;
5733
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005734 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5735 if (triggers) {
5736 ret = wpa_drv_wowlan(wpa_s, triggers);
5737 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005738 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005739 return ret;
5740}
5741
5742
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005743enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005744{
5745 if (freq < 3000)
5746 return BAND_2_4_GHZ;
5747 if (freq > 50000)
5748 return BAND_60_GHZ;
5749 return BAND_5_GHZ;
5750}
5751
5752
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005753unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005754{
5755 int i;
5756 unsigned int band = 0;
5757
5758 if (freqs) {
5759 /* freqs are specified for the radio work */
5760 for (i = 0; freqs[i]; i++)
5761 band |= wpas_freq_to_band(freqs[i]);
5762 } else {
5763 /*
5764 * freqs are not specified, implies all
5765 * the supported freqs by HW
5766 */
5767 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5768 if (wpa_s->hw.modes[i].num_channels != 0) {
5769 if (wpa_s->hw.modes[i].mode ==
5770 HOSTAPD_MODE_IEEE80211B ||
5771 wpa_s->hw.modes[i].mode ==
5772 HOSTAPD_MODE_IEEE80211G)
5773 band |= BAND_2_4_GHZ;
5774 else if (wpa_s->hw.modes[i].mode ==
5775 HOSTAPD_MODE_IEEE80211A)
5776 band |= BAND_5_GHZ;
5777 else if (wpa_s->hw.modes[i].mode ==
5778 HOSTAPD_MODE_IEEE80211AD)
5779 band |= BAND_60_GHZ;
5780 else if (wpa_s->hw.modes[i].mode ==
5781 HOSTAPD_MODE_IEEE80211ANY)
5782 band = BAND_2_4_GHZ | BAND_5_GHZ |
5783 BAND_60_GHZ;
5784 }
5785 }
5786 }
5787
5788 return band;
5789}
5790
5791
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005792static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5793 const char *rn)
5794{
5795 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5796 struct wpa_radio *radio;
5797
5798 while (rn && iface) {
5799 radio = iface->radio;
5800 if (radio && os_strcmp(rn, radio->name) == 0) {
5801 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5802 wpa_s->ifname, rn);
5803 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5804 return radio;
5805 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005806
5807 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005808 }
5809
5810 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5811 wpa_s->ifname, rn ? rn : "N/A");
5812 radio = os_zalloc(sizeof(*radio));
5813 if (radio == NULL)
5814 return NULL;
5815
5816 if (rn)
5817 os_strlcpy(radio->name, rn, sizeof(radio->name));
5818 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005819 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005820 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5821
5822 return radio;
5823}
5824
5825
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005826static void radio_work_free(struct wpa_radio_work *work)
5827{
5828 if (work->wpa_s->scan_work == work) {
5829 /* This should not really happen. */
5830 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5831 work->type, work, work->started);
5832 work->wpa_s->scan_work = NULL;
5833 }
5834
5835#ifdef CONFIG_P2P
5836 if (work->wpa_s->p2p_scan_work == work) {
5837 /* This should not really happen. */
5838 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5839 work->type, work, work->started);
5840 work->wpa_s->p2p_scan_work = NULL;
5841 }
5842#endif /* CONFIG_P2P */
5843
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005844 if (work->started) {
5845 work->wpa_s->radio->num_active_works--;
5846 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005847 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005848 work->type, work,
5849 work->wpa_s->radio->num_active_works);
5850 }
5851
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005852 dl_list_del(&work->list);
5853 os_free(work);
5854}
5855
5856
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005857static int radio_work_is_connect(struct wpa_radio_work *work)
5858{
5859 return os_strcmp(work->type, "sme-connect") == 0 ||
5860 os_strcmp(work->type, "connect") == 0;
5861}
5862
5863
5864static int radio_work_is_scan(struct wpa_radio_work *work)
5865{
5866 return os_strcmp(work->type, "scan") == 0 ||
5867 os_strcmp(work->type, "p2p-scan") == 0;
5868}
5869
5870
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005871static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5872{
5873 struct wpa_radio_work *active_work = NULL;
5874 struct wpa_radio_work *tmp;
5875
5876 /* Get the active work to know the type and band. */
5877 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5878 if (tmp->started) {
5879 active_work = tmp;
5880 break;
5881 }
5882 }
5883
5884 if (!active_work) {
5885 /* No active work, start one */
5886 radio->num_active_works = 0;
5887 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5888 list) {
5889 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005890 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005891 (((struct wpa_driver_scan_params *)
5892 tmp->ctx)->only_new_results ||
5893 tmp->wpa_s->clear_driver_scan_cache))
5894 continue;
5895 return tmp;
5896 }
5897 return NULL;
5898 }
5899
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005900 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005901 /*
5902 * If the active work is either connect or sme-connect,
5903 * do not parallelize them with other radio works.
5904 */
5905 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5906 "Do not parallelize radio work with %s",
5907 active_work->type);
5908 return NULL;
5909 }
5910
5911 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5912 if (tmp->started)
5913 continue;
5914
5915 /*
5916 * If connect or sme-connect are enqueued, parallelize only
5917 * those operations ahead of them in the queue.
5918 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005919 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005920 break;
5921
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005922 /* Serialize parallel scan and p2p_scan operations on the same
5923 * interface since the driver_nl80211 mechanism for tracking
5924 * scan cookies does not yet have support for this. */
5925 if (active_work->wpa_s == tmp->wpa_s &&
5926 radio_work_is_scan(active_work) &&
5927 radio_work_is_scan(tmp)) {
5928 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5929 "Do not start work '%s' when another work '%s' is already scheduled",
5930 tmp->type, active_work->type);
5931 continue;
5932 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005933 /*
5934 * Check that the radio works are distinct and
5935 * on different bands.
5936 */
5937 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5938 (active_work->bands != tmp->bands)) {
5939 /*
5940 * If a scan has to be scheduled through nl80211 scan
5941 * interface and if an external scan is already running,
5942 * do not schedule the scan since it is likely to get
5943 * rejected by kernel.
5944 */
5945 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005946 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005947 (((struct wpa_driver_scan_params *)
5948 tmp->ctx)->only_new_results ||
5949 tmp->wpa_s->clear_driver_scan_cache))
5950 continue;
5951
5952 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5953 "active_work:%s new_work:%s",
5954 active_work->type, tmp->type);
5955 return tmp;
5956 }
5957 }
5958
5959 /* Did not find a radio work to schedule in parallel. */
5960 return NULL;
5961}
5962
5963
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005964static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5965{
5966 struct wpa_radio *radio = eloop_ctx;
5967 struct wpa_radio_work *work;
5968 struct os_reltime now, diff;
5969 struct wpa_supplicant *wpa_s;
5970
5971 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005972 if (work == NULL) {
5973 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005974 return;
5975 }
5976
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005977 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5978 radio_list);
5979
5980 if (!(wpa_s &&
5981 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5982 if (work->started)
5983 return; /* already started and still in progress */
5984
Hai Shalom60840252021-02-19 19:02:11 -08005985 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005986 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5987 return;
5988 }
5989 } else {
5990 work = NULL;
5991 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5992 /* get the work to schedule next */
5993 work = radio_work_get_next_work(radio);
5994 }
5995 if (!work)
5996 return;
5997 }
5998
5999 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006000 os_get_reltime(&now);
6001 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006002 wpa_dbg(wpa_s, MSG_DEBUG,
6003 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006004 work->type, work, diff.sec, diff.usec);
6005 work->started = 1;
6006 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006007 radio->num_active_works++;
6008
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006009 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006010
6011 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6012 radio->num_active_works < MAX_ACTIVE_WORKS)
6013 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006014}
6015
6016
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006017/*
6018 * This function removes both started and pending radio works running on
6019 * the provided interface's radio.
6020 * Prior to the removal of the radio work, its callback (cb) is called with
6021 * deinit set to be 1. Each work's callback is responsible for clearing its
6022 * internal data and restoring to a correct state.
6023 * @wpa_s: wpa_supplicant data
6024 * @type: type of works to be removed
6025 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6026 * this interface's works.
6027 */
6028void radio_remove_works(struct wpa_supplicant *wpa_s,
6029 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006030{
6031 struct wpa_radio_work *work, *tmp;
6032 struct wpa_radio *radio = wpa_s->radio;
6033
6034 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6035 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006036 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006037 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006038
6039 /* skip other ifaces' works */
6040 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006041 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006042
6043 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6044 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006045 work->cb(work, 1);
6046 radio_work_free(work);
6047 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006048
6049 /* in case we removed the started work */
6050 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006051}
6052
6053
Roshan Pius3a1667e2018-07-03 15:17:14 -07006054void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6055{
6056 struct wpa_radio_work *work;
6057 struct wpa_radio *radio = wpa_s->radio;
6058
6059 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6060 if (work->ctx != ctx)
6061 continue;
6062 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6063 work->type, work, work->started ? " (started)" : "");
6064 radio_work_free(work);
6065 break;
6066 }
6067}
6068
6069
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006070static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6071{
6072 struct wpa_radio *radio = wpa_s->radio;
6073
6074 if (!radio)
6075 return;
6076
6077 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6078 wpa_s->ifname, radio->name);
6079 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006080 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006081 /* If the interface that triggered the external scan was removed, the
6082 * external scan is no longer running. */
6083 if (wpa_s == radio->external_scan_req_interface)
6084 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006085 wpa_s->radio = NULL;
6086 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006087 return; /* Interfaces remain for this radio */
6088
6089 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006090 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006091 os_free(radio);
6092}
6093
6094
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006095void radio_work_check_next(struct wpa_supplicant *wpa_s)
6096{
6097 struct wpa_radio *radio = wpa_s->radio;
6098
6099 if (dl_list_empty(&radio->work))
6100 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006101 if (wpa_s->ext_work_in_progress) {
6102 wpa_printf(MSG_DEBUG,
6103 "External radio work in progress - delay start of pending item");
6104 return;
6105 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006106 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6107 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6108}
6109
6110
6111/**
6112 * radio_add_work - Add a radio work item
6113 * @wpa_s: Pointer to wpa_supplicant data
6114 * @freq: Frequency of the offchannel operation in MHz or 0
6115 * @type: Unique identifier for each type of work
6116 * @next: Force as the next work to be executed
6117 * @cb: Callback function for indicating when radio is available
6118 * @ctx: Context pointer for the work (work->ctx in cb())
6119 * Returns: 0 on success, -1 on failure
6120 *
6121 * This function is used to request time for an operation that requires
6122 * exclusive radio control. Once the radio is available, the registered callback
6123 * function will be called. radio_work_done() must be called once the exclusive
6124 * radio operation has been completed, so that the radio is freed for other
6125 * operations. The special case of deinit=1 is used to free the context data
6126 * during interface removal. That does not allow the callback function to start
6127 * the radio operation, i.e., it must free any resources allocated for the radio
6128 * work and return.
6129 *
6130 * The @freq parameter can be used to indicate a single channel on which the
6131 * offchannel operation will occur. This may allow multiple radio work
6132 * operations to be performed in parallel if they apply for the same channel.
6133 * Setting this to 0 indicates that the work item may use multiple channels or
6134 * requires exclusive control of the radio.
6135 */
6136int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6137 const char *type, int next,
6138 void (*cb)(struct wpa_radio_work *work, int deinit),
6139 void *ctx)
6140{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006141 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006142 struct wpa_radio_work *work;
6143 int was_empty;
6144
6145 work = os_zalloc(sizeof(*work));
6146 if (work == NULL)
6147 return -1;
6148 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6149 os_get_reltime(&work->time);
6150 work->freq = freq;
6151 work->type = type;
6152 work->wpa_s = wpa_s;
6153 work->cb = cb;
6154 work->ctx = ctx;
6155
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006156 if (freq)
6157 work->bands = wpas_freq_to_band(freq);
6158 else if (os_strcmp(type, "scan") == 0 ||
6159 os_strcmp(type, "p2p-scan") == 0)
6160 work->bands = wpas_get_bands(wpa_s,
6161 ((struct wpa_driver_scan_params *)
6162 ctx)->freqs);
6163 else
6164 work->bands = wpas_get_bands(wpa_s, NULL);
6165
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006166 was_empty = dl_list_empty(&wpa_s->radio->work);
6167 if (next)
6168 dl_list_add(&wpa_s->radio->work, &work->list);
6169 else
6170 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6171 if (was_empty) {
6172 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6173 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006174 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6175 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6176 wpa_dbg(wpa_s, MSG_DEBUG,
6177 "Try to schedule a radio work (num_active_works=%u)",
6178 radio->num_active_works);
6179 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006180 }
6181
6182 return 0;
6183}
6184
6185
6186/**
6187 * radio_work_done - Indicate that a radio work item has been completed
6188 * @work: Completed work
6189 *
6190 * This function is called once the callback function registered with
6191 * radio_add_work() has completed its work.
6192 */
6193void radio_work_done(struct wpa_radio_work *work)
6194{
6195 struct wpa_supplicant *wpa_s = work->wpa_s;
6196 struct os_reltime now, diff;
6197 unsigned int started = work->started;
6198
6199 os_get_reltime(&now);
6200 os_reltime_sub(&now, &work->time, &diff);
6201 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6202 work->type, work, started ? "done" : "canceled",
6203 diff.sec, diff.usec);
6204 radio_work_free(work);
6205 if (started)
6206 radio_work_check_next(wpa_s);
6207}
6208
6209
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006210struct wpa_radio_work *
6211radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006212{
6213 struct wpa_radio_work *work;
6214 struct wpa_radio *radio = wpa_s->radio;
6215
6216 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6217 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006218 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006219 }
6220
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006221 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006222}
6223
6224
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006225static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006226 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006227{
6228 const char *ifname, *driver, *rn;
6229
6230 driver = iface->driver;
6231next_driver:
6232 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6233 return -1;
6234
6235 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6236 if (wpa_s->drv_priv == NULL) {
6237 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006238 int level = MSG_ERROR;
6239
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006240 pos = driver ? os_strchr(driver, ',') : NULL;
6241 if (pos) {
6242 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6243 "driver interface - try next driver wrapper");
6244 driver = pos + 1;
6245 goto next_driver;
6246 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006247
6248#ifdef CONFIG_MATCH_IFACE
6249 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6250 level = MSG_DEBUG;
6251#endif /* CONFIG_MATCH_IFACE */
6252 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006253 return -1;
6254 }
6255 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6256 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6257 "driver_param '%s'", wpa_s->conf->driver_param);
6258 return -1;
6259 }
6260
6261 ifname = wpa_drv_get_ifname(wpa_s);
6262 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6263 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6264 "interface name with '%s'", ifname);
6265 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6266 }
6267
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006268 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006269 if (rn && rn[0] == '\0')
6270 rn = NULL;
6271
6272 wpa_s->radio = radio_add_interface(wpa_s, rn);
6273 if (wpa_s->radio == NULL)
6274 return -1;
6275
6276 return 0;
6277}
6278
6279
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006280#ifdef CONFIG_GAS_SERVER
6281
6282static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6283 unsigned int freq, const u8 *dst,
6284 const u8 *src, const u8 *bssid,
6285 const u8 *data, size_t data_len,
6286 enum offchannel_send_action_result result)
6287{
6288 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6289 " result=%s",
6290 freq, MAC2STR(dst),
6291 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6292 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6293 "FAILED"));
6294 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6295 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6296}
6297
6298
6299static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6300 struct wpabuf *buf, unsigned int wait_time)
6301{
6302 struct wpa_supplicant *wpa_s = ctx;
6303 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6304
6305 if (wait_time > wpa_s->max_remain_on_chan)
6306 wait_time = wpa_s->max_remain_on_chan;
6307
6308 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6309 wpabuf_head(buf), wpabuf_len(buf),
6310 wait_time, wpas_gas_server_tx_status, 0);
6311}
6312
6313#endif /* CONFIG_GAS_SERVER */
6314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006315static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006316 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006317{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006318 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006319 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006320 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006321
6322 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6323 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6324 iface->confname ? iface->confname : "N/A",
6325 iface->driver ? iface->driver : "default",
6326 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6327 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6328
6329 if (iface->confname) {
6330#ifdef CONFIG_BACKEND_FILE
6331 wpa_s->confname = os_rel2abs_path(iface->confname);
6332 if (wpa_s->confname == NULL) {
6333 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6334 "for configuration file '%s'.",
6335 iface->confname);
6336 return -1;
6337 }
6338 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6339 iface->confname, wpa_s->confname);
6340#else /* CONFIG_BACKEND_FILE */
6341 wpa_s->confname = os_strdup(iface->confname);
6342#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006343 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006344 if (wpa_s->conf == NULL) {
6345 wpa_printf(MSG_ERROR, "Failed to read or parse "
6346 "configuration '%s'.", wpa_s->confname);
6347 return -1;
6348 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006349 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006350 if (wpa_s->confanother &&
6351 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6352 wpa_printf(MSG_ERROR,
6353 "Failed to read or parse configuration '%s'.",
6354 wpa_s->confanother);
6355 return -1;
6356 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006357
6358 /*
6359 * Override ctrl_interface and driver_param if set on command
6360 * line.
6361 */
6362 if (iface->ctrl_interface) {
6363 os_free(wpa_s->conf->ctrl_interface);
6364 wpa_s->conf->ctrl_interface =
6365 os_strdup(iface->ctrl_interface);
6366 }
6367
6368 if (iface->driver_param) {
6369 os_free(wpa_s->conf->driver_param);
6370 wpa_s->conf->driver_param =
6371 os_strdup(iface->driver_param);
6372 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006373
6374 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6375 os_free(wpa_s->conf->ctrl_interface);
6376 wpa_s->conf->ctrl_interface = NULL;
6377 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006378 } else
6379 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6380 iface->driver_param);
6381
6382 if (wpa_s->conf == NULL) {
6383 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6384 return -1;
6385 }
6386
6387 if (iface->ifname == NULL) {
6388 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6389 return -1;
6390 }
6391 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6392 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6393 iface->ifname);
6394 return -1;
6395 }
6396 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006397#ifdef CONFIG_MATCH_IFACE
6398 wpa_s->matched = iface->matched;
6399#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006400
6401 if (iface->bridge_ifname) {
6402 if (os_strlen(iface->bridge_ifname) >=
6403 sizeof(wpa_s->bridge_ifname)) {
6404 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6405 "name '%s'.", iface->bridge_ifname);
6406 return -1;
6407 }
6408 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6409 sizeof(wpa_s->bridge_ifname));
6410 }
6411
6412 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006413 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6414 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006415
6416 /* Initialize driver interface and register driver event handler before
6417 * L2 receive handler so that association events are processed before
6418 * EAPOL-Key packets if both become available for the same select()
6419 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006420 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006421 return -1;
6422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006423 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6424 return -1;
6425
6426 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6427 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6428 NULL);
6429 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6430
6431 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6432 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6433 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6434 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6435 "dot11RSNAConfigPMKLifetime");
6436 return -1;
6437 }
6438
6439 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6440 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6441 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6442 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6443 "dot11RSNAConfigPMKReauthThreshold");
6444 return -1;
6445 }
6446
6447 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6448 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6449 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6450 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6451 "dot11RSNAConfigSATimeout");
6452 return -1;
6453 }
6454
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006455 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6456 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006457 &wpa_s->hw.flags,
6458 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006459 if (wpa_s->hw.modes) {
6460 u16 i;
6461
6462 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6463 if (wpa_s->hw.modes[i].vht_capab) {
6464 wpa_s->hw_capab = CAPAB_VHT;
6465 break;
6466 }
6467
6468 if (wpa_s->hw.modes[i].ht_capab &
6469 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6470 wpa_s->hw_capab = CAPAB_HT40;
6471 else if (wpa_s->hw.modes[i].ht_capab &&
6472 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6473 wpa_s->hw_capab = CAPAB_HT;
6474 }
6475 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006476
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006477 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6478 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006479 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006480 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006481 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006482 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006483 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006484 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006485 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006486 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006487 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6488 wpa_s->max_sched_scan_plan_interval =
6489 capa.max_sched_scan_plan_interval;
6490 wpa_s->max_sched_scan_plan_iterations =
6491 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006492 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6493 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006494 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6495 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006496 wpa_s->extended_capa = capa.extended_capa;
6497 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6498 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006499 wpa_s->num_multichan_concurrent =
6500 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006501 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6502
6503 if (capa.mac_addr_rand_scan_supported)
6504 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6505 if (wpa_s->sched_scan_supported &&
6506 capa.mac_addr_rand_sched_scan_supported)
6507 wpa_s->mac_addr_rand_supported |=
6508 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006509
6510 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6511 if (wpa_s->extended_capa &&
6512 wpa_s->extended_capa_len >= 3 &&
6513 wpa_s->extended_capa[2] & 0x40)
6514 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006515 }
6516 if (wpa_s->max_remain_on_chan == 0)
6517 wpa_s->max_remain_on_chan = 1000;
6518
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006519 /*
6520 * Only take p2p_mgmt parameters when P2P Device is supported.
6521 * Doing it here as it determines whether l2_packet_init() will be done
6522 * during wpa_supplicant_driver_init().
6523 */
6524 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6525 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006526
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006527 if (wpa_s->num_multichan_concurrent == 0)
6528 wpa_s->num_multichan_concurrent = 1;
6529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006530 if (wpa_supplicant_driver_init(wpa_s) < 0)
6531 return -1;
6532
6533#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006534 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006535 return -1;
6536#endif /* CONFIG_TDLS */
6537
6538 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6539 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6540 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6541 return -1;
6542 }
6543
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006544#ifdef CONFIG_FST
6545 if (wpa_s->conf->fst_group_id) {
6546 struct fst_iface_cfg cfg;
6547 struct fst_wpa_obj iface_obj;
6548
6549 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6550 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6551 sizeof(cfg.group_id));
6552 cfg.priority = wpa_s->conf->fst_priority;
6553 cfg.llt = wpa_s->conf->fst_llt;
6554
6555 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6556 &iface_obj, &cfg);
6557 if (!wpa_s->fst) {
6558 wpa_msg(wpa_s, MSG_ERROR,
6559 "FST: Cannot attach iface %s to group %s",
6560 wpa_s->ifname, cfg.group_id);
6561 return -1;
6562 }
6563 }
6564#endif /* CONFIG_FST */
6565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006566 if (wpas_wps_init(wpa_s))
6567 return -1;
6568
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006569#ifdef CONFIG_GAS_SERVER
6570 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6571 if (!wpa_s->gas_server) {
6572 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6573 return -1;
6574 }
6575#endif /* CONFIG_GAS_SERVER */
6576
6577#ifdef CONFIG_DPP
6578 if (wpas_dpp_init(wpa_s) < 0)
6579 return -1;
6580#endif /* CONFIG_DPP */
6581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006582 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6583 return -1;
6584 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6585
6586 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6587 if (wpa_s->ctrl_iface == NULL) {
6588 wpa_printf(MSG_ERROR,
6589 "Failed to initialize control interface '%s'.\n"
6590 "You may have another wpa_supplicant process "
6591 "already running or the file was\n"
6592 "left by an unclean termination of wpa_supplicant "
6593 "in which case you will need\n"
6594 "to manually remove this file before starting "
6595 "wpa_supplicant again.\n",
6596 wpa_s->conf->ctrl_interface);
6597 return -1;
6598 }
6599
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006600 wpa_s->gas = gas_query_init(wpa_s);
6601 if (wpa_s->gas == NULL) {
6602 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6603 return -1;
6604 }
6605
Roshan Pius3a1667e2018-07-03 15:17:14 -07006606 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6607 wpa_s->p2p_mgmt) &&
6608 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006609 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6610 return -1;
6611 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006612
6613 if (wpa_bss_init(wpa_s) < 0)
6614 return -1;
6615
Paul Stewart092955c2017-02-06 09:13:09 -08006616#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6617#ifdef CONFIG_MESH
6618 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6619#endif /* CONFIG_MESH */
6620#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6621
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006622 /*
6623 * Set Wake-on-WLAN triggers, if configured.
6624 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6625 * have effect anyway when the interface is down).
6626 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006627 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006628 return -1;
6629
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006630#ifdef CONFIG_EAP_PROXY
6631{
6632 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006633 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6634 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006635 if (wpa_s->mnc_len > 0) {
6636 wpa_s->imsi[len] = '\0';
6637 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6638 wpa_s->imsi, wpa_s->mnc_len);
6639 } else {
6640 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6641 }
6642}
6643#endif /* CONFIG_EAP_PROXY */
6644
Dmitry Shmidt04949592012-07-19 12:16:46 -07006645 if (pcsc_reader_init(wpa_s) < 0)
6646 return -1;
6647
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006648 if (wpas_init_ext_pw(wpa_s) < 0)
6649 return -1;
6650
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006651 wpas_rrm_reset(wpa_s);
6652
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006653 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6654
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006655#ifdef CONFIG_HS20
6656 hs20_init(wpa_s);
6657#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006658#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006659 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006660 if ((wpa_s->conf->oce & OCE_STA) &&
6661 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6662 wpa_s->enable_oce = OCE_STA;
6663 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6664 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6665 /* TODO: Need to add STA-CFON support */
6666 wpa_printf(MSG_ERROR,
6667 "OCE STA-CFON feature is not yet supported");
6668 }
6669 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006670 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6671#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006672
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006673 wpa_supplicant_set_default_scan_ies(wpa_s);
6674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006675 return 0;
6676}
6677
6678
6679static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006680 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006681{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006682 struct wpa_global *global = wpa_s->global;
6683 struct wpa_supplicant *iface, *prev;
6684
6685 if (wpa_s == wpa_s->parent)
6686 wpas_p2p_group_remove(wpa_s, "*");
6687
6688 iface = global->ifaces;
6689 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006690 if (iface->p2pdev == wpa_s)
6691 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006692 if (iface == wpa_s || iface->parent != wpa_s) {
6693 iface = iface->next;
6694 continue;
6695 }
6696 wpa_printf(MSG_DEBUG,
6697 "Remove remaining child interface %s from parent %s",
6698 iface->ifname, wpa_s->ifname);
6699 prev = iface;
6700 iface = iface->next;
6701 wpa_supplicant_remove_iface(global, prev, terminate);
6702 }
6703
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006704 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006705 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006706 /*
6707 * Don't deauthenticate if WoWLAN is enable and not explicitly
6708 * been configured to disconnect.
6709 */
6710 if (!wpa_drv_get_wowlan(wpa_s) ||
6711 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006712 wpa_supplicant_deauthenticate(
6713 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006714
Hai Shalomfdcde762020-04-02 11:19:20 -07006715 wpa_drv_set_countermeasures(wpa_s, 0);
6716 wpa_clear_keys(wpa_s, NULL);
6717 } else {
6718 wpa_msg(wpa_s, MSG_INFO,
6719 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6720 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006721 }
6722
6723 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006724 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006725
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006726 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006727 radio_remove_interface(wpa_s);
6728
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006729#ifdef CONFIG_FST
6730 if (wpa_s->fst) {
6731 fst_detach(wpa_s->fst);
6732 wpa_s->fst = NULL;
6733 }
6734 if (wpa_s->received_mb_ies) {
6735 wpabuf_free(wpa_s->received_mb_ies);
6736 wpa_s->received_mb_ies = NULL;
6737 }
6738#endif /* CONFIG_FST */
6739
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006740 if (wpa_s->drv_priv)
6741 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006742
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006743 if (notify)
6744 wpas_notify_iface_removed(wpa_s);
6745
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006746 if (terminate)
6747 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006748
6749 if (wpa_s->ctrl_iface) {
6750 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6751 wpa_s->ctrl_iface = NULL;
6752 }
6753
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006754#ifdef CONFIG_MESH
6755 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08006756 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006757 wpa_s->ifmsh = NULL;
6758 }
6759#endif /* CONFIG_MESH */
6760
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006761 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006762 wpa_config_free(wpa_s->conf);
6763 wpa_s->conf = NULL;
6764 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006765
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006766 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006767 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006768
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006769 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006770}
6771
6772
Dmitry Shmidte4663042016-04-04 10:07:49 -07006773#ifdef CONFIG_MATCH_IFACE
6774
6775/**
6776 * wpa_supplicant_match_iface - Match an interface description to a name
6777 * @global: Pointer to global data from wpa_supplicant_init()
6778 * @ifname: Name of the interface to match
6779 * Returns: Pointer to the created interface description or %NULL on failure
6780 */
6781struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6782 const char *ifname)
6783{
6784 int i;
6785 struct wpa_interface *iface, *miface;
6786
6787 for (i = 0; i < global->params.match_iface_count; i++) {
6788 miface = &global->params.match_ifaces[i];
6789 if (!miface->ifname ||
6790 fnmatch(miface->ifname, ifname, 0) == 0) {
6791 iface = os_zalloc(sizeof(*iface));
6792 if (!iface)
6793 return NULL;
6794 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07006795 if (!miface->ifname)
6796 iface->matched = WPA_IFACE_MATCHED_NULL;
6797 else
6798 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006799 iface->ifname = ifname;
6800 return iface;
6801 }
6802 }
6803
6804 return NULL;
6805}
6806
6807
6808/**
6809 * wpa_supplicant_match_existing - Match existing interfaces
6810 * @global: Pointer to global data from wpa_supplicant_init()
6811 * Returns: 0 on success, -1 on failure
6812 */
6813static int wpa_supplicant_match_existing(struct wpa_global *global)
6814{
6815 struct if_nameindex *ifi, *ifp;
6816 struct wpa_supplicant *wpa_s;
6817 struct wpa_interface *iface;
6818
6819 ifp = if_nameindex();
6820 if (!ifp) {
6821 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6822 return -1;
6823 }
6824
6825 for (ifi = ifp; ifi->if_name; ifi++) {
6826 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6827 if (wpa_s)
6828 continue;
6829 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6830 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08006831 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006832 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006833 }
6834 }
6835
6836 if_freenameindex(ifp);
6837 return 0;
6838}
6839
6840#endif /* CONFIG_MATCH_IFACE */
6841
6842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006843/**
6844 * wpa_supplicant_add_iface - Add a new network interface
6845 * @global: Pointer to global data from wpa_supplicant_init()
6846 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006847 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006848 * Returns: Pointer to the created interface or %NULL on failure
6849 *
6850 * This function is used to add new network interfaces for %wpa_supplicant.
6851 * This can be called before wpa_supplicant_run() to add interfaces before the
6852 * main event loop has been started. In addition, new interfaces can be added
6853 * dynamically while %wpa_supplicant is already running. This could happen,
6854 * e.g., when a hotplug network adapter is inserted.
6855 */
6856struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006857 struct wpa_interface *iface,
6858 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006859{
6860 struct wpa_supplicant *wpa_s;
6861 struct wpa_interface t_iface;
6862 struct wpa_ssid *ssid;
6863
6864 if (global == NULL || iface == NULL)
6865 return NULL;
6866
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006867 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006868 if (wpa_s == NULL)
6869 return NULL;
6870
6871 wpa_s->global = global;
6872
6873 t_iface = *iface;
6874 if (global->params.override_driver) {
6875 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6876 "('%s' -> '%s')",
6877 iface->driver, global->params.override_driver);
6878 t_iface.driver = global->params.override_driver;
6879 }
6880 if (global->params.override_ctrl_interface) {
6881 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6882 "ctrl_interface ('%s' -> '%s')",
6883 iface->ctrl_interface,
6884 global->params.override_ctrl_interface);
6885 t_iface.ctrl_interface =
6886 global->params.override_ctrl_interface;
6887 }
6888 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6889 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6890 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006891 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006892 return NULL;
6893 }
6894
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006895 /* Notify the control interfaces about new iface */
6896 if (wpas_notify_iface_added(wpa_s)) {
6897 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6898 return NULL;
6899 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006900
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006901 /* Notify the control interfaces about new networks for non p2p mgmt
6902 * ifaces. */
6903 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006904 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6905 wpas_notify_network_added(wpa_s, ssid);
6906 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006907
6908 wpa_s->next = global->ifaces;
6909 global->ifaces = wpa_s;
6910
6911 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006912 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006914#ifdef CONFIG_P2P
6915 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006916 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006917 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006918 wpas_p2p_add_p2pdev_interface(
6919 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006920 wpa_printf(MSG_INFO,
6921 "P2P: Failed to enable P2P Device interface");
6922 /* Try to continue without. P2P will be disabled. */
6923 }
6924#endif /* CONFIG_P2P */
6925
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006926 return wpa_s;
6927}
6928
6929
6930/**
6931 * wpa_supplicant_remove_iface - Remove a network interface
6932 * @global: Pointer to global data from wpa_supplicant_init()
6933 * @wpa_s: Pointer to the network interface to be removed
6934 * Returns: 0 if interface was removed, -1 if interface was not found
6935 *
6936 * This function can be used to dynamically remove network interfaces from
6937 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6938 * addition, this function is used to remove all remaining interfaces when
6939 * %wpa_supplicant is terminated.
6940 */
6941int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006942 struct wpa_supplicant *wpa_s,
6943 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006944{
6945 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006946#ifdef CONFIG_MESH
6947 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6948 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006949 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006950#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006951
6952 /* Remove interface from the global list of interfaces */
6953 prev = global->ifaces;
6954 if (prev == wpa_s) {
6955 global->ifaces = wpa_s->next;
6956 } else {
6957 while (prev && prev->next != wpa_s)
6958 prev = prev->next;
6959 if (prev == NULL)
6960 return -1;
6961 prev->next = wpa_s->next;
6962 }
6963
6964 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6965
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006966#ifdef CONFIG_MESH
6967 if (mesh_if_created) {
6968 ifname = os_strdup(wpa_s->ifname);
6969 if (ifname == NULL) {
6970 wpa_dbg(wpa_s, MSG_ERROR,
6971 "mesh: Failed to malloc ifname");
6972 return -1;
6973 }
6974 }
6975#endif /* CONFIG_MESH */
6976
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006977 if (global->p2p_group_formation == wpa_s)
6978 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006979 if (global->p2p_invite_group == wpa_s)
6980 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006981 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006982
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006983#ifdef CONFIG_MESH
6984 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006985 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006986 os_free(ifname);
6987 }
6988#endif /* CONFIG_MESH */
6989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006990 return 0;
6991}
6992
6993
6994/**
6995 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6996 * @wpa_s: Pointer to the network interface
6997 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6998 */
6999const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7000{
7001 const char *eapol_method;
7002
7003 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7004 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7005 return "NO-EAP";
7006 }
7007
7008 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7009 if (eapol_method == NULL)
7010 return "UNKNOWN-EAP";
7011
7012 return eapol_method;
7013}
7014
7015
7016/**
7017 * wpa_supplicant_get_iface - Get a new network interface
7018 * @global: Pointer to global data from wpa_supplicant_init()
7019 * @ifname: Interface name
7020 * Returns: Pointer to the interface or %NULL if not found
7021 */
7022struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7023 const char *ifname)
7024{
7025 struct wpa_supplicant *wpa_s;
7026
7027 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7028 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7029 return wpa_s;
7030 }
7031 return NULL;
7032}
7033
7034
7035#ifndef CONFIG_NO_WPA_MSG
7036static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7037{
7038 struct wpa_supplicant *wpa_s = ctx;
7039 if (wpa_s == NULL)
7040 return NULL;
7041 return wpa_s->ifname;
7042}
7043#endif /* CONFIG_NO_WPA_MSG */
7044
7045
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007046#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7047#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7048#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7049
7050/* Periodic cleanup tasks */
7051static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7052{
7053 struct wpa_global *global = eloop_ctx;
7054 struct wpa_supplicant *wpa_s;
7055
7056 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7057 wpas_periodic, global, NULL);
7058
7059#ifdef CONFIG_P2P
7060 if (global->p2p)
7061 p2p_expire_peers(global->p2p);
7062#endif /* CONFIG_P2P */
7063
7064 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7065 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7066#ifdef CONFIG_AP
7067 ap_periodic(wpa_s);
7068#endif /* CONFIG_AP */
7069 }
7070}
7071
7072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007073/**
7074 * wpa_supplicant_init - Initialize %wpa_supplicant
7075 * @params: Parameters for %wpa_supplicant
7076 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7077 *
7078 * This function is used to initialize %wpa_supplicant. After successful
7079 * initialization, the returned data pointer can be used to add and remove
7080 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7081 */
7082struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7083{
7084 struct wpa_global *global;
7085 int ret, i;
7086
7087 if (params == NULL)
7088 return NULL;
7089
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007090#ifdef CONFIG_DRIVER_NDIS
7091 {
7092 void driver_ndis_init_ops(void);
7093 driver_ndis_init_ops();
7094 }
7095#endif /* CONFIG_DRIVER_NDIS */
7096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007097#ifndef CONFIG_NO_WPA_MSG
7098 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7099#endif /* CONFIG_NO_WPA_MSG */
7100
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007101 if (params->wpa_debug_file_path)
7102 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007103 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007104 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007105 if (params->wpa_debug_syslog)
7106 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007107 if (params->wpa_debug_tracing) {
7108 ret = wpa_debug_open_linux_tracing();
7109 if (ret) {
7110 wpa_printf(MSG_ERROR,
7111 "Failed to enable trace logging");
7112 return NULL;
7113 }
7114 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007115
7116 ret = eap_register_methods();
7117 if (ret) {
7118 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7119 if (ret == -2)
7120 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7121 "the same EAP type.");
7122 return NULL;
7123 }
7124
7125 global = os_zalloc(sizeof(*global));
7126 if (global == NULL)
7127 return NULL;
7128 dl_list_init(&global->p2p_srv_bonjour);
7129 dl_list_init(&global->p2p_srv_upnp);
7130 global->params.daemonize = params->daemonize;
7131 global->params.wait_for_monitor = params->wait_for_monitor;
7132 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7133 if (params->pid_file)
7134 global->params.pid_file = os_strdup(params->pid_file);
7135 if (params->ctrl_interface)
7136 global->params.ctrl_interface =
7137 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007138 if (params->ctrl_interface_group)
7139 global->params.ctrl_interface_group =
7140 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007141 if (params->override_driver)
7142 global->params.override_driver =
7143 os_strdup(params->override_driver);
7144 if (params->override_ctrl_interface)
7145 global->params.override_ctrl_interface =
7146 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007147#ifdef CONFIG_MATCH_IFACE
7148 global->params.match_iface_count = params->match_iface_count;
7149 if (params->match_iface_count) {
7150 global->params.match_ifaces =
7151 os_calloc(params->match_iface_count,
7152 sizeof(struct wpa_interface));
7153 os_memcpy(global->params.match_ifaces,
7154 params->match_ifaces,
7155 params->match_iface_count *
7156 sizeof(struct wpa_interface));
7157 }
7158#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007159#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007160 if (params->conf_p2p_dev)
7161 global->params.conf_p2p_dev =
7162 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007163#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007164 wpa_debug_level = global->params.wpa_debug_level =
7165 params->wpa_debug_level;
7166 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7167 params->wpa_debug_show_keys;
7168 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7169 params->wpa_debug_timestamp;
7170
Hai Shalomfdcde762020-04-02 11:19:20 -07007171 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007172
7173 if (eloop_init()) {
7174 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7175 wpa_supplicant_deinit(global);
7176 return NULL;
7177 }
7178
Jouni Malinen75ecf522011-06-27 15:19:46 -07007179 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007180
7181 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7182 if (global->ctrl_iface == NULL) {
7183 wpa_supplicant_deinit(global);
7184 return NULL;
7185 }
7186
7187 if (wpas_notify_supplicant_initialized(global)) {
7188 wpa_supplicant_deinit(global);
7189 return NULL;
7190 }
7191
7192 for (i = 0; wpa_drivers[i]; i++)
7193 global->drv_count++;
7194 if (global->drv_count == 0) {
7195 wpa_printf(MSG_ERROR, "No drivers enabled");
7196 wpa_supplicant_deinit(global);
7197 return NULL;
7198 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007199 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007200 if (global->drv_priv == NULL) {
7201 wpa_supplicant_deinit(global);
7202 return NULL;
7203 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007204
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007205#ifdef CONFIG_WIFI_DISPLAY
7206 if (wifi_display_init(global) < 0) {
7207 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7208 wpa_supplicant_deinit(global);
7209 return NULL;
7210 }
7211#endif /* CONFIG_WIFI_DISPLAY */
7212
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007213 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7214 wpas_periodic, global, NULL);
7215
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007216 return global;
7217}
7218
7219
7220/**
7221 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7222 * @global: Pointer to global data from wpa_supplicant_init()
7223 * Returns: 0 after successful event loop run, -1 on failure
7224 *
7225 * This function starts the main event loop and continues running as long as
7226 * there are any remaining events. In most cases, this function is running as
7227 * long as the %wpa_supplicant process in still in use.
7228 */
7229int wpa_supplicant_run(struct wpa_global *global)
7230{
7231 struct wpa_supplicant *wpa_s;
7232
7233 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007234 (wpa_supplicant_daemon(global->params.pid_file) ||
7235 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007236 return -1;
7237
Dmitry Shmidte4663042016-04-04 10:07:49 -07007238#ifdef CONFIG_MATCH_IFACE
7239 if (wpa_supplicant_match_existing(global))
7240 return -1;
7241#endif
7242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007243 if (global->params.wait_for_monitor) {
7244 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007245 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007246 wpa_supplicant_ctrl_iface_wait(
7247 wpa_s->ctrl_iface);
7248 }
7249
7250 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7251 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7252
7253 eloop_run();
7254
7255 return 0;
7256}
7257
7258
7259/**
7260 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7261 * @global: Pointer to global data from wpa_supplicant_init()
7262 *
7263 * This function is called to deinitialize %wpa_supplicant and to free all
7264 * allocated resources. Remaining network interfaces will also be removed.
7265 */
7266void wpa_supplicant_deinit(struct wpa_global *global)
7267{
7268 int i;
7269
7270 if (global == NULL)
7271 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007272
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007273 eloop_cancel_timeout(wpas_periodic, global, NULL);
7274
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007275#ifdef CONFIG_WIFI_DISPLAY
7276 wifi_display_deinit(global);
7277#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007278
7279 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007280 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007281
7282 if (global->ctrl_iface)
7283 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7284
7285 wpas_notify_supplicant_deinitialized(global);
7286
7287 eap_peer_unregister_methods();
7288#ifdef CONFIG_AP
7289 eap_server_unregister_methods();
7290#endif /* CONFIG_AP */
7291
7292 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7293 if (!global->drv_priv[i])
7294 continue;
7295 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7296 }
7297 os_free(global->drv_priv);
7298
7299 random_deinit();
7300
7301 eloop_destroy();
7302
7303 if (global->params.pid_file) {
7304 os_daemonize_terminate(global->params.pid_file);
7305 os_free(global->params.pid_file);
7306 }
7307 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007308 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007309 os_free(global->params.override_driver);
7310 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007311#ifdef CONFIG_MATCH_IFACE
7312 os_free(global->params.match_ifaces);
7313#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007314#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007315 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007316#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007317
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007318 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007319 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007320 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007322 os_free(global);
7323 wpa_debug_close_syslog();
7324 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007325 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007326}
7327
7328
7329void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7330{
7331 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7332 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7333 char country[3];
7334 country[0] = wpa_s->conf->country[0];
7335 country[1] = wpa_s->conf->country[1];
7336 country[2] = '\0';
7337 if (wpa_drv_set_country(wpa_s, country) < 0) {
7338 wpa_printf(MSG_ERROR, "Failed to set country code "
7339 "'%s'", country);
7340 }
7341 }
7342
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007343 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7344 wpas_init_ext_pw(wpa_s);
7345
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007346 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7347 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7348
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007349 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7350 struct wpa_driver_capa capa;
7351 int res = wpa_drv_get_capa(wpa_s, &capa);
7352
7353 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7354 wpa_printf(MSG_ERROR,
7355 "Failed to update wowlan_triggers to '%s'",
7356 wpa_s->conf->wowlan_triggers);
7357 }
7358
Hai Shalom81f62d82019-07-22 12:10:00 -07007359 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7360 wpa_supplicant_set_default_scan_ies(wpa_s);
7361
Hai Shalom899fcc72020-10-19 14:38:18 -07007362#ifdef CONFIG_BGSCAN
7363 /*
7364 * We default to global bgscan parameters only when per-network bgscan
7365 * parameters aren't set. Only bother resetting bgscan parameters if
7366 * this is the case.
7367 */
7368 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7369 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7370 wpa_s->wpa_state == WPA_COMPLETED)
7371 wpa_supplicant_reset_bgscan(wpa_s);
7372#endif /* CONFIG_BGSCAN */
7373
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007374#ifdef CONFIG_WPS
7375 wpas_wps_update_config(wpa_s);
7376#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007377 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007378 wpa_s->conf->changed_parameters = 0;
7379}
7380
7381
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007382void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007383{
7384 int i;
7385
7386 for (i = 0; i < *num_freqs; i++) {
7387 if (freqs[i] == freq)
7388 return;
7389 }
7390
7391 freqs[*num_freqs] = freq;
7392 (*num_freqs)++;
7393}
7394
7395
7396static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7397{
7398 struct wpa_bss *bss, *cbss;
7399 const int max_freqs = 10;
7400 int *freqs;
7401 int num_freqs = 0;
7402
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007403 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007404 if (freqs == NULL)
7405 return NULL;
7406
7407 cbss = wpa_s->current_bss;
7408
7409 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7410 if (bss == cbss)
7411 continue;
7412 if (bss->ssid_len == cbss->ssid_len &&
7413 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007414 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007415 add_freq(freqs, &num_freqs, bss->freq);
7416 if (num_freqs == max_freqs)
7417 break;
7418 }
7419 }
7420
7421 if (num_freqs == 0) {
7422 os_free(freqs);
7423 freqs = NULL;
7424 }
7425
7426 return freqs;
7427}
7428
7429
7430void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7431{
7432 int timeout;
7433 int count;
7434 int *freqs = NULL;
7435
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007436 wpas_connect_work_done(wpa_s);
7437
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007438 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007439 * Remove possible authentication timeout since the connection failed.
7440 */
7441 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7442
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007443 /*
Hai Shalom60840252021-02-19 19:02:11 -08007444 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007445 * generated based on local request to disconnect.
7446 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007447 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007448 wpa_s->own_disconnect_req = 0;
7449 wpa_dbg(wpa_s, MSG_DEBUG,
7450 "Ignore connection failure due to local request to disconnect");
7451 return;
7452 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007453 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007454 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7455 "indication since interface has been put into "
7456 "disconnected state");
7457 return;
7458 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007459 if (wpa_s->auto_reconnect_disabled) {
7460 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7461 "indication since auto connect is disabled");
7462 return;
7463 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007464
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007465 /*
Hai Shalom60840252021-02-19 19:02:11 -08007466 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007468 */
Hai Shalom60840252021-02-19 19:02:11 -08007469 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007470 if (count == 1 && wpa_s->current_bss) {
7471 /*
Hai Shalom60840252021-02-19 19:02:11 -08007472 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007473 * another BSS available for the same ESS, we should try that
7474 * next. Otherwise, we may as well try this one once more
7475 * before allowing other, likely worse, ESSes to be considered.
7476 */
7477 freqs = get_bss_freqs_in_ess(wpa_s);
7478 if (freqs) {
7479 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7480 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007481 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007482 /*
7483 * On the next scan, go through only the known channels
7484 * used in this ESS based on previous scans to speed up
7485 * common load balancing use case.
7486 */
7487 os_free(wpa_s->next_scan_freqs);
7488 wpa_s->next_scan_freqs = freqs;
7489 }
7490 }
7491
Hai Shalom899fcc72020-10-19 14:38:18 -07007492 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007493
Hai Shalom899fcc72020-10-19 14:38:18 -07007494 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007495 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7496 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007497 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007498 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007499 /*
7500 * Multiple consecutive connection failures mean that other APs are
7501 * either not available or have already been tried, so we can start
7502 * increasing the delay here to avoid constant scanning.
7503 */
7504 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007505 case 1:
7506 timeout = 100;
7507 break;
7508 case 2:
7509 timeout = 500;
7510 break;
7511 case 3:
7512 timeout = 1000;
7513 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007514 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007515 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007516 break;
7517 default:
7518 timeout = 10000;
7519 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007520 }
7521
Hai Shalom899fcc72020-10-19 14:38:18 -07007522 wpa_dbg(wpa_s, MSG_DEBUG,
7523 "Consecutive connection failures: %d --> request scan in %d ms",
7524 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007526 /*
7527 * TODO: if more than one possible AP is available in scan results,
7528 * could try the other ones before requesting a new scan.
7529 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007530
7531 /* speed up the connection attempt with normal scan */
7532 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007533 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7534 1000 * (timeout % 1000));
7535}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007536
7537
Hai Shalomce48b4a2018-09-05 11:41:35 -07007538#ifdef CONFIG_FILS
7539void fils_connection_failure(struct wpa_supplicant *wpa_s)
7540{
7541 struct wpa_ssid *ssid = wpa_s->current_ssid;
7542 const u8 *realm, *username, *rrk;
7543 size_t realm_len, username_len, rrk_len;
7544 u16 next_seq_num;
7545
7546 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7547 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7548 &username, &username_len,
7549 &realm, &realm_len, &next_seq_num,
7550 &rrk, &rrk_len) != 0 ||
7551 !realm)
7552 return;
7553
7554 wpa_hexdump_ascii(MSG_DEBUG,
7555 "FILS: Store last connection failure realm",
7556 realm, realm_len);
7557 os_free(wpa_s->last_con_fail_realm);
7558 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7559 if (wpa_s->last_con_fail_realm) {
7560 wpa_s->last_con_fail_realm_len = realm_len;
7561 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7562 }
7563}
7564#endif /* CONFIG_FILS */
7565
7566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007567int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7568{
7569 return wpa_s->conf->ap_scan == 2 ||
7570 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7571}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007572
Dmitry Shmidt04949592012-07-19 12:16:46 -07007573
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007574#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007575int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7576 struct wpa_ssid *ssid,
7577 const char *field,
7578 const char *value)
7579{
7580#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007581 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007582
7583 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7584 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7585 (const u8 *) value, os_strlen(value));
7586
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007587 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007588 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007589#else /* IEEE8021X_EAPOL */
7590 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7591 return -1;
7592#endif /* IEEE8021X_EAPOL */
7593}
7594
7595int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7596 struct wpa_ssid *ssid,
7597 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007598 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007599{
7600#ifdef IEEE8021X_EAPOL
7601 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007602 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007603
7604 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007605 case WPA_CTRL_REQ_EAP_IDENTITY:
7606 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007607 os_free(eap->imsi_identity);
7608 if (value == NULL)
7609 return -1;
7610 identity = os_strchr(value, ':');
7611 if (identity == NULL) {
7612 /* plain identity */
7613 eap->identity = (u8 *)os_strdup(value);
7614 eap->identity_len = os_strlen(value);
7615 } else {
7616 /* have both plain identity and encrypted identity */
7617 imsi_identity = value;
7618 *identity++ = '\0';
7619 /* plain identity */
7620 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7621 eap->imsi_identity_len = strlen(imsi_identity);
7622 /* encrypted identity */
7623 eap->identity = (u8 *)dup_binstr(identity,
7624 value_len - strlen(imsi_identity) - 1);
7625 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7626 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007627 eap->pending_req_identity = 0;
7628 if (ssid == wpa_s->current_ssid)
7629 wpa_s->reassociate = 1;
7630 break;
7631 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007632 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007633 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007634 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007635 eap->pending_req_password = 0;
7636 if (ssid == wpa_s->current_ssid)
7637 wpa_s->reassociate = 1;
7638 break;
7639 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007640 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007641 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007642 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007643 eap->pending_req_new_password = 0;
7644 if (ssid == wpa_s->current_ssid)
7645 wpa_s->reassociate = 1;
7646 break;
7647 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007648 str_clear_free(eap->cert.pin);
7649 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007650 eap->pending_req_pin = 0;
7651 if (ssid == wpa_s->current_ssid)
7652 wpa_s->reassociate = 1;
7653 break;
7654 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007655 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007656 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007657 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007658 os_free(eap->pending_req_otp);
7659 eap->pending_req_otp = NULL;
7660 eap->pending_req_otp_len = 0;
7661 break;
7662 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007663 str_clear_free(eap->cert.private_key_passwd);
7664 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007665 eap->pending_req_passphrase = 0;
7666 if (ssid == wpa_s->current_ssid)
7667 wpa_s->reassociate = 1;
7668 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007669 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007670 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007671 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007672 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007673 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007674 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7675 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7676 return -1;
7677 ssid->mem_only_psk = 1;
7678 if (ssid->passphrase)
7679 wpa_config_update_psk(ssid);
7680 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7681 wpa_supplicant_req_scan(wpa_s, 0, 0);
7682 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007683 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7684 if (eap->pending_ext_cert_check != PENDING_CHECK)
7685 return -1;
7686 if (os_strcmp(value, "good") == 0)
7687 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7688 else if (os_strcmp(value, "bad") == 0)
7689 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7690 else
7691 return -1;
7692 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007693 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007695 return -1;
7696 }
7697
7698 return 0;
7699#else /* IEEE8021X_EAPOL */
7700 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7701 return -1;
7702#endif /* IEEE8021X_EAPOL */
7703}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007704#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007705
7706
7707int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7708{
Hai Shalomfdcde762020-04-02 11:19:20 -07007709#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007710 int i;
7711 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007712#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007713
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007714 if (wpa_s->p2p_mgmt)
7715 return 1; /* no normal network profiles on p2p_mgmt interface */
7716
Dmitry Shmidt04949592012-07-19 12:16:46 -07007717 if (ssid == NULL)
7718 return 1;
7719
7720 if (ssid->disabled)
7721 return 1;
7722
Hai Shalomfdcde762020-04-02 11:19:20 -07007723#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007724 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007725 drv_enc = wpa_s->drv_enc;
7726 else
7727 drv_enc = (unsigned int) -1;
7728
7729 for (i = 0; i < NUM_WEP_KEYS; i++) {
7730 size_t len = ssid->wep_key_len[i];
7731 if (len == 0)
7732 continue;
7733 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7734 continue;
7735 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7736 continue;
7737 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7738 continue;
7739 return 1; /* invalid WEP key */
7740 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007741#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007742
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007743 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007744 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007745 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007746 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007747 return 1;
7748
Dmitry Shmidt04949592012-07-19 12:16:46 -07007749 return 0;
7750}
7751
7752
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007753int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7754{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007755 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7756 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7757 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7758 /*
7759 * Driver does not support BIP -- ignore pmf=1 default
7760 * since the connection with PMF would fail and the
7761 * configuration does not require PMF to be enabled.
7762 */
7763 return NO_MGMT_FRAME_PROTECTION;
7764 }
7765
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007766 if (ssid &&
7767 (ssid->key_mgmt &
7768 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7769 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7770 /*
7771 * Do not use the default PMF value for non-RSN networks
7772 * since PMF is available only with RSN and pmf=2
7773 * configuration would otherwise prevent connections to
7774 * all open networks.
7775 */
7776 return NO_MGMT_FRAME_PROTECTION;
7777 }
7778
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007779 return wpa_s->conf->pmf;
7780 }
7781
7782 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007783}
7784
7785
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007786int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007787{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007788 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007789 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007790 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007791 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007792 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007793}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007794
7795
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007796void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007797{
7798 struct wpa_ssid *ssid = wpa_s->current_ssid;
7799 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007800 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007801
7802 if (ssid == NULL) {
7803 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7804 "SSID block");
7805 return;
7806 }
7807
7808 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7809 return;
7810
7811 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007812
7813#ifdef CONFIG_P2P
7814 if (ssid->p2p_group &&
7815 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7816 /*
7817 * Skip the wait time since there is a short timeout on the
7818 * connection to a P2P group.
7819 */
7820 return;
7821 }
7822#endif /* CONFIG_P2P */
7823
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007824 if (ssid->auth_failures > 50)
7825 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007826 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007827 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007828 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007829 dur = 90;
7830 else if (ssid->auth_failures > 3)
7831 dur = 60;
7832 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007833 dur = 30;
7834 else if (ssid->auth_failures > 1)
7835 dur = 20;
7836 else
7837 dur = 10;
7838
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007839 if (ssid->auth_failures > 1 &&
7840 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7841 dur += os_random() % (ssid->auth_failures * 10);
7842
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007843 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007844 if (now.sec + dur <= ssid->disabled_until.sec)
7845 return;
7846
7847 ssid->disabled_until.sec = now.sec + dur;
7848
7849 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007850 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007851 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007852 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007853}
7854
7855
7856void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7857 struct wpa_ssid *ssid, int clear_failures)
7858{
7859 if (ssid == NULL)
7860 return;
7861
7862 if (ssid->disabled_until.sec) {
7863 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7864 "id=%d ssid=\"%s\"",
7865 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7866 }
7867 ssid->disabled_until.sec = 0;
7868 ssid->disabled_until.usec = 0;
7869 if (clear_failures)
7870 ssid->auth_failures = 0;
7871}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007872
7873
7874int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7875{
7876 size_t i;
7877
7878 if (wpa_s->disallow_aps_bssid == NULL)
7879 return 0;
7880
7881 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7882 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7883 bssid, ETH_ALEN) == 0)
7884 return 1;
7885 }
7886
7887 return 0;
7888}
7889
7890
7891int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7892 size_t ssid_len)
7893{
7894 size_t i;
7895
7896 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7897 return 0;
7898
7899 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7900 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7901 if (ssid_len == s->ssid_len &&
7902 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7903 return 1;
7904 }
7905
7906 return 0;
7907}
7908
7909
7910/**
7911 * wpas_request_connection - Request a new connection
7912 * @wpa_s: Pointer to the network interface
7913 *
7914 * This function is used to request a new connection to be found. It will mark
7915 * the interface to allow reassociation and request a new scan to find a
7916 * suitable network to connect to.
7917 */
7918void wpas_request_connection(struct wpa_supplicant *wpa_s)
7919{
7920 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007921 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007922 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007923 wpa_s->disconnected = 0;
7924 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007925 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007926
7927 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7928 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007929 else
7930 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007931}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007932
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007933
Roshan Pius02242d72016-08-09 15:31:48 -07007934/**
7935 * wpas_request_disconnection - Request disconnection
7936 * @wpa_s: Pointer to the network interface
7937 *
7938 * This function is used to request disconnection from the currently connected
7939 * network. This will stop any ongoing scans and initiate deauthentication.
7940 */
7941void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7942{
7943#ifdef CONFIG_SME
7944 wpa_s->sme.prev_bssid_set = 0;
7945#endif /* CONFIG_SME */
7946 wpa_s->reassociate = 0;
7947 wpa_s->disconnected = 1;
7948 wpa_supplicant_cancel_sched_scan(wpa_s);
7949 wpa_supplicant_cancel_scan(wpa_s);
7950 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7951 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007952 radio_remove_works(wpa_s, "connect", 0);
7953 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007954}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007955
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007956
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007957void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7958 struct wpa_used_freq_data *freqs_data,
7959 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007960{
7961 unsigned int i;
7962
7963 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7964 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007965 for (i = 0; i < len; i++) {
7966 struct wpa_used_freq_data *cur = &freqs_data[i];
7967 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7968 i, cur->freq, cur->flags);
7969 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007970}
7971
7972
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007973/*
7974 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007975 * are using the same radio as the current interface, and in addition, get
7976 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007977 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007978int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7979 struct wpa_used_freq_data *freqs_data,
7980 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007981{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007982 struct wpa_supplicant *ifs;
7983 u8 bssid[ETH_ALEN];
7984 int freq;
7985 unsigned int idx = 0, i;
7986
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007987 wpa_dbg(wpa_s, MSG_DEBUG,
7988 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007989 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007990
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007991 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7992 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007993 if (idx == len)
7994 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007995
7996 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7997 continue;
7998
7999 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008000 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8001 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008002 freq = ifs->current_ssid->frequency;
8003 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8004 freq = ifs->assoc_freq;
8005 else
8006 continue;
8007
8008 /* Hold only distinct freqs */
8009 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008010 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008011 break;
8012
8013 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008014 freqs_data[idx++].freq = freq;
8015
8016 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008017 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008018 WPA_FREQ_USED_BY_P2P_CLIENT :
8019 WPA_FREQ_USED_BY_INFRA_STATION;
8020 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008021 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008022
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008023 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008024 return idx;
8025}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008026
8027
8028/*
8029 * Find the operating frequencies of any of the virtual interfaces that
8030 * are using the same radio as the current interface.
8031 */
8032int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8033 int *freq_array, unsigned int len)
8034{
8035 struct wpa_used_freq_data *freqs_data;
8036 int num, i;
8037
8038 os_memset(freq_array, 0, sizeof(int) * len);
8039
8040 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8041 if (!freqs_data)
8042 return -1;
8043
8044 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8045 for (i = 0; i < num; i++)
8046 freq_array[i] = freqs_data[i].freq;
8047
8048 os_free(freqs_data);
8049
8050 return num;
8051}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008052
8053
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008054struct wpa_supplicant *
8055wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8056{
8057 switch (frame) {
8058#ifdef CONFIG_P2P
8059 case VENDOR_ELEM_PROBE_REQ_P2P:
8060 case VENDOR_ELEM_PROBE_RESP_P2P:
8061 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8062 case VENDOR_ELEM_BEACON_P2P_GO:
8063 case VENDOR_ELEM_P2P_PD_REQ:
8064 case VENDOR_ELEM_P2P_PD_RESP:
8065 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8066 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8067 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8068 case VENDOR_ELEM_P2P_INV_REQ:
8069 case VENDOR_ELEM_P2P_INV_RESP:
8070 case VENDOR_ELEM_P2P_ASSOC_REQ:
8071 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008072 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008073#endif /* CONFIG_P2P */
8074 default:
8075 return wpa_s;
8076 }
8077}
8078
8079
8080void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8081{
8082 unsigned int i;
8083 char buf[30];
8084
8085 wpa_printf(MSG_DEBUG, "Update vendor elements");
8086
8087 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8088 if (wpa_s->vendor_elem[i]) {
8089 int res;
8090
8091 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8092 if (!os_snprintf_error(sizeof(buf), res)) {
8093 wpa_hexdump_buf(MSG_DEBUG, buf,
8094 wpa_s->vendor_elem[i]);
8095 }
8096 }
8097 }
8098
8099#ifdef CONFIG_P2P
8100 if (wpa_s->parent == wpa_s &&
8101 wpa_s->global->p2p &&
8102 !wpa_s->global->p2p_disabled)
8103 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8104#endif /* CONFIG_P2P */
8105}
8106
8107
8108int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8109 const u8 *elem, size_t len)
8110{
8111 u8 *ie, *end;
8112
8113 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8114 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8115
8116 for (; ie + 1 < end; ie += 2 + ie[1]) {
8117 if (ie + len > end)
8118 break;
8119 if (os_memcmp(ie, elem, len) != 0)
8120 continue;
8121
8122 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8123 wpabuf_free(wpa_s->vendor_elem[frame]);
8124 wpa_s->vendor_elem[frame] = NULL;
8125 } else {
8126 os_memmove(ie, ie + len, end - (ie + len));
8127 wpa_s->vendor_elem[frame]->used -= len;
8128 }
8129 wpas_vendor_elem_update(wpa_s);
8130 return 0;
8131 }
8132
8133 return -1;
8134}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008135
8136
8137struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008138 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008139 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008140{
8141 u16 i;
8142
8143 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008144 if (modes[i].mode != mode ||
8145 !modes[i].num_channels || !modes[i].channels)
8146 continue;
8147 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8148 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008149 return &modes[i];
8150 }
8151
8152 return NULL;
8153}
8154
8155
8156static struct
8157wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8158 const u8 *bssid)
8159{
8160 struct wpa_bss_tmp_disallowed *bss;
8161
8162 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8163 struct wpa_bss_tmp_disallowed, list) {
8164 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8165 return bss;
8166 }
8167
8168 return NULL;
8169}
8170
8171
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008172static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8173{
8174 struct wpa_bss_tmp_disallowed *tmp;
8175 unsigned int num_bssid = 0;
8176 u8 *bssids;
8177 int ret;
8178
8179 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8180 if (!bssids)
8181 return -1;
8182 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8183 struct wpa_bss_tmp_disallowed, list) {
8184 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8185 ETH_ALEN);
8186 num_bssid++;
8187 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008188 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008189 os_free(bssids);
8190 return ret;
8191}
8192
8193
8194static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8195{
8196 struct wpa_supplicant *wpa_s = eloop_ctx;
8197 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8198
8199 /* Make sure the bss is not already freed */
8200 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8201 struct wpa_bss_tmp_disallowed, list) {
8202 if (bss == tmp) {
8203 dl_list_del(&tmp->list);
8204 os_free(tmp);
8205 wpa_set_driver_tmp_disallow_list(wpa_s);
8206 break;
8207 }
8208 }
8209}
8210
8211
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008212void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008213 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008214{
8215 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008216
8217 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8218 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008219 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008220 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008221 }
8222
8223 bss = os_malloc(sizeof(*bss));
8224 if (!bss) {
8225 wpa_printf(MSG_DEBUG,
8226 "Failed to allocate memory for temp disallow BSS");
8227 return;
8228 }
8229
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008230 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8231 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008232 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008233
8234finish:
8235 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008236 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8237 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008238}
8239
8240
Hai Shalom74f70d42019-02-11 14:42:39 -08008241int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8242 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008243{
Hai Shalom74f70d42019-02-11 14:42:39 -08008244 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008245
8246 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8247 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008248 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8249 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008250 break;
8251 }
8252 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008253 if (!disallowed)
8254 return 0;
8255
8256 if (disallowed->rssi_threshold != 0 &&
8257 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008258 return 0;
8259
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008260 return 1;
8261}
Hai Shalom81f62d82019-07-22 12:10:00 -07008262
8263
8264int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8265 unsigned int type, const u8 *addr,
8266 const u8 *mask)
8267{
8268 if ((addr && !mask) || (!addr && mask)) {
8269 wpa_printf(MSG_INFO,
8270 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8271 return -1;
8272 }
8273
8274 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8275 wpa_printf(MSG_INFO,
8276 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8277 return -1;
8278 }
8279
8280 if (type & MAC_ADDR_RAND_SCAN) {
8281 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8282 addr, mask))
8283 return -1;
8284 }
8285
8286 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8287 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8288 addr, mask))
8289 return -1;
8290
8291 if (wpa_s->sched_scanning && !wpa_s->pno)
8292 wpas_scan_restart_sched_scan(wpa_s);
8293 }
8294
8295 if (type & MAC_ADDR_RAND_PNO) {
8296 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8297 addr, mask))
8298 return -1;
8299
8300 if (wpa_s->pno) {
8301 wpas_stop_pno(wpa_s);
8302 wpas_start_pno(wpa_s);
8303 }
8304 }
8305
8306 return 0;
8307}
8308
8309
8310int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8311 unsigned int type)
8312{
8313 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8314 if (wpa_s->pno) {
8315 if (type & MAC_ADDR_RAND_PNO) {
8316 wpas_stop_pno(wpa_s);
8317 wpas_start_pno(wpa_s);
8318 }
8319 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8320 wpas_scan_restart_sched_scan(wpa_s);
8321 }
8322
8323 return 0;
8324}
Hai Shalomfdcde762020-04-02 11:19:20 -07008325
8326
8327int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8328 struct wpa_signal_info *si)
8329{
8330 int res;
8331
8332 if (!wpa_s->driver->signal_poll)
8333 return -1;
8334
8335 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8336
8337#ifdef CONFIG_TESTING_OPTIONS
8338 if (res == 0) {
8339 struct driver_signal_override *dso;
8340
8341 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8342 struct driver_signal_override, list) {
8343 if (os_memcmp(wpa_s->bssid, dso->bssid,
8344 ETH_ALEN) != 0)
8345 continue;
8346 wpa_printf(MSG_DEBUG,
8347 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8348 si->current_signal,
8349 dso->si_current_signal,
8350 si->avg_signal,
8351 dso->si_avg_signal,
8352 si->avg_beacon_signal,
8353 dso->si_avg_beacon_signal,
8354 si->current_noise,
8355 dso->si_current_noise);
8356 si->current_signal = dso->si_current_signal;
8357 si->avg_signal = dso->si_avg_signal;
8358 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8359 si->current_noise = dso->si_current_noise;
8360 break;
8361 }
8362 }
8363#endif /* CONFIG_TESTING_OPTIONS */
8364
8365 return res;
8366}
8367
8368
8369struct wpa_scan_results *
8370wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8371{
8372 struct wpa_scan_results *scan_res;
8373#ifdef CONFIG_TESTING_OPTIONS
8374 size_t idx;
8375#endif /* CONFIG_TESTING_OPTIONS */
8376
8377 if (!wpa_s->driver->get_scan_results2)
8378 return NULL;
8379
8380 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8381
8382#ifdef CONFIG_TESTING_OPTIONS
8383 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8384 struct driver_signal_override *dso;
8385 struct wpa_scan_res *res = scan_res->res[idx];
8386
8387 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8388 struct driver_signal_override, list) {
8389 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8390 continue;
8391 wpa_printf(MSG_DEBUG,
8392 "Override driver scan signal level %d->%d for "
8393 MACSTR,
8394 res->level, dso->scan_level,
8395 MAC2STR(res->bssid));
8396 res->flags |= WPA_SCAN_QUAL_INVALID;
8397 if (dso->scan_level < 0)
8398 res->flags |= WPA_SCAN_LEVEL_DBM;
8399 else
8400 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8401 res->level = dso->scan_level;
8402 break;
8403 }
8404 }
8405#endif /* CONFIG_TESTING_OPTIONS */
8406
8407 return scan_res;
8408}