blob: 224fb10ced7f532c310484dbf6134c9456f437af [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalom74f70d42019-02-11 14:42:39 -08003 * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080044#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080046#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080047#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "wpas_glue.h"
49#include "wps_supplicant.h"
50#include "ibss_rsn.h"
51#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "ap.h"
54#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070055#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "notify.h"
57#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059#include "bss.h"
60#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080061#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070062#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070063#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070064#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080065#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066#include "dpp_supplicant.h"
67#ifdef CONFIG_MESH
68#include "ap/ap_config.h"
69#include "ap/hostapd.h"
70#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070072const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073"wpa_supplicant v" VERSION_STR "\n"
Hai Shalom74f70d42019-02-11 14:42:39 -080074"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070076const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080077"This software may be distributed under the terms of the BSD license.\n"
78"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079#ifdef EAP_TLS_OPENSSL
80"\nThis product includes software developed by the OpenSSL Project\n"
81"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
82#endif /* EAP_TLS_OPENSSL */
83;
84
85#ifndef CONFIG_NO_STDOUT_DEBUG
86/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080088"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070089const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080090"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091"\n"
92"Redistribution and use in source and binary forms, with or without\n"
93"modification, are permitted provided that the following conditions are\n"
94"met:\n"
95"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070096const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097"1. Redistributions of source code must retain the above copyright\n"
98" notice, this list of conditions and the following disclaimer.\n"
99"\n"
100"2. Redistributions in binary form must reproduce the above copyright\n"
101" notice, this list of conditions and the following disclaimer in the\n"
102" documentation and/or other materials provided with the distribution.\n"
103"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
106" names of its contributors may be used to endorse or promote products\n"
107" derived from this software without specific prior written permission.\n"
108"\n"
109"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
110"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
111"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
112"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700113const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
115"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
116"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
117"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
118"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
119"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
120"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
121"\n";
122#endif /* CONFIG_NO_STDOUT_DEBUG */
123
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700124
125static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
126#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
127static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
128#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700129#ifdef CONFIG_OWE
130static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
131#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700132
133
Hai Shalomfdcde762020-04-02 11:19:20 -0700134#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700135/* Configure default/group WEP keys for static WEP */
136int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
137{
138 int i, set = 0;
139
140 for (i = 0; i < NUM_WEP_KEYS; i++) {
141 if (ssid->wep_key_len[i] == 0)
142 continue;
143
144 set = 1;
145 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
146 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700147 ssid->wep_key[i], ssid->wep_key_len[i],
148 i == ssid->wep_tx_keyidx ?
149 KEY_FLAG_GROUP_RX_TX_DEFAULT :
150 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151 }
152
153 return set;
154}
Hai Shalomfdcde762020-04-02 11:19:20 -0700155#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156
157
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700158int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
159 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160{
161 u8 key[32];
162 size_t keylen;
163 enum wpa_alg alg;
164 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800165 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166
167 /* IBSS/WPA-None uses only one key (Group) for both receiving and
168 * sending unicast and multicast packets. */
169
170 if (ssid->mode != WPAS_MODE_IBSS) {
171 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
172 "IBSS/ad-hoc) for WPA-None", ssid->mode);
173 return -1;
174 }
175
176 if (!ssid->psk_set) {
177 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
178 "WPA-None");
179 return -1;
180 }
181
182 switch (wpa_s->group_cipher) {
183 case WPA_CIPHER_CCMP:
184 os_memcpy(key, ssid->psk, 16);
185 keylen = 16;
186 alg = WPA_ALG_CCMP;
187 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700188 case WPA_CIPHER_GCMP:
189 os_memcpy(key, ssid->psk, 16);
190 keylen = 16;
191 alg = WPA_ALG_GCMP;
192 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 case WPA_CIPHER_TKIP:
194 /* WPA-None uses the same Michael MIC key for both TX and RX */
195 os_memcpy(key, ssid->psk, 16 + 8);
196 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
197 keylen = 32;
198 alg = WPA_ALG_TKIP;
199 break;
200 default:
201 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
202 "WPA-None", wpa_s->group_cipher);
203 return -1;
204 }
205
206 /* TODO: should actually remember the previously used seq#, both for TX
207 * and RX from each STA.. */
208
Hai Shalomfdcde762020-04-02 11:19:20 -0700209 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
210 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800211 os_memset(key, 0, sizeof(key));
212 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213}
214
215
216static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
217{
218 struct wpa_supplicant *wpa_s = eloop_ctx;
219 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700220 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
221 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
222 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223 bssid = wpa_s->pending_bssid;
224 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
225 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800226 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700227 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800229 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 wpa_s->reassociate = 1;
231
232 /*
233 * If we timed out, the AP or the local radio may be busy.
234 * So, wait a second until scanning again.
235 */
236 wpa_supplicant_req_scan(wpa_s, 1, 0);
237}
238
239
240/**
241 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
242 * @wpa_s: Pointer to wpa_supplicant data
243 * @sec: Number of seconds after which to time out authentication
244 * @usec: Number of microseconds after which to time out authentication
245 *
246 * This function is used to schedule a timeout for the current authentication
247 * attempt.
248 */
249void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
250 int sec, int usec)
251{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700252 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
254 return;
255
256 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
257 "%d usec", sec, usec);
258 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700259 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700260 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
261}
262
263
Roshan Pius3a1667e2018-07-03 15:17:14 -0700264/*
265 * wpas_auth_timeout_restart - Restart and change timeout for authentication
266 * @wpa_s: Pointer to wpa_supplicant data
267 * @sec_diff: difference in seconds applied to original timeout value
268 */
269void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
270{
271 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
272
273 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
274 wpa_dbg(wpa_s, MSG_DEBUG,
275 "Authentication timeout restart: %d sec", new_sec);
276 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
277 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
278 wpa_s, NULL);
279 }
280}
281
282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283/**
284 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
285 * @wpa_s: Pointer to wpa_supplicant data
286 *
287 * This function is used to cancel authentication timeout scheduled with
288 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
289 * been completed.
290 */
291void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
292{
293 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
294 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800295 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700296 os_free(wpa_s->last_con_fail_realm);
297 wpa_s->last_con_fail_realm = NULL;
298 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299}
300
301
302/**
303 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
304 * @wpa_s: Pointer to wpa_supplicant data
305 *
306 * This function is used to configure EAPOL state machine based on the selected
307 * authentication mode.
308 */
309void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
310{
311#ifdef IEEE8021X_EAPOL
312 struct eapol_config eapol_conf;
313 struct wpa_ssid *ssid = wpa_s->current_ssid;
314
315#ifdef CONFIG_IBSS_RSN
316 if (ssid->mode == WPAS_MODE_IBSS &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
319 /*
320 * RSN IBSS authentication is per-STA and we can disable the
321 * per-BSSID EAPOL authentication.
322 */
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700324 eapol_sm_notify_eap_success(wpa_s->eapol, true);
325 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 return;
327 }
328#endif /* CONFIG_IBSS_RSN */
329
Hai Shalome21d4e82020-04-29 16:34:06 -0700330 eapol_sm_notify_eap_success(wpa_s->eapol, false);
331 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
334 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
335 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
336 else
337 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
338
339 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
340 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
341 eapol_conf.accept_802_1x_keys = 1;
342 eapol_conf.required_keys = 0;
343 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
344 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
345 }
346 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
347 eapol_conf.required_keys |=
348 EAPOL_REQUIRE_KEY_BROADCAST;
349 }
350
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 eapol_conf.required_keys = 0;
353 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700354 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 eapol_conf.workaround = ssid->eap_workaround;
356 eapol_conf.eap_disabled =
357 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700360 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800361
362#ifdef CONFIG_WPS
363 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
364 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
365 if (wpa_s->current_bss) {
366 struct wpabuf *ie;
367 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
368 WPS_IE_VENDOR_TYPE);
369 if (ie) {
370 if (wps_is_20(ie))
371 eapol_conf.wps |=
372 EAPOL_PEER_IS_WPS20_AP;
373 wpabuf_free(ie);
374 }
375 }
376 }
377#endif /* CONFIG_WPS */
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700380
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800381#ifdef CONFIG_MACSEC
382 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
383 ieee802_1x_create_preshared_mka(wpa_s, ssid);
384 else
385 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
386#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800387#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
391/**
392 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
393 * @wpa_s: Pointer to wpa_supplicant data
394 * @ssid: Configuration data for the network
395 *
396 * This function is used to configure WPA state machine and related parameters
397 * to a mode where WPA is not enabled. This is called as part of the
398 * authentication configuration when the selected network does not use WPA.
399 */
400void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
401 struct wpa_ssid *ssid)
402{
Hai Shalomfdcde762020-04-02 11:19:20 -0700403#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700405#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406
407 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
408 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
409 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
410 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
411 else
412 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
413 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
414 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700415 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700417 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
418 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
420 wpa_s->group_cipher = WPA_CIPHER_NONE;
421 wpa_s->mgmt_group_cipher = 0;
422
Hai Shalomfdcde762020-04-02 11:19:20 -0700423#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 for (i = 0; i < NUM_WEP_KEYS; i++) {
425 if (ssid->wep_key_len[i] > 5) {
426 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
427 wpa_s->group_cipher = WPA_CIPHER_WEP104;
428 break;
429 } else if (ssid->wep_key_len[i] > 0) {
430 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
431 wpa_s->group_cipher = WPA_CIPHER_WEP40;
432 break;
433 }
434 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700435#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
440 wpa_s->pairwise_cipher);
441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
443 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
445 pmksa_cache_clear_current(wpa_s->wpa);
446}
447
448
Dmitry Shmidt04949592012-07-19 12:16:46 -0700449void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800450{
451 int i;
452 if (wpa_s->hw.modes == NULL)
453 return;
454
455 for (i = 0; i < wpa_s->hw.num_modes; i++) {
456 os_free(wpa_s->hw.modes[i].channels);
457 os_free(wpa_s->hw.modes[i].rates);
458 }
459
460 os_free(wpa_s->hw.modes);
461 wpa_s->hw.modes = NULL;
462}
463
464
Hai Shalom74f70d42019-02-11 14:42:39 -0800465void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800466{
467 struct wpa_bss_tmp_disallowed *bss, *prev;
468
469 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
470 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700471 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800472 dl_list_del(&bss->list);
473 os_free(bss);
474 }
475}
476
477
Paul Stewart092955c2017-02-06 09:13:09 -0800478void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
479{
480 struct fils_hlp_req *req;
481
482 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
483 list)) != NULL) {
484 dl_list_del(&req->list);
485 wpabuf_free(req->pkt);
486 os_free(req);
487 }
488}
489
490
Hai Shalomfdcde762020-04-02 11:19:20 -0700491void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
492{
493 struct wpa_supplicant *wpa_s = eloop_ctx;
494
495 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
496 return;
497 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
498 wpa_bss_flush(wpa_s);
499}
500
501
502#ifdef CONFIG_TESTING_OPTIONS
503void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
504{
505 struct driver_signal_override *dso;
506
507 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
508 struct driver_signal_override, list))) {
509 dl_list_del(&dso->list);
510 os_free(dso);
511 }
512}
513#endif /* CONFIG_TESTING_OPTIONS */
514
515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
517{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700518 int i;
519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700521 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522 scard_deinit(wpa_s->scard);
523 wpa_s->scard = NULL;
524 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
525 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
526 l2_packet_deinit(wpa_s->l2);
527 wpa_s->l2 = NULL;
528 if (wpa_s->l2_br) {
529 l2_packet_deinit(wpa_s->l2_br);
530 wpa_s->l2_br = NULL;
531 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800532#ifdef CONFIG_TESTING_OPTIONS
533 l2_packet_deinit(wpa_s->l2_test);
534 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800535 os_free(wpa_s->get_pref_freq_list_override);
536 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700537 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
538 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800539 os_free(wpa_s->extra_sae_rejected_groups);
540 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700541 wpabuf_free(wpa_s->rsne_override_eapol);
542 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800543 wpabuf_free(wpa_s->rsnxe_override_assoc);
544 wpa_s->rsnxe_override_assoc = NULL;
545 wpabuf_free(wpa_s->rsnxe_override_eapol);
546 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700547 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800548#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 if (wpa_s->conf != NULL) {
551 struct wpa_ssid *ssid;
552 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
553 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554 }
555
556 os_free(wpa_s->confname);
557 wpa_s->confname = NULL;
558
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700559 os_free(wpa_s->confanother);
560 wpa_s->confanother = NULL;
561
Hai Shalomce48b4a2018-09-05 11:41:35 -0700562 os_free(wpa_s->last_con_fail_realm);
563 wpa_s->last_con_fail_realm = NULL;
564 wpa_s->last_con_fail_realm_len = 0;
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566 wpa_sm_set_eapol(wpa_s->wpa, NULL);
567 eapol_sm_deinit(wpa_s->eapol);
568 wpa_s->eapol = NULL;
569
570 rsn_preauth_deinit(wpa_s->wpa);
571
572#ifdef CONFIG_TDLS
573 wpa_tdls_deinit(wpa_s->wpa);
574#endif /* CONFIG_TDLS */
575
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800576 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800578 ptksa_cache_deinit(wpa_s->ptksa);
579 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 wpa_sm_deinit(wpa_s->wpa);
581 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800582 wpa_bssid_ignore_clear(wpa_s);
583
584#ifdef CONFIG_PASN
585 wpas_pasn_auth_stop(wpa_s);
586#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587
588 wpa_bss_deinit(wpa_s);
589
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700590 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_supplicant_cancel_scan(wpa_s);
592 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800593 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
594#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
595 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
596 wpa_s, NULL);
597#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700599 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700600 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpas_wps_deinit(wpa_s);
603
604 wpabuf_free(wpa_s->pending_eapol_rx);
605 wpa_s->pending_eapol_rx = NULL;
606
607#ifdef CONFIG_IBSS_RSN
608 ibss_rsn_deinit(wpa_s->ibss_rsn);
609 wpa_s->ibss_rsn = NULL;
610#endif /* CONFIG_IBSS_RSN */
611
612 sme_deinit(wpa_s);
613
614#ifdef CONFIG_AP
615 wpa_supplicant_ap_deinit(wpa_s);
616#endif /* CONFIG_AP */
617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800620#ifdef CONFIG_OFFCHANNEL
621 offchannel_deinit(wpa_s);
622#endif /* CONFIG_OFFCHANNEL */
623
624 wpa_supplicant_cancel_sched_scan(wpa_s);
625
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 os_free(wpa_s->next_scan_freqs);
627 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800628
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800629 os_free(wpa_s->manual_scan_freqs);
630 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700631 os_free(wpa_s->select_network_scan_freqs);
632 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800633
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700634 os_free(wpa_s->manual_sched_scan_freqs);
635 wpa_s->manual_sched_scan_freqs = NULL;
636
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800637 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
638
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700639 /*
640 * Need to remove any pending gas-query radio work before the
641 * gas_query_deinit() call because gas_query::work has not yet been set
642 * for works that have not been started. gas_query_free() will be unable
643 * to cancel such pending radio works and once the pending gas-query
644 * radio work eventually gets removed, the deinit notification call to
645 * gas_query_start_cb() would result in dereferencing freed memory.
646 */
647 if (wpa_s->radio)
648 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800649 gas_query_deinit(wpa_s->gas);
650 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 gas_server_deinit(wpa_s->gas_server);
652 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800653
654 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700655
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700656 ieee802_1x_dealloc_kay_sm(wpa_s);
657
Dmitry Shmidt04949592012-07-19 12:16:46 -0700658 os_free(wpa_s->bssid_filter);
659 wpa_s->bssid_filter = NULL;
660
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800661 os_free(wpa_s->disallow_aps_bssid);
662 wpa_s->disallow_aps_bssid = NULL;
663 os_free(wpa_s->disallow_aps_ssid);
664 wpa_s->disallow_aps_ssid = NULL;
665
Dmitry Shmidt04949592012-07-19 12:16:46 -0700666 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700667#ifdef CONFIG_WNM
668 wnm_deallocate_memory(wpa_s);
669#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670
671 ext_password_deinit(wpa_s->ext_pw);
672 wpa_s->ext_pw = NULL;
673
674 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800675 wpa_s->last_gas_resp = NULL;
676 wpabuf_free(wpa_s->prev_gas_resp);
677 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700678
679 os_free(wpa_s->last_scan_res);
680 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800681
682#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700683 if (wpa_s->drv_priv)
684 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700685 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800686#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700687
688 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
689 wpabuf_free(wpa_s->vendor_elem[i]);
690 wpa_s->vendor_elem[i] = NULL;
691 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800692
693 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800694
695 wpa_s->sched_scan_plans_num = 0;
696 os_free(wpa_s->sched_scan_plans);
697 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800698
699#ifdef CONFIG_MBO
700 wpa_s->non_pref_chan_num = 0;
701 os_free(wpa_s->non_pref_chan);
702 wpa_s->non_pref_chan = NULL;
703#endif /* CONFIG_MBO */
704
705 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700706
707 wpabuf_free(wpa_s->lci);
708 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800709 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800710
711#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
712#ifdef CONFIG_MESH
713 {
714 struct external_pmksa_cache *entry;
715
716 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
717 struct external_pmksa_cache,
718 list)) != NULL) {
719 dl_list_del(&entry->list);
720 os_free(entry->pmksa_cache);
721 os_free(entry);
722 }
723 }
724#endif /* CONFIG_MESH */
725#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
726
727 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800728
729 wpabuf_free(wpa_s->ric_ies);
730 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700731
732#ifdef CONFIG_DPP
733 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700734 dpp_global_deinit(wpa_s->dpp);
735 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700736#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800737
738#ifdef CONFIG_PASN
739 wpas_pasn_auth_stop(wpa_s);
740#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741}
742
743
744/**
745 * wpa_clear_keys - Clear keys configured for the driver
746 * @wpa_s: Pointer to wpa_supplicant data
747 * @addr: Previously used BSSID or %NULL if not available
748 *
749 * This function clears the encryption keys that has been previously configured
750 * for the driver.
751 */
752void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
753{
Hai Shalomc3565922019-10-28 11:58:20 -0700754 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755
756 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800757 for (i = 0; i < max; i++) {
758 if (wpa_s->keys_cleared & BIT(i))
759 continue;
760 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700761 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700763 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
764 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700766 if (!(wpa_s->keys_cleared & BIT(0)))
767 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
768 0, NULL, 0, KEY_FLAG_PAIRWISE);
769 if (!(wpa_s->keys_cleared & BIT(15)))
770 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
771 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 /* MLME-SETPROTECTION.request(None) */
773 wpa_drv_mlme_setprotection(
774 wpa_s, addr,
775 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
776 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
777 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800778 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779}
780
781
782/**
783 * wpa_supplicant_state_txt - Get the connection state name as a text string
784 * @state: State (wpa_state; WPA_*)
785 * Returns: The state name as a printable text string
786 */
787const char * wpa_supplicant_state_txt(enum wpa_states state)
788{
789 switch (state) {
790 case WPA_DISCONNECTED:
791 return "DISCONNECTED";
792 case WPA_INACTIVE:
793 return "INACTIVE";
794 case WPA_INTERFACE_DISABLED:
795 return "INTERFACE_DISABLED";
796 case WPA_SCANNING:
797 return "SCANNING";
798 case WPA_AUTHENTICATING:
799 return "AUTHENTICATING";
800 case WPA_ASSOCIATING:
801 return "ASSOCIATING";
802 case WPA_ASSOCIATED:
803 return "ASSOCIATED";
804 case WPA_4WAY_HANDSHAKE:
805 return "4WAY_HANDSHAKE";
806 case WPA_GROUP_HANDSHAKE:
807 return "GROUP_HANDSHAKE";
808 case WPA_COMPLETED:
809 return "COMPLETED";
810 default:
811 return "UNKNOWN";
812 }
813}
814
815
816#ifdef CONFIG_BGSCAN
817
Hai Shalom899fcc72020-10-19 14:38:18 -0700818static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
819{
820 if (wpa_s->bgscan_ssid) {
821 bgscan_deinit(wpa_s);
822 wpa_s->bgscan_ssid = NULL;
823 }
824}
825
826
827/**
828 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
829 * @wpa_s: Pointer to the wpa_supplicant data
830 *
831 * Stop, start, or reconfigure the scan parameters depending on the method.
832 */
833void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800835 const char *name;
836
837 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
838 name = wpa_s->current_ssid->bgscan;
839 else
840 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700841 if (!name || name[0] == '\0') {
842 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800843 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700844 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800845 if (wpas_driver_bss_selection(wpa_s))
846 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800847#ifdef CONFIG_P2P
848 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
849 return;
850#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851
852 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800853 if (wpa_s->current_ssid) {
854 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
856 "bgscan");
857 /*
858 * Live without bgscan; it is only used as a roaming
859 * optimization, so the initial connection is not
860 * affected.
861 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700862 } else {
863 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700865 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
866 0);
867 if (scan_res) {
868 bgscan_notify_scan(wpa_s, scan_res);
869 wpa_scan_results_free(scan_res);
870 }
871 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872 } else
873 wpa_s->bgscan_ssid = NULL;
874}
875
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876#endif /* CONFIG_BGSCAN */
877
878
Dmitry Shmidt04949592012-07-19 12:16:46 -0700879static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
880{
881 if (autoscan_init(wpa_s, 0))
882 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
883}
884
885
886static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
887{
888 autoscan_deinit(wpa_s);
889}
890
891
892void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
893{
894 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
895 wpa_s->wpa_state == WPA_SCANNING) {
896 autoscan_deinit(wpa_s);
897 wpa_supplicant_start_autoscan(wpa_s);
898 }
899}
900
901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902/**
903 * wpa_supplicant_set_state - Set current connection state
904 * @wpa_s: Pointer to wpa_supplicant data
905 * @state: The new connection state
906 *
907 * This function is called whenever the connection state changes, e.g.,
908 * association is completed for WPA/WPA2 4-Way Handshake is started.
909 */
910void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
911 enum wpa_states state)
912{
913 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700914#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700915 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700916#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917
918 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
919 wpa_supplicant_state_txt(wpa_s->wpa_state),
920 wpa_supplicant_state_txt(state));
921
Hai Shalom74f70d42019-02-11 14:42:39 -0800922 if (state == WPA_COMPLETED &&
923 os_reltime_initialized(&wpa_s->roam_start)) {
924 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
925 wpa_s->roam_start.sec = 0;
926 wpa_s->roam_start.usec = 0;
927 wpas_notify_auth_changed(wpa_s);
928 wpas_notify_roam_time(wpa_s);
929 wpas_notify_roam_complete(wpa_s);
930 } else if (state == WPA_DISCONNECTED &&
931 os_reltime_initialized(&wpa_s->roam_start)) {
932 wpa_s->roam_start.sec = 0;
933 wpa_s->roam_start.usec = 0;
934 wpa_s->roam_time.sec = 0;
935 wpa_s->roam_time.usec = 0;
936 wpas_notify_roam_complete(wpa_s);
937 }
938
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800939 if (state == WPA_INTERFACE_DISABLED) {
940 /* Assure normal scan when interface is restored */
941 wpa_s->normal_scans = 0;
942 }
943
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700944 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800945 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700946 /* Reinitialize normal_scan counter */
947 wpa_s->normal_scans = 0;
948 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800949
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700950#ifdef CONFIG_P2P
951 /*
952 * P2PS client has to reply to Probe Request frames received on the
953 * group operating channel. Enable Probe Request frame reporting for
954 * P2P connected client in case p2p_cli_probe configuration property is
955 * set to 1.
956 */
957 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
958 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
959 wpa_s->current_ssid->p2p_group) {
960 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
961 wpa_dbg(wpa_s, MSG_DEBUG,
962 "P2P: Enable CLI Probe Request RX reporting");
963 wpa_s->p2p_cli_probe =
964 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
965 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
966 wpa_dbg(wpa_s, MSG_DEBUG,
967 "P2P: Disable CLI Probe Request RX reporting");
968 wpa_s->p2p_cli_probe = 0;
969 wpa_drv_probe_req_report(wpa_s, 0);
970 }
971 }
972#endif /* CONFIG_P2P */
973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 if (state != WPA_SCANNING)
975 wpa_supplicant_notify_scanning(wpa_s, 0);
976
977 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700979 int fils_hlp_sent = 0;
980
981#ifdef CONFIG_SME
982 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
983 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
984 fils_hlp_sent = 1;
985#endif /* CONFIG_SME */
986 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
987 wpa_auth_alg_fils(wpa_s->auth_alg))
988 fils_hlp_sent = 1;
989
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700990#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700992 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800993 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700995 ssid && ssid->id_str ? ssid->id_str : "",
996 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700997#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700998 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -0700999 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001 wpa_drv_set_operstate(wpa_s, 1);
1002#ifndef IEEE8021X_EAPOL
1003 wpa_drv_set_supp_port(wpa_s, 1);
1004#endif /* IEEE8021X_EAPOL */
1005 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001006 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001008
1009 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001010
1011#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1012 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001013 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001014#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001015#ifdef CONFIG_OWE
1016 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1017 wpas_update_owe_connect_params(wpa_s);
1018#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001019#ifdef CONFIG_HS20
1020 hs20_configure_frame_filters(wpa_s);
1021#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1023 state == WPA_ASSOCIATED) {
1024 wpa_s->new_connection = 1;
1025 wpa_drv_set_operstate(wpa_s, 0);
1026#ifndef IEEE8021X_EAPOL
1027 wpa_drv_set_supp_port(wpa_s, 0);
1028#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001029 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 }
1031 wpa_s->wpa_state = state;
1032
1033#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001034 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1035 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001036 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 wpa_supplicant_stop_bgscan(wpa_s);
1038#endif /* CONFIG_BGSCAN */
1039
Hai Shalom5f92bc92019-04-18 11:54:11 -07001040 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001041 wpa_supplicant_stop_autoscan(wpa_s);
1042
1043 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1044 wpa_supplicant_start_autoscan(wpa_s);
1045
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001046 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1047 wmm_ac_notify_disassoc(wpa_s);
1048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 if (wpa_s->wpa_state != old_state) {
1050 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1051
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001052 /*
1053 * Notify the P2P Device interface about a state change in one
1054 * of the interfaces.
1055 */
1056 wpas_p2p_indicate_state_change(wpa_s);
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 if (wpa_s->wpa_state == WPA_COMPLETED ||
1059 old_state == WPA_COMPLETED)
1060 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001061#ifdef CONFIG_DPP2
1062 if (wpa_s->wpa_state == WPA_COMPLETED)
1063 wpas_dpp_connected(wpa_s);
1064#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065 }
Hai Shalomc3565922019-10-28 11:58:20 -07001066#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1067 if (update_fils_connect_params)
1068 wpas_update_fils_connect_params(wpa_s);
1069#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070}
1071
1072
1073void wpa_supplicant_terminate_proc(struct wpa_global *global)
1074{
1075 int pending = 0;
1076#ifdef CONFIG_WPS
1077 struct wpa_supplicant *wpa_s = global->ifaces;
1078 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001079 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001080 if (wpas_wps_terminate_pending(wpa_s) == 1)
1081 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001082#ifdef CONFIG_P2P
1083 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1084 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1085 wpas_p2p_disconnect(wpa_s);
1086#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088 }
1089#endif /* CONFIG_WPS */
1090 if (pending)
1091 return;
1092 eloop_terminate();
1093}
1094
1095
1096static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1097{
1098 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 wpa_supplicant_terminate_proc(global);
1100}
1101
1102
1103void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1104{
1105 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001106 enum wpa_states new_state;
1107
1108 if (old_state == WPA_SCANNING)
1109 new_state = WPA_SCANNING;
1110 else
1111 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112
1113 wpa_s->pairwise_cipher = 0;
1114 wpa_s->group_cipher = 0;
1115 wpa_s->mgmt_group_cipher = 0;
1116 wpa_s->key_mgmt = 0;
1117 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001118 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119
1120 if (wpa_s->wpa_state != old_state)
1121 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1122}
1123
1124
1125/**
1126 * wpa_supplicant_reload_configuration - Reload configuration data
1127 * @wpa_s: Pointer to wpa_supplicant data
1128 * Returns: 0 on success or -1 if configuration parsing failed
1129 *
1130 * This function can be used to request that the configuration data is reloaded
1131 * (e.g., after configuration file change). This function is reloading
1132 * configuration only for one interface, so this may need to be called multiple
1133 * times if %wpa_supplicant is controlling multiple interfaces and all
1134 * interfaces need reconfiguration.
1135 */
1136int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1137{
1138 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 int reconf_ctrl;
1140 int old_ap_scan;
1141
1142 if (wpa_s->confname == NULL)
1143 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001144 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145 if (conf == NULL) {
1146 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1147 "file '%s' - exiting", wpa_s->confname);
1148 return -1;
1149 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001150 if (wpa_s->confanother &&
1151 !wpa_config_read(wpa_s->confanother, conf)) {
1152 wpa_msg(wpa_s, MSG_ERROR,
1153 "Failed to parse the configuration file '%s' - exiting",
1154 wpa_s->confanother);
1155 return -1;
1156 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001157
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 conf->changed_parameters = (unsigned int) -1;
1159
1160 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1161 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1162 os_strcmp(conf->ctrl_interface,
1163 wpa_s->conf->ctrl_interface) != 0);
1164
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001165 if (reconf_ctrl) {
1166 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 wpa_s->ctrl_iface = NULL;
1168 }
1169
1170 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001171 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001172 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1173 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001174 wpa_supplicant_deauthenticate(wpa_s,
1175 WLAN_REASON_DEAUTH_LEAVING);
1176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177
1178 /*
1179 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001182 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1183 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1184 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 /*
1186 * Clear forced success to clear EAP state for next
1187 * authentication.
1188 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001189 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 }
1191 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1192 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001193 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1195 rsn_preauth_deinit(wpa_s->wpa);
1196
1197 old_ap_scan = wpa_s->conf->ap_scan;
1198 wpa_config_free(wpa_s->conf);
1199 wpa_s->conf = conf;
1200 if (old_ap_scan != wpa_s->conf->ap_scan)
1201 wpas_notify_ap_scan_changed(wpa_s);
1202
1203 if (reconf_ctrl)
1204 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1205
1206 wpa_supplicant_update_config(wpa_s);
1207
1208 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001209 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_s->reassociate = 1;
1211 wpa_supplicant_req_scan(wpa_s, 0, 0);
1212 }
Hai Shalom60840252021-02-19 19:02:11 -08001213 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1215 return 0;
1216}
1217
1218
1219static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1220{
1221 struct wpa_global *global = signal_ctx;
1222 struct wpa_supplicant *wpa_s;
1223 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1224 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1225 sig);
1226 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1227 wpa_supplicant_terminate_proc(global);
1228 }
1229 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001230
1231 if (wpa_debug_reopen_file() < 0) {
1232 /* Ignore errors since we cannot really do much to fix this */
1233 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235}
1236
1237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1239 struct wpa_ssid *ssid,
1240 struct wpa_ie_data *ie)
1241{
1242 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1243 if (ret) {
1244 if (ret == -2) {
1245 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1246 "from association info");
1247 }
1248 return -1;
1249 }
1250
1251 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1252 "cipher suites");
1253 if (!(ie->group_cipher & ssid->group_cipher)) {
1254 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1255 "cipher 0x%x (mask 0x%x) - reject",
1256 ie->group_cipher, ssid->group_cipher);
1257 return -1;
1258 }
1259 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1260 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1261 "cipher 0x%x (mask 0x%x) - reject",
1262 ie->pairwise_cipher, ssid->pairwise_cipher);
1263 return -1;
1264 }
1265 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1266 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1267 "management 0x%x (mask 0x%x) - reject",
1268 ie->key_mgmt, ssid->key_mgmt);
1269 return -1;
1270 }
1271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001272 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001273 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1275 "that does not support management frame protection - "
1276 "reject");
1277 return -1;
1278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279
1280 return 0;
1281}
1282
1283
Hai Shalom021b0b52019-04-10 11:17:58 -07001284static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1285 int freq)
1286{
1287 if (!ie->has_group)
1288 ie->group_cipher = wpa_default_rsn_cipher(freq);
1289 if (!ie->has_pairwise)
1290 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1291 return (ie->group_cipher & ssid->group_cipher) &&
1292 (ie->pairwise_cipher & ssid->pairwise_cipher);
1293}
1294
1295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296/**
1297 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1298 * @wpa_s: Pointer to wpa_supplicant data
1299 * @bss: Scan results for the selected BSS, or %NULL if not available
1300 * @ssid: Configuration data for the selected network
1301 * @wpa_ie: Buffer for the WPA/RSN IE
1302 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1303 * used buffer length in case the functions returns success.
1304 * Returns: 0 on success or -1 on failure
1305 *
1306 * This function is used to configure authentication and encryption parameters
1307 * based on the network configuration and scan result for the selected BSS (if
1308 * available).
1309 */
1310int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1311 struct wpa_bss *bss, struct wpa_ssid *ssid,
1312 u8 *wpa_ie, size_t *wpa_ie_len)
1313{
1314 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001315 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001316 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317
1318 if (bss) {
1319 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1320 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001321 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001322 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001323 } else {
1324 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1325 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001326
1327 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1328 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001329 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 (ie.key_mgmt & ssid->key_mgmt)) {
1331 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1332 proto = WPA_PROTO_RSN;
1333 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001334 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335 (ie.group_cipher & ssid->group_cipher) &&
1336 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1337 (ie.key_mgmt & ssid->key_mgmt)) {
1338 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1339 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001340#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001341 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1342 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1343 (ie.group_cipher & ssid->group_cipher) &&
1344 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1345 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001346 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001347 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001348 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1349 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1350 (ie.group_cipher & ssid->group_cipher) &&
1351 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1352 (ie.key_mgmt & ssid->key_mgmt)) {
1353 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1354 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001355#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356 } else if (bss) {
1357 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001358 wpa_dbg(wpa_s, MSG_DEBUG,
1359 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1360 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1361 ssid->key_mgmt);
1362 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1363 MAC2STR(bss->bssid),
1364 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1365 bss_wpa ? " WPA" : "",
1366 bss_rsn ? " RSN" : "",
1367 bss_osen ? " OSEN" : "");
1368 if (bss_rsn) {
1369 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1370 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1371 wpa_dbg(wpa_s, MSG_DEBUG,
1372 "Could not parse RSN element");
1373 } else {
1374 wpa_dbg(wpa_s, MSG_DEBUG,
1375 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1376 ie.pairwise_cipher, ie.group_cipher,
1377 ie.key_mgmt);
1378 }
1379 }
1380 if (bss_wpa) {
1381 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1382 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1383 wpa_dbg(wpa_s, MSG_DEBUG,
1384 "Could not parse WPA element");
1385 } else {
1386 wpa_dbg(wpa_s, MSG_DEBUG,
1387 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1388 ie.pairwise_cipher, ie.group_cipher,
1389 ie.key_mgmt);
1390 }
1391 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 return -1;
1393 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001394 if (ssid->proto & WPA_PROTO_OSEN)
1395 proto = WPA_PROTO_OSEN;
1396 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 proto = WPA_PROTO_RSN;
1398 else
1399 proto = WPA_PROTO_WPA;
1400 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1401 os_memset(&ie, 0, sizeof(ie));
1402 ie.group_cipher = ssid->group_cipher;
1403 ie.pairwise_cipher = ssid->pairwise_cipher;
1404 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405 ie.mgmt_group_cipher = 0;
1406 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1407 if (ssid->group_mgmt_cipher &
1408 WPA_CIPHER_BIP_GMAC_256)
1409 ie.mgmt_group_cipher =
1410 WPA_CIPHER_BIP_GMAC_256;
1411 else if (ssid->group_mgmt_cipher &
1412 WPA_CIPHER_BIP_CMAC_256)
1413 ie.mgmt_group_cipher =
1414 WPA_CIPHER_BIP_CMAC_256;
1415 else if (ssid->group_mgmt_cipher &
1416 WPA_CIPHER_BIP_GMAC_128)
1417 ie.mgmt_group_cipher =
1418 WPA_CIPHER_BIP_GMAC_128;
1419 else
1420 ie.mgmt_group_cipher =
1421 WPA_CIPHER_AES_128_CMAC;
1422 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001423#ifdef CONFIG_OWE
1424 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1425 !ssid->owe_only &&
1426 !bss_wpa && !bss_rsn && !bss_osen) {
1427 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1428 wpa_s->wpa_proto = 0;
1429 *wpa_ie_len = 0;
1430 return 0;
1431 }
1432#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1434 "based on configuration");
1435 } else
1436 proto = ie.proto;
1437 }
1438
1439 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1440 "pairwise %d key_mgmt %d proto %d",
1441 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 if (ssid->ieee80211w) {
1443 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1444 ie.mgmt_group_cipher);
1445 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001447 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1449 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001450 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451
1452 if (bss || !wpa_s->ap_ies_from_associnfo) {
1453 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1454 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1455 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001456 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1457 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1458 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 return -1;
1460 }
1461
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001462#ifdef CONFIG_NO_WPA
1463 wpa_s->group_cipher = WPA_CIPHER_NONE;
1464 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1465#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001467 wpa_dbg(wpa_s, MSG_DEBUG,
1468 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1469 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001470 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1471 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1473 "cipher");
1474 return -1;
1475 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001476 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1477 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478
1479 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001480 wpa_dbg(wpa_s, MSG_DEBUG,
1481 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1482 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001483 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1484 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1486 "cipher");
1487 return -1;
1488 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001489 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1490 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001491#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492
1493 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001494#ifdef CONFIG_SAE
1495 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1496 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1497#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001498#ifdef CONFIG_IEEE80211R
1499 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1500 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1501 sel &= ~WPA_KEY_MGMT_FT;
1502#endif /* CONFIG_IEEE80211R */
1503 wpa_dbg(wpa_s, MSG_DEBUG,
1504 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1505 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001507#ifdef CONFIG_IEEE80211R
1508#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001509 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1510 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1512 wpa_dbg(wpa_s, MSG_DEBUG,
1513 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001514 if (!ssid->ft_eap_pmksa_caching &&
1515 pmksa_cache_get_current(wpa_s->wpa)) {
1516 /* PMKSA caching with FT may have interoperability
1517 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001518 wpa_dbg(wpa_s, MSG_DEBUG,
1519 "WPA: Disable PMKSA caching for FT/802.1X connection");
1520 pmksa_cache_clear_current(wpa_s->wpa);
1521 }
1522#endif /* CONFIG_SHA384 */
1523#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001524#ifdef CONFIG_SUITEB192
1525 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1526 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1527 wpa_dbg(wpa_s, MSG_DEBUG,
1528 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1529#endif /* CONFIG_SUITEB192 */
1530#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001531 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1532 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1533 wpa_dbg(wpa_s, MSG_DEBUG,
1534 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001535#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001536#ifdef CONFIG_FILS
1537#ifdef CONFIG_IEEE80211R
1538 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1539 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1540 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1541 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1544#endif /* CONFIG_IEEE80211R */
1545 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1546 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1547 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1548 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1549 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1550 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1551#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001553 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1554 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001557 if (!ssid->ft_eap_pmksa_caching &&
1558 pmksa_cache_get_current(wpa_s->wpa)) {
1559 /* PMKSA caching with FT may have interoperability
1560 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001561 wpa_dbg(wpa_s, MSG_DEBUG,
1562 "WPA: Disable PMKSA caching for FT/802.1X connection");
1563 pmksa_cache_clear_current(wpa_s->wpa);
1564 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001565#endif /* CONFIG_IEEE80211R */
1566#ifdef CONFIG_DPP
1567 } else if (sel & WPA_KEY_MGMT_DPP) {
1568 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1569 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1570#endif /* CONFIG_DPP */
1571#ifdef CONFIG_SAE
1572 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1575 } else if (sel & WPA_KEY_MGMT_SAE) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1577 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1578#endif /* CONFIG_SAE */
1579#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1581 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1582 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1583#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1585 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1586 wpa_dbg(wpa_s, MSG_DEBUG,
1587 "WPA: using KEY_MGMT 802.1X with SHA256");
1588 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1589 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1590 wpa_dbg(wpa_s, MSG_DEBUG,
1591 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1593 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1594 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1595 } else if (sel & WPA_KEY_MGMT_PSK) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1598 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1599 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1600 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001601#ifdef CONFIG_HS20
1602 } else if (sel & WPA_KEY_MGMT_OSEN) {
1603 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1604 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1605#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001606#ifdef CONFIG_OWE
1607 } else if (sel & WPA_KEY_MGMT_OWE) {
1608 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1609 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1610#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 } else {
1612 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1613 "authenticated key management type");
1614 return -1;
1615 }
1616
1617 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1618 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1619 wpa_s->pairwise_cipher);
1620 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1621
Hai Shalomc3565922019-10-28 11:58:20 -07001622 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1623 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1624 wpa_msg(wpa_s, MSG_INFO,
1625 "RSN: Management frame protection required but the selected AP does not enable it");
1626 return -1;
1627 }
1628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001630 if (ssid->group_mgmt_cipher)
1631 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001632 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1634 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001635 wpa_dbg(wpa_s, MSG_DEBUG,
1636 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1637 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001638 if (sel & WPA_CIPHER_AES_128_CMAC) {
1639 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1640 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1641 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001642 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1643 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1644 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1645 "BIP-GMAC-128");
1646 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1647 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1648 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1649 "BIP-GMAC-256");
1650 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1651 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1652 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1653 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 } else {
1655 wpa_s->mgmt_group_cipher = 0;
1656 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1657 }
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1659 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001660 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001661 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001662#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001663 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1664 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001666#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001667 sae_pwe = wpa_s->conf->sae_pwe;
1668 if (ssid->sae_password_id && sae_pwe != 3)
1669 sae_pwe = 1;
1670 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001671#ifdef CONFIG_SAE_PK
1672 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1673 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1674 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1675 ((ssid->sae_password &&
1676 sae_pk_valid_password(ssid->sae_password)) ||
1677 (!ssid->sae_password && ssid->passphrase &&
1678 sae_pk_valid_password(ssid->passphrase))));
1679#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001680#ifdef CONFIG_TESTING_OPTIONS
1681 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1682 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001683 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1684 wpa_s->oci_freq_override_eapol);
1685 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1686 wpa_s->oci_freq_override_eapol_g2);
1687 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1688 wpa_s->oci_freq_override_ft_assoc);
1689 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1690 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001691#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001692
1693 /* Extended Key ID is only supported in infrastructure BSS so far */
1694 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1695 (ssid->proto & WPA_PROTO_RSN) &&
1696 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1697 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1698 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1699 int use_ext_key_id = 0;
1700
1701 wpa_msg(wpa_s, MSG_DEBUG,
1702 "WPA: Enable Extended Key ID support");
1703 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1704 wpa_s->conf->extended_key_id);
1705 if (bss_rsn &&
1706 wpa_s->conf->extended_key_id &&
1707 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1708 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1709 use_ext_key_id = 1;
1710 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1711 use_ext_key_id);
1712 } else {
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1714 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1715 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716
1717 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1718 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1719 return -1;
1720 }
1721
Hai Shalomc3565922019-10-28 11:58:20 -07001722 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1723 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1724 &wpa_s->rsnxe_len)) {
1725 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1726 return -1;
1727 }
1728
Hai Shalom021b0b52019-04-10 11:17:58 -07001729 if (0) {
1730#ifdef CONFIG_DPP
1731 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1732 /* Use PMK from DPP network introduction (PMKSA entry) */
1733 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001734#ifdef CONFIG_DPP2
1735 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1736#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001737#endif /* CONFIG_DPP */
1738 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001739 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001740 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001741
Roshan Pius3a1667e2018-07-03 15:17:14 -07001742 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1743 WPA_KEY_MGMT_FT_PSK |
1744 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1745
1746 if (ssid->psk_set && !sae_only) {
1747 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1748 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001749 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1750 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001751 psk_set = 1;
1752 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001753
Roshan Pius3a1667e2018-07-03 15:17:14 -07001754 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1755 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001756 psk_set = 1;
1757
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001758#ifndef CONFIG_NO_PBKDF2
1759 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001760 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001761 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001762 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1763 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001764 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1765 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001766 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001767 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001768 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001769 }
1770#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001771#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001772 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001773 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1774 ssid->ext_psk);
1775 char pw_str[64 + 1];
1776 u8 psk[PMK_LEN];
1777
1778 if (pw == NULL) {
1779 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1780 "found from external storage");
1781 return -1;
1782 }
1783
1784 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1785 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1786 "PSK length %d in external storage",
1787 (int) wpabuf_len(pw));
1788 ext_password_free(pw);
1789 return -1;
1790 }
1791
1792 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1793 pw_str[wpabuf_len(pw)] = '\0';
1794
1795#ifndef CONFIG_NO_PBKDF2
1796 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1797 {
1798 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1799 4096, psk, PMK_LEN);
1800 os_memset(pw_str, 0, sizeof(pw_str));
1801 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1802 "external passphrase)",
1803 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001804 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1805 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001806 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001807 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 } else
1809#endif /* CONFIG_NO_PBKDF2 */
1810 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1811 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1812 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1813 "Invalid PSK hex string");
1814 os_memset(pw_str, 0, sizeof(pw_str));
1815 ext_password_free(pw);
1816 return -1;
1817 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001818 wpa_hexdump_key(MSG_MSGDUMP,
1819 "PSK (from external PSK)",
1820 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001821 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1822 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001823 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001824 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001825 } else {
1826 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1827 "PSK available");
1828 os_memset(pw_str, 0, sizeof(pw_str));
1829 ext_password_free(pw);
1830 return -1;
1831 }
1832
1833 os_memset(pw_str, 0, sizeof(pw_str));
1834 ext_password_free(pw);
1835 }
1836#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001837
1838 if (!psk_set) {
1839 wpa_msg(wpa_s, MSG_INFO,
1840 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001841 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001842 return -1;
1843 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001844#ifdef CONFIG_OWE
1845 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1846 /* OWE Diffie-Hellman exchange in (Re)Association
1847 * Request/Response frames set the PMK, so do not override it
1848 * here. */
1849#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001850 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1852
Hai Shalomfdcde762020-04-02 11:19:20 -07001853 if (ssid->mode != WPAS_MODE_IBSS &&
1854 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1855 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1856 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1857 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1858 wpa_msg(wpa_s, MSG_INFO,
1859 "Disable PTK0 rekey support - replaced with reconnect");
1860 wpa_s->deny_ptk0_rekey = 1;
1861 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1862 } else {
1863 wpa_s->deny_ptk0_rekey = 0;
1864 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1865 }
1866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867 return 0;
1868}
1869
1870
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001871static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1872{
1873 *pos = 0x00;
1874
1875 switch (idx) {
1876 case 0: /* Bits 0-7 */
1877 break;
1878 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001879 if (wpa_s->conf->coloc_intf_reporting) {
1880 /* Bit 13 - Collocated Interference Reporting */
1881 *pos |= 0x20;
1882 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001883 break;
1884 case 2: /* Bits 16-23 */
1885#ifdef CONFIG_WNM
1886 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001887 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001888 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001889#endif /* CONFIG_WNM */
1890 break;
1891 case 3: /* Bits 24-31 */
1892#ifdef CONFIG_WNM
1893 *pos |= 0x02; /* Bit 25 - SSID List */
1894#endif /* CONFIG_WNM */
1895#ifdef CONFIG_INTERWORKING
1896 if (wpa_s->conf->interworking)
1897 *pos |= 0x80; /* Bit 31 - Interworking */
1898#endif /* CONFIG_INTERWORKING */
1899 break;
1900 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001901#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001902 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001903 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001904#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001905 break;
1906 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001907#ifdef CONFIG_HS20
1908 if (wpa_s->conf->hs20)
1909 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1910#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001911#ifdef CONFIG_MBO
1912 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1913#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001914 break;
1915 case 6: /* Bits 48-55 */
1916 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001917 case 7: /* Bits 56-63 */
1918 break;
1919 case 8: /* Bits 64-71 */
1920 if (wpa_s->conf->ftm_responder)
1921 *pos |= 0x40; /* Bit 70 - FTM responder */
1922 if (wpa_s->conf->ftm_initiator)
1923 *pos |= 0x80; /* Bit 71 - FTM initiator */
1924 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001925 case 9: /* Bits 72-79 */
1926#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001927 if (!wpa_s->disable_fils)
1928 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001929#endif /* CONFIG_FILS */
1930 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001931 case 10: /* Bits 80-87 */
1932 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
1933 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001934 }
1935}
1936
1937
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001938int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001939{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001940 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001941 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001942
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001943 if (len < wpa_s->extended_capa_len)
1944 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001945 if (buflen < (size_t) len + 2) {
1946 wpa_printf(MSG_INFO,
1947 "Not enough room for building extended capabilities element");
1948 return -1;
1949 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001950
1951 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001952 *pos++ = len;
1953 for (i = 0; i < len; i++, pos++) {
1954 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001955
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001956 if (i < wpa_s->extended_capa_len) {
1957 *pos &= ~wpa_s->extended_capa_mask[i];
1958 *pos |= wpa_s->extended_capa[i];
1959 }
1960 }
1961
1962 while (len > 0 && buf[1 + len] == 0) {
1963 len--;
1964 buf[1] = len;
1965 }
1966 if (len == 0)
1967 return 0;
1968
1969 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001970}
1971
1972
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001973static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1974 struct wpa_bss *test_bss)
1975{
1976 struct wpa_bss *bss;
1977
1978 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1979 if (bss == test_bss)
1980 return 1;
1981 }
1982
1983 return 0;
1984}
1985
1986
1987static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1988 struct wpa_ssid *test_ssid)
1989{
1990 struct wpa_ssid *ssid;
1991
1992 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1993 if (ssid == test_ssid)
1994 return 1;
1995 }
1996
1997 return 0;
1998}
1999
2000
2001int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2002 struct wpa_ssid *test_ssid)
2003{
2004 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2005 return 0;
2006
2007 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2008}
2009
2010
2011void wpas_connect_work_free(struct wpa_connect_work *cwork)
2012{
2013 if (cwork == NULL)
2014 return;
2015 os_free(cwork);
2016}
2017
2018
2019void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2020{
2021 struct wpa_connect_work *cwork;
2022 struct wpa_radio_work *work = wpa_s->connect_work;
2023
2024 if (!work)
2025 return;
2026
2027 wpa_s->connect_work = NULL;
2028 cwork = work->ctx;
2029 work->ctx = NULL;
2030 wpas_connect_work_free(cwork);
2031 radio_work_done(work);
2032}
2033
2034
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002035int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2036{
2037 struct os_reltime now;
2038 u8 addr[ETH_ALEN];
2039
2040 os_get_reltime(&now);
2041 if (wpa_s->last_mac_addr_style == style &&
2042 wpa_s->last_mac_addr_change.sec != 0 &&
2043 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2044 wpa_s->conf->rand_addr_lifetime)) {
2045 wpa_msg(wpa_s, MSG_DEBUG,
2046 "Previously selected random MAC address has not yet expired");
2047 return 0;
2048 }
2049
2050 switch (style) {
2051 case 1:
2052 if (random_mac_addr(addr) < 0)
2053 return -1;
2054 break;
2055 case 2:
2056 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2057 if (random_mac_addr_keep_oui(addr) < 0)
2058 return -1;
2059 break;
2060 default:
2061 return -1;
2062 }
2063
2064 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2065 wpa_msg(wpa_s, MSG_INFO,
2066 "Failed to set random MAC address");
2067 return -1;
2068 }
2069
2070 os_get_reltime(&wpa_s->last_mac_addr_change);
2071 wpa_s->mac_addr_changed = 1;
2072 wpa_s->last_mac_addr_style = style;
2073
2074 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2075 wpa_msg(wpa_s, MSG_INFO,
2076 "Could not update MAC address information");
2077 return -1;
2078 }
2079
2080 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2081 MAC2STR(addr));
2082
2083 return 0;
2084}
2085
2086
2087int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2088{
2089 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2090 !wpa_s->conf->preassoc_mac_addr)
2091 return 0;
2092
2093 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2094}
2095
2096
Hai Shalomc3565922019-10-28 11:58:20 -07002097static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2098{
2099#ifdef CONFIG_SAE
2100 int *groups = conf->sae_groups;
2101 int default_groups[] = { 19, 20, 21, 0 };
2102 const char *password;
2103
2104 if (!groups || groups[0] <= 0)
2105 groups = default_groups;
2106
2107 password = ssid->sae_password;
2108 if (!password)
2109 password = ssid->passphrase;
2110
Hai Shalom899fcc72020-10-19 14:38:18 -07002111 if (!password ||
2112 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2113 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002114 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002115 /* PT derivation not needed */
2116 sae_deinit_pt(ssid->pt);
2117 ssid->pt = NULL;
2118 return;
2119 }
2120
2121 if (ssid->pt)
2122 return; /* PT already derived */
2123 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2124 (const u8 *) password, os_strlen(password),
2125 ssid->sae_password_id);
2126#endif /* CONFIG_SAE */
2127}
2128
2129
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002130static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2131{
2132#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2133 os_free(wpa_s->sme.sae_rejected_groups);
2134 wpa_s->sme.sae_rejected_groups = NULL;
2135#ifdef CONFIG_TESTING_OPTIONS
2136 if (wpa_s->extra_sae_rejected_groups) {
2137 int i, *groups = wpa_s->extra_sae_rejected_groups;
2138
2139 for (i = 0; groups[i]; i++) {
2140 wpa_printf(MSG_DEBUG,
2141 "TESTING: Indicate rejection of an extra SAE group %d",
2142 groups[i]);
2143 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2144 groups[i]);
2145 }
2146 }
2147#endif /* CONFIG_TESTING_OPTIONS */
2148#endif /* CONFIG_SAE && CONFIG_SME */
2149}
2150
2151
Hai Shalom60840252021-02-19 19:02:11 -08002152int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2153{
2154 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2155 wpa_msg(wpa_s, MSG_INFO,
2156 "Could not restore permanent MAC address");
2157 return -1;
2158 }
2159 wpa_s->mac_addr_changed = 0;
2160 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2161 wpa_msg(wpa_s, MSG_INFO,
2162 "Could not update MAC address information");
2163 return -1;
2164 }
2165 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2166 return 0;
2167}
2168
2169
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002170static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2171
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002172/**
2173 * wpa_supplicant_associate - Request association
2174 * @wpa_s: Pointer to wpa_supplicant data
2175 * @bss: Scan results for the selected BSS, or %NULL if not available
2176 * @ssid: Configuration data for the selected network
2177 *
2178 * This function is used to request %wpa_supplicant to associate with a BSS.
2179 */
2180void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2181 struct wpa_bss *bss, struct wpa_ssid *ssid)
2182{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002183 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002184 int rand_style;
2185
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002186 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002187 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002188
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002189 /*
2190 * If we are starting a new connection, any previously pending EAPOL
2191 * RX cannot be valid anymore.
2192 */
2193 wpabuf_free(wpa_s->pending_eapol_rx);
2194 wpa_s->pending_eapol_rx = NULL;
2195
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002196 if (ssid->mac_addr == -1)
2197 rand_style = wpa_s->conf->mac_addr;
2198 else
2199 rand_style = ssid->mac_addr;
2200
Hai Shalomfdcde762020-04-02 11:19:20 -07002201 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002202 wmm_ac_clear_saved_tspecs(wpa_s);
2203 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002204 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002205#ifdef CONFIG_TESTING_OPTIONS
2206 wpa_s->testing_resend_assoc = 0;
2207#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002208
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002209 if (wpa_s->last_ssid == ssid) {
2210 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002211 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002212 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2213 wmm_ac_save_tspecs(wpa_s);
2214 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002215 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2216 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002217 }
Hai Shalomc3565922019-10-28 11:58:20 -07002218 } else {
2219#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002220 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002221 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2222#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002223 }
2224
2225 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002226 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2227 return;
2228 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002229 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002230 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002231 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002232 }
2233 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234
2235#ifdef CONFIG_IBSS_RSN
2236 ibss_rsn_deinit(wpa_s->ibss_rsn);
2237 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002238#else /* CONFIG_IBSS_RSN */
2239 if (ssid->mode == WPAS_MODE_IBSS &&
2240 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2241 wpa_msg(wpa_s, MSG_INFO,
2242 "IBSS RSN not supported in the build");
2243 return;
2244 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245#endif /* CONFIG_IBSS_RSN */
2246
2247 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2248 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2249#ifdef CONFIG_AP
2250 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2251 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2252 "mode");
2253 return;
2254 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002255 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2256 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002257 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2258 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002259 return;
2260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002261 wpa_s->current_bss = bss;
2262#else /* CONFIG_AP */
2263 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2264 "the build");
2265#endif /* CONFIG_AP */
2266 return;
2267 }
2268
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002269 if (ssid->mode == WPAS_MODE_MESH) {
2270#ifdef CONFIG_MESH
2271 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2272 wpa_msg(wpa_s, MSG_INFO,
2273 "Driver does not support mesh mode");
2274 return;
2275 }
2276 if (bss)
2277 ssid->frequency = bss->freq;
2278 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2279 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2280 return;
2281 }
2282 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002283#else /* CONFIG_MESH */
2284 wpa_msg(wpa_s, MSG_ERROR,
2285 "mesh mode support not included in the build");
2286#endif /* CONFIG_MESH */
2287 return;
2288 }
2289
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002290 /*
2291 * Set WPA state machine configuration to match the selected network now
2292 * so that the information is available before wpas_start_assoc_cb()
2293 * gets called. This is needed at least for RSN pre-authentication where
2294 * candidate APs are added to a list based on scan result processing
2295 * before completion of the first association.
2296 */
2297 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2298
2299#ifdef CONFIG_DPP
2300 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2301 return;
2302#endif /* CONFIG_DPP */
2303
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304#ifdef CONFIG_TDLS
2305 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002306 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307#endif /* CONFIG_TDLS */
2308
Hai Shalomc3565922019-10-28 11:58:20 -07002309#ifdef CONFIG_MBO
2310 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2311#endif /* CONFIG_MBO */
2312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002314 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 sme_authenticate(wpa_s, bss, ssid);
2316 return;
2317 }
2318
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002319 if (wpa_s->connect_work) {
2320 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2321 return;
2322 }
2323
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002324 if (radio_work_pending(wpa_s, "connect")) {
2325 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2326 return;
2327 }
2328
Dmitry Shmidt29333592017-01-09 12:27:11 -08002329#ifdef CONFIG_SME
2330 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2331 /* Clear possibly set auth_alg, if any, from last attempt. */
2332 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2333 }
2334#endif /* CONFIG_SME */
2335
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002336 wpas_abort_ongoing_scan(wpa_s);
2337
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002338 cwork = os_zalloc(sizeof(*cwork));
2339 if (cwork == NULL)
2340 return;
2341
2342 cwork->bss = bss;
2343 cwork->ssid = ssid;
2344
2345 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2346 wpas_start_assoc_cb, cwork) < 0) {
2347 os_free(cwork);
2348 }
2349}
2350
2351
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002352static int bss_is_ibss(struct wpa_bss *bss)
2353{
2354 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2355 IEEE80211_CAP_IBSS;
2356}
2357
2358
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002359static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2360 const struct wpa_ssid *ssid)
2361{
2362 enum hostapd_hw_mode hw_mode;
2363 struct hostapd_hw_modes *mode = NULL;
2364 u8 channel;
2365 int i;
2366
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002367 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2368 if (hw_mode == NUM_HOSTAPD_MODES)
2369 return 0;
2370 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2371 if (wpa_s->hw.modes[i].mode == hw_mode) {
2372 mode = &wpa_s->hw.modes[i];
2373 break;
2374 }
2375 }
2376
2377 if (!mode)
2378 return 0;
2379
2380 return mode->vht_capab != 0;
2381}
2382
2383
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002384void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2385 const struct wpa_ssid *ssid,
2386 struct hostapd_freq_params *freq)
2387{
Hai Shalom81f62d82019-07-22 12:10:00 -07002388 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002389 enum hostapd_hw_mode hw_mode;
2390 struct hostapd_hw_modes *mode = NULL;
2391 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2392 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002393 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002394 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2395 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002396 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002397 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002398 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002399 int chwidth, seg0, seg1;
2400 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002401 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002402
2403 freq->freq = ssid->frequency;
2404
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002405 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2406 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2407
2408 if (ssid->mode != WPAS_MODE_IBSS)
2409 break;
2410
2411 /* Don't adjust control freq in case of fixed_freq */
2412 if (ssid->fixed_freq)
2413 break;
2414
2415 if (!bss_is_ibss(bss))
2416 continue;
2417
2418 if (ssid->ssid_len == bss->ssid_len &&
2419 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2420 wpa_printf(MSG_DEBUG,
2421 "IBSS already found in scan results, adjust control freq: %d",
2422 bss->freq);
2423 freq->freq = bss->freq;
2424 obss_scan = 0;
2425 break;
2426 }
2427 }
2428
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002429 /* For IBSS check HT_IBSS flag */
2430 if (ssid->mode == WPAS_MODE_IBSS &&
2431 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2432 return;
2433
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002434 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2435 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2436 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2437 wpa_printf(MSG_DEBUG,
2438 "IBSS: WEP/TKIP detected, do not try to enable HT");
2439 return;
2440 }
2441
2442 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002443 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2444 if (wpa_s->hw.modes[i].mode == hw_mode) {
2445 mode = &wpa_s->hw.modes[i];
2446 break;
2447 }
2448 }
2449
2450 if (!mode)
2451 return;
2452
Hai Shalom60840252021-02-19 19:02:11 -08002453 freq->channel = channel;
2454
Hai Shalomc3565922019-10-28 11:58:20 -07002455 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2456 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002457
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002458#ifdef CONFIG_HT_OVERRIDES
2459 if (ssid->disable_ht) {
2460 freq->ht_enabled = 0;
2461 return;
2462 }
2463#endif /* CONFIG_HT_OVERRIDES */
2464
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002465 freq->ht_enabled = ht_supported(mode);
2466 if (!freq->ht_enabled)
2467 return;
2468
Hai Shalomc3565922019-10-28 11:58:20 -07002469 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2470 if (is_24ghz)
2471 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002472#ifdef CONFIG_HE_OVERRIDES
2473 if (is_24ghz && ssid->disable_he)
2474 freq->he_enabled = 0;
2475#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002476
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002477 /* Setup higher BW only for 5 GHz */
2478 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2479 return;
2480
2481 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2482 pri_chan = &mode->channels[chan_idx];
2483 if (pri_chan->chan == channel)
2484 break;
2485 pri_chan = NULL;
2486 }
2487 if (!pri_chan)
2488 return;
2489
2490 /* Check primary channel flags */
2491 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2492 return;
2493
Hai Shalom74f70d42019-02-11 14:42:39 -08002494 freq->channel = pri_chan->chan;
2495
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002496#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002497 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002498#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002499 if (ssid->disable_vht)
2500 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002501#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002502 goto skip_ht40;
2503 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002504#endif /* CONFIG_HT_OVERRIDES */
2505
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002506 /* Check/setup HT40+/HT40- */
2507 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2508 if (ht40plus[j] == channel) {
2509 ht40 = 1;
2510 break;
2511 }
2512 }
2513
2514 /* Find secondary channel */
2515 for (i = 0; i < mode->num_channels; i++) {
2516 sec_chan = &mode->channels[i];
2517 if (sec_chan->chan == channel + ht40 * 4)
2518 break;
2519 sec_chan = NULL;
2520 }
2521 if (!sec_chan)
2522 return;
2523
2524 /* Check secondary channel flags */
2525 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2526 return;
2527
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002528 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002529 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2530 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002531 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002532 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2533 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002534 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002535 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002536
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002537 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002538 struct wpa_scan_results *scan_res;
2539
2540 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2541 if (scan_res == NULL) {
2542 /* Back to HT20 */
2543 freq->sec_channel_offset = 0;
2544 return;
2545 }
2546
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002547 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002548 switch (res) {
2549 case 0:
2550 /* Back to HT20 */
2551 freq->sec_channel_offset = 0;
2552 break;
2553 case 1:
2554 /* Configuration allowed */
2555 break;
2556 case 2:
2557 /* Switch pri/sec channels */
2558 freq->freq = hw_get_freq(mode, sec_chan->chan);
2559 freq->sec_channel_offset = -freq->sec_channel_offset;
2560 freq->channel = sec_chan->chan;
2561 break;
2562 default:
2563 freq->sec_channel_offset = 0;
2564 break;
2565 }
2566
2567 wpa_scan_results_free(scan_res);
2568 }
2569
Hai Shalom74f70d42019-02-11 14:42:39 -08002570#ifdef CONFIG_HT_OVERRIDES
2571skip_ht40:
2572#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002573 wpa_printf(MSG_DEBUG,
2574 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2575 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002576
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002577 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002578 return;
2579
2580 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002581 if (ssid->mode == WPAS_MODE_IBSS &&
2582 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002583 return;
2584
2585 vht_freq = *freq;
2586
Paul Stewart092955c2017-02-06 09:13:09 -08002587#ifdef CONFIG_VHT_OVERRIDES
2588 if (ssid->disable_vht) {
2589 freq->vht_enabled = 0;
2590 return;
2591 }
2592#endif /* CONFIG_VHT_OVERRIDES */
2593
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002594 vht_freq.vht_enabled = vht_supported(mode);
2595 if (!vht_freq.vht_enabled)
2596 return;
2597
Hai Shalomfdcde762020-04-02 11:19:20 -07002598 /* Enable HE with VHT for 5 GHz */
2599 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002600
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002601 /* setup center_freq1, bandwidth */
2602 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2603 if (freq->channel >= vht80[j] &&
2604 freq->channel < vht80[j] + 16)
2605 break;
2606 }
2607
2608 if (j == ARRAY_SIZE(vht80))
2609 return;
2610
2611 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2612 struct hostapd_channel_data *chan;
2613
2614 chan = hw_get_channel_chan(mode, i, NULL);
2615 if (!chan)
2616 return;
2617
2618 /* Back to HT configuration if channel not usable */
2619 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2620 return;
2621 }
2622
Hai Shalom81f62d82019-07-22 12:10:00 -07002623 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002624 seg0 = vht80[j] + 6;
2625 seg1 = 0;
2626
Hai Shalom81f62d82019-07-22 12:10:00 -07002627 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002628 /* setup center_freq2, bandwidth */
2629 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2630 /* Only accept 80 MHz segments separated by a gap */
2631 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2632 continue;
2633 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2634 struct hostapd_channel_data *chan;
2635
2636 chan = hw_get_channel_chan(mode, i, NULL);
2637 if (!chan)
2638 continue;
2639
2640 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2641 HOSTAPD_CHAN_NO_IR |
2642 HOSTAPD_CHAN_RADAR))
2643 continue;
2644
2645 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002646 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002647 vht_caps |=
2648 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2649 seg1 = vht80[k] + 6;
2650 }
2651
Hai Shalom81f62d82019-07-22 12:10:00 -07002652 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002653 break;
2654 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002655 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002656 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002657 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002658 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2659 seg0 = 50;
2660 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002661 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002662 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2663 seg0 = 114;
2664 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002665 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2666 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002667 seg0 = vht80[j] + 2;
2668#ifdef CONFIG_HT_OVERRIDES
2669 if (ssid->disable_ht40)
2670 seg0 = 0;
2671#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002672 }
2673
Hai Shalomfdcde762020-04-02 11:19:20 -07002674#ifdef CONFIG_HE_OVERRIDES
2675 if (ssid->disable_he) {
2676 vht_freq.he_enabled = 0;
2677 freq->he_enabled = 0;
2678 }
2679#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002680 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002681 freq->channel, ssid->enable_edmg,
2682 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002683 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002684 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002685 chwidth, seg0, seg1, vht_caps,
2686 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002687 return;
2688
2689 *freq = vht_freq;
2690
2691 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2692 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002693}
2694
2695
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002696#ifdef CONFIG_FILS
2697static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2698 size_t ie_buf_len)
2699{
2700 struct fils_hlp_req *req;
2701 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2702 const u8 *pos;
2703 u8 *buf = ie_buf;
2704
2705 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2706 list) {
2707 rem_len = ie_buf_len - ie_len;
2708 pos = wpabuf_head(req->pkt);
2709 hdr_len = 1 + 2 * ETH_ALEN + 6;
2710 hlp_len = wpabuf_len(req->pkt);
2711
2712 if (rem_len < 2 + hdr_len + hlp_len) {
2713 wpa_printf(MSG_ERROR,
2714 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2715 (unsigned long) rem_len,
2716 (unsigned long) (2 + hdr_len + hlp_len));
2717 break;
2718 }
2719
2720 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2721 /* Element ID */
2722 *buf++ = WLAN_EID_EXTENSION;
2723 /* Length */
2724 *buf++ = len;
2725 /* Element ID Extension */
2726 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2727 /* Destination MAC address */
2728 os_memcpy(buf, req->dst, ETH_ALEN);
2729 buf += ETH_ALEN;
2730 /* Source MAC address */
2731 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2732 buf += ETH_ALEN;
2733 /* LLC/SNAP Header */
2734 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2735 buf += 6;
2736 /* HLP Packet */
2737 os_memcpy(buf, pos, len - hdr_len);
2738 buf += len - hdr_len;
2739 pos += len - hdr_len;
2740
2741 hlp_len -= len - hdr_len;
2742 ie_len += 2 + len;
2743 rem_len -= 2 + len;
2744
2745 while (hlp_len) {
2746 len = (hlp_len > 255) ? 255 : hlp_len;
2747 if (rem_len < 2 + len)
2748 break;
2749 *buf++ = WLAN_EID_FRAGMENT;
2750 *buf++ = len;
2751 os_memcpy(buf, pos, len);
2752 buf += len;
2753 pos += len;
2754
2755 hlp_len -= len;
2756 ie_len += 2 + len;
2757 rem_len -= 2 + len;
2758 }
2759 }
2760
2761 return ie_len;
2762}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002763
2764
2765int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2766{
2767 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2768 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2769 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2770 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2771}
2772
2773
2774int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2775{
2776#ifdef CONFIG_FILS_SK_PFS
2777 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2778 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2779#else /* CONFIG_FILS_SK_PFS */
2780 return 0;
2781#endif /* CONFIG_FILS_SK_PFS */
2782}
2783
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002784#endif /* CONFIG_FILS */
2785
2786
2787static u8 * wpas_populate_assoc_ies(
2788 struct wpa_supplicant *wpa_s,
2789 struct wpa_bss *bss, struct wpa_ssid *ssid,
2790 struct wpa_driver_associate_params *params,
2791 enum wpa_drv_update_connect_params_mask *mask)
2792{
2793 u8 *wpa_ie;
2794 size_t max_wpa_ie_len = 500;
2795 size_t wpa_ie_len;
2796 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002797#ifdef CONFIG_MBO
2798 const u8 *mbo_ie;
2799#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302800#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2801 int pmksa_cached = 0;
2802#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002803#ifdef CONFIG_FILS
2804 const u8 *realm, *username, *rrk;
2805 size_t realm_len, username_len, rrk_len;
2806 u16 next_seq_num;
2807 struct fils_hlp_req *req;
2808
2809 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2810 list) {
2811 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2812 2 + 2 * wpabuf_len(req->pkt) / 255;
2813 }
2814#endif /* CONFIG_FILS */
2815
2816 wpa_ie = os_malloc(max_wpa_ie_len);
2817 if (!wpa_ie) {
2818 wpa_printf(MSG_ERROR,
2819 "Failed to allocate connect IE buffer for %lu bytes",
2820 (unsigned long) max_wpa_ie_len);
2821 return NULL;
2822 }
2823
2824 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2825 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2826 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2827 int try_opportunistic;
2828 const u8 *cache_id = NULL;
2829
2830 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2831 wpa_s->conf->okc :
2832 ssid->proactive_key_caching) &&
2833 (ssid->proto & WPA_PROTO_RSN);
2834#ifdef CONFIG_FILS
2835 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2836 cache_id = wpa_bss_get_fils_cache_id(bss);
2837#endif /* CONFIG_FILS */
2838 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2839 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002840 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002841 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302842#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2843 pmksa_cached = 1;
2844#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002845 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002846 wpa_ie_len = max_wpa_ie_len;
2847 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2848 wpa_ie, &wpa_ie_len)) {
2849 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2850 "key management and encryption suites");
2851 os_free(wpa_ie);
2852 return NULL;
2853 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002854#ifdef CONFIG_HS20
2855 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2856 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2857 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2858 wpa_ie_len = max_wpa_ie_len;
2859 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2860 wpa_ie, &wpa_ie_len)) {
2861 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2862 "key management and encryption suites");
2863 os_free(wpa_ie);
2864 return NULL;
2865 }
2866#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002867 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2868 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2869 /*
2870 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2871 * use non-WPA since the scan results did not indicate that the
2872 * AP is using WPA or WPA2.
2873 */
2874 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2875 wpa_ie_len = 0;
2876 wpa_s->wpa_proto = 0;
2877 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2878 wpa_ie_len = max_wpa_ie_len;
2879 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2880 wpa_ie, &wpa_ie_len)) {
2881 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2882 "key management and encryption suites (no "
2883 "scan results)");
2884 os_free(wpa_ie);
2885 return NULL;
2886 }
2887#ifdef CONFIG_WPS
2888 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2889 struct wpabuf *wps_ie;
2890 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2891 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2892 wpa_ie_len = wpabuf_len(wps_ie);
2893 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2894 } else
2895 wpa_ie_len = 0;
2896 wpabuf_free(wps_ie);
2897 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2898 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2899 params->wps = WPS_MODE_PRIVACY;
2900 else
2901 params->wps = WPS_MODE_OPEN;
2902 wpa_s->wpa_proto = 0;
2903#endif /* CONFIG_WPS */
2904 } else {
2905 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2906 wpa_ie_len = 0;
2907 wpa_s->wpa_proto = 0;
2908 }
2909
2910#ifdef IEEE8021X_EAPOL
2911 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2912 if (ssid->leap) {
2913 if (ssid->non_leap == 0)
2914 algs = WPA_AUTH_ALG_LEAP;
2915 else
2916 algs |= WPA_AUTH_ALG_LEAP;
2917 }
2918 }
2919
2920#ifdef CONFIG_FILS
2921 /* Clear FILS association */
2922 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2923
2924 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2925 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2926 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2927 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002928 &next_seq_num, &rrk, &rrk_len) == 0 &&
2929 (!wpa_s->last_con_fail_realm ||
2930 wpa_s->last_con_fail_realm_len != realm_len ||
2931 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002932 algs = WPA_AUTH_ALG_FILS;
2933 params->fils_erp_username = username;
2934 params->fils_erp_username_len = username_len;
2935 params->fils_erp_realm = realm;
2936 params->fils_erp_realm_len = realm_len;
2937 params->fils_erp_next_seq_num = next_seq_num;
2938 params->fils_erp_rrk = rrk;
2939 params->fils_erp_rrk_len = rrk_len;
2940
2941 if (mask)
2942 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302943 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2944 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2945 pmksa_cached) {
2946 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002947 }
2948#endif /* CONFIG_FILS */
2949#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002950#ifdef CONFIG_SAE
2951 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2952 algs = WPA_AUTH_ALG_SAE;
2953#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002954
2955 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2956 if (ssid->auth_alg) {
2957 algs = ssid->auth_alg;
2958 wpa_dbg(wpa_s, MSG_DEBUG,
2959 "Overriding auth_alg selection: 0x%x", algs);
2960 }
2961
Hai Shalom5f92bc92019-04-18 11:54:11 -07002962#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302963 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002964 wpa_dbg(wpa_s, MSG_DEBUG,
2965 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2966 algs = WPA_AUTH_ALG_OPEN;
2967 }
2968#endif /* CONFIG_SAE */
2969
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002970#ifdef CONFIG_P2P
2971 if (wpa_s->global->p2p) {
2972 u8 *pos;
2973 size_t len;
2974 int res;
2975 pos = wpa_ie + wpa_ie_len;
2976 len = max_wpa_ie_len - wpa_ie_len;
2977 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2978 ssid->p2p_group);
2979 if (res >= 0)
2980 wpa_ie_len += res;
2981 }
2982
2983 wpa_s->cross_connect_disallowed = 0;
2984 if (bss) {
2985 struct wpabuf *p2p;
2986 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2987 if (p2p) {
2988 wpa_s->cross_connect_disallowed =
2989 p2p_get_cross_connect_disallowed(p2p);
2990 wpabuf_free(p2p);
2991 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2992 "connection",
2993 wpa_s->cross_connect_disallowed ?
2994 "disallows" : "allows");
2995 }
2996 }
2997
2998 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2999#endif /* CONFIG_P2P */
3000
3001 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003002 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003003 wpa_ie + wpa_ie_len,
3004 max_wpa_ie_len -
3005 wpa_ie_len);
3006 }
3007
3008 /*
3009 * Workaround: Add Extended Capabilities element only if the AP
3010 * included this element in Beacon/Probe Response frames. Some older
3011 * APs seem to have interoperability issues if this element is
3012 * included, so while the standard may require us to include the
3013 * element in all cases, it is justifiable to skip it to avoid
3014 * interoperability issues.
3015 */
3016 if (ssid->p2p_group)
3017 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3018 else
3019 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3020
3021 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3022 u8 ext_capab[18];
3023 int ext_capab_len;
3024 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3025 sizeof(ext_capab));
3026 if (ext_capab_len > 0 &&
3027 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3028 u8 *pos = wpa_ie;
3029 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3030 pos += 2 + pos[1];
3031 os_memmove(pos + ext_capab_len, pos,
3032 wpa_ie_len - (pos - wpa_ie));
3033 wpa_ie_len += ext_capab_len;
3034 os_memcpy(pos, ext_capab, ext_capab_len);
3035 }
3036 }
3037
3038#ifdef CONFIG_HS20
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003039 if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003040 struct wpabuf *hs20;
3041
Roshan Pius3a1667e2018-07-03 15:17:14 -07003042 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003043 if (hs20) {
3044 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3045 size_t len;
3046
Hai Shalom74f70d42019-02-11 14:42:39 -08003047 wpas_hs20_add_indication(hs20, pps_mo_id,
3048 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003049 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003050 len = max_wpa_ie_len - wpa_ie_len;
3051 if (wpabuf_len(hs20) <= len) {
3052 os_memcpy(wpa_ie + wpa_ie_len,
3053 wpabuf_head(hs20), wpabuf_len(hs20));
3054 wpa_ie_len += wpabuf_len(hs20);
3055 }
3056 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003057 }
3058 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003059 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003060#endif /* CONFIG_HS20 */
3061
3062 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3063 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3064 size_t len;
3065
3066 len = max_wpa_ie_len - wpa_ie_len;
3067 if (wpabuf_len(buf) <= len) {
3068 os_memcpy(wpa_ie + wpa_ie_len,
3069 wpabuf_head(buf), wpabuf_len(buf));
3070 wpa_ie_len += wpabuf_len(buf);
3071 }
3072 }
3073
3074#ifdef CONFIG_FST
3075 if (wpa_s->fst_ies) {
3076 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3077
3078 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3079 os_memcpy(wpa_ie + wpa_ie_len,
3080 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3081 wpa_ie_len += fst_ies_len;
3082 }
3083 }
3084#endif /* CONFIG_FST */
3085
3086#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003087 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003088 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003089 int len;
3090
3091 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003092 max_wpa_ie_len - wpa_ie_len,
3093 !!mbo_attr_from_mbo_ie(mbo_ie,
3094 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095 if (len >= 0)
3096 wpa_ie_len += len;
3097 }
3098#endif /* CONFIG_MBO */
3099
3100#ifdef CONFIG_FILS
3101 if (algs == WPA_AUTH_ALG_FILS) {
3102 size_t len;
3103
3104 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3105 max_wpa_ie_len - wpa_ie_len);
3106 wpa_ie_len += len;
3107 }
3108#endif /* CONFIG_FILS */
3109
3110#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003111#ifdef CONFIG_TESTING_OPTIONS
3112 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3113 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3114 } else
3115#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003116 if (algs == WPA_AUTH_ALG_OPEN &&
3117 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3118 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003119 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003120
Roshan Pius3a1667e2018-07-03 15:17:14 -07003121 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003122 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003123 } else if (wpa_s->assoc_status_code ==
3124 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003125 if (wpa_s->last_owe_group == 19)
3126 group = 20;
3127 else if (wpa_s->last_owe_group == 20)
3128 group = 21;
3129 else
3130 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003131 } else {
3132 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003133 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003134
Roshan Pius3a1667e2018-07-03 15:17:14 -07003135 wpa_s->last_owe_group = group;
3136 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003137 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3138 if (owe_ie &&
3139 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3140 os_memcpy(wpa_ie + wpa_ie_len,
3141 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3142 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003143 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003144 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003145 }
3146#endif /* CONFIG_OWE */
3147
Hai Shalom021b0b52019-04-10 11:17:58 -07003148#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003149 if (DPP_VERSION > 1 &&
3150 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003151 ssid->dpp_netaccesskey &&
3152 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003153 struct rsn_pmksa_cache_entry *pmksa;
3154
3155 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3156 if (!pmksa || !pmksa->dpp_pfs)
3157 goto pfs_fail;
3158
Hai Shalom021b0b52019-04-10 11:17:58 -07003159 dpp_pfs_free(wpa_s->dpp_pfs);
3160 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3161 ssid->dpp_netaccesskey_len);
3162 if (!wpa_s->dpp_pfs) {
3163 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3164 /* Try to continue without PFS */
3165 goto pfs_fail;
3166 }
3167 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3168 max_wpa_ie_len - wpa_ie_len) {
3169 os_memcpy(wpa_ie + wpa_ie_len,
3170 wpabuf_head(wpa_s->dpp_pfs->ie),
3171 wpabuf_len(wpa_s->dpp_pfs->ie));
3172 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3173 }
3174 }
3175pfs_fail:
3176#endif /* CONFIG_DPP2 */
3177
Roshan Pius3a1667e2018-07-03 15:17:14 -07003178#ifdef CONFIG_IEEE80211R
3179 /*
3180 * Add MDIE under these conditions: the network profile allows FT,
3181 * the AP supports FT, and the mobility domain ID matches.
3182 */
3183 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3184 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3185
3186 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3187 size_t len = 0;
3188 const u8 *md = mdie + 2;
3189 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3190
3191 if (os_memcmp(md, wpa_md,
3192 MOBILITY_DOMAIN_ID_LEN) == 0) {
3193 /* Add mobility domain IE */
3194 len = wpa_ft_add_mdie(
3195 wpa_s->wpa, wpa_ie + wpa_ie_len,
3196 max_wpa_ie_len - wpa_ie_len, mdie);
3197 wpa_ie_len += len;
3198 }
3199#ifdef CONFIG_SME
3200 if (len > 0 && wpa_s->sme.ft_used &&
3201 wpa_sm_has_ptk(wpa_s->wpa)) {
3202 wpa_dbg(wpa_s, MSG_DEBUG,
3203 "SME: Trying to use FT over-the-air");
3204 algs |= WPA_AUTH_ALG_FT;
3205 }
3206#endif /* CONFIG_SME */
3207 }
3208 }
3209#endif /* CONFIG_IEEE80211R */
3210
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003211#ifdef CONFIG_TESTING_OPTIONS
3212 if (wpa_s->rsnxe_override_assoc &&
3213 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3214 max_wpa_ie_len - wpa_ie_len) {
3215 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3216 os_memcpy(wpa_ie + wpa_ie_len,
3217 wpabuf_head(wpa_s->rsnxe_override_assoc),
3218 wpabuf_len(wpa_s->rsnxe_override_assoc));
3219 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3220 } else
3221#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003222 if (wpa_s->rsnxe_len > 0 &&
3223 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3224 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3225 wpa_ie_len += wpa_s->rsnxe_len;
3226 }
3227
Hai Shalom60840252021-02-19 19:02:11 -08003228 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3229 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003230 struct wpabuf *mscs_ie;
3231 size_t mscs_ie_len, buf_len;
3232
Hai Shalom899fcc72020-10-19 14:38:18 -07003233 buf_len = 3 + /* MSCS descriptor IE header */
3234 1 + /* Request type */
3235 2 + /* User priority control */
3236 4 + /* Stream timeout */
3237 3 + /* TCLAS Mask IE header */
3238 wpa_s->robust_av.frame_classifier_len;
3239 mscs_ie = wpabuf_alloc(buf_len);
3240 if (!mscs_ie) {
3241 wpa_printf(MSG_INFO,
3242 "MSCS: Failed to allocate MSCS IE");
3243 goto mscs_fail;
3244 }
3245
3246 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3247 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3248 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3249 mscs_ie_len = wpabuf_len(mscs_ie);
3250 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3251 mscs_ie_len);
3252 wpa_ie_len += mscs_ie_len;
3253 }
3254
3255 wpabuf_free(mscs_ie);
3256 }
3257mscs_fail:
3258
Hai Shalom74f70d42019-02-11 14:42:39 -08003259 if (ssid->multi_ap_backhaul_sta) {
3260 size_t multi_ap_ie_len;
3261
3262 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3263 max_wpa_ie_len - wpa_ie_len,
3264 MULTI_AP_BACKHAUL_STA);
3265 if (multi_ap_ie_len == 0) {
3266 wpa_printf(MSG_ERROR,
3267 "Multi-AP: Failed to build Multi-AP IE");
3268 os_free(wpa_ie);
3269 return NULL;
3270 }
3271 wpa_ie_len += multi_ap_ie_len;
3272 }
3273
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003274 params->wpa_ie = wpa_ie;
3275 params->wpa_ie_len = wpa_ie_len;
3276 params->auth_alg = algs;
3277 if (mask)
3278 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3279
3280 return wpa_ie;
3281}
3282
3283
Hai Shalomc3565922019-10-28 11:58:20 -07003284#ifdef CONFIG_OWE
3285static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3286{
3287 struct wpa_driver_associate_params params;
3288 u8 *wpa_ie;
3289
3290 os_memset(&params, 0, sizeof(params));
3291 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3292 wpa_s->current_ssid, &params, NULL);
3293 if (!wpa_ie)
3294 return;
3295
3296 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3297 os_free(wpa_ie);
3298}
3299#endif /* CONFIG_OWE */
3300
3301
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003302#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3303static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3304{
3305 struct wpa_driver_associate_params params;
3306 enum wpa_drv_update_connect_params_mask mask = 0;
3307 u8 *wpa_ie;
3308
3309 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3310 return; /* nothing to do */
3311
3312 os_memset(&params, 0, sizeof(params));
3313 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3314 wpa_s->current_ssid, &params, &mask);
3315 if (!wpa_ie)
3316 return;
3317
3318 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3319 os_free(wpa_ie);
3320 return;
3321 }
3322
3323 wpa_s->auth_alg = params.auth_alg;
3324 wpa_drv_update_connect_params(wpa_s, &params, mask);
3325 os_free(wpa_ie);
3326}
3327#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3328
3329
Hai Shalomc3565922019-10-28 11:58:20 -07003330static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3331{
3332 if (!edmg_ie || edmg_ie[1] < 6)
3333 return 0;
3334 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3335}
3336
3337
3338static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3339{
3340 if (!edmg_ie || edmg_ie[1] < 6)
3341 return 0;
3342 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3343}
3344
3345
3346/* Returns the intersection of two EDMG configurations.
3347 * Note: The current implementation is limited to CB2 only (CB1 included),
3348 * i.e., the implementation supports up to 2 contiguous channels.
3349 * For supporting non-contiguous (aggregated) channels and for supporting
3350 * CB3 and above, this function will need to be extended.
3351 */
3352static struct ieee80211_edmg_config
3353get_edmg_intersection(struct ieee80211_edmg_config a,
3354 struct ieee80211_edmg_config b,
3355 u8 primary_channel)
3356{
3357 struct ieee80211_edmg_config result;
3358 int i, contiguous = 0;
3359 int max_contiguous = 0;
3360
3361 result.channels = b.channels & a.channels;
3362 if (!result.channels) {
3363 wpa_printf(MSG_DEBUG,
3364 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3365 a.channels, b.channels);
3366 goto fail;
3367 }
3368
3369 if (!(result.channels & BIT(primary_channel - 1))) {
3370 wpa_printf(MSG_DEBUG,
3371 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3372 primary_channel, result.channels);
3373 goto fail;
3374 }
3375
3376 /* Find max contiguous channels */
3377 for (i = 0; i < 6; i++) {
3378 if (result.channels & BIT(i))
3379 contiguous++;
3380 else
3381 contiguous = 0;
3382
3383 if (contiguous > max_contiguous)
3384 max_contiguous = contiguous;
3385 }
3386
3387 /* Assuming AP and STA supports ONLY contiguous channels,
3388 * bw configuration can have value between 4-7.
3389 */
3390 if ((b.bw_config < a.bw_config))
3391 result.bw_config = b.bw_config;
3392 else
3393 result.bw_config = a.bw_config;
3394
3395 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3396 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3397 wpa_printf(MSG_DEBUG,
3398 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3399 max_contiguous);
3400 goto fail;
3401 }
3402
3403 return result;
3404
3405fail:
3406 result.channels = 0;
3407 result.bw_config = 0;
3408 return result;
3409}
3410
3411
3412static struct ieee80211_edmg_config
3413get_supported_edmg(struct wpa_supplicant *wpa_s,
3414 struct hostapd_freq_params *freq,
3415 struct ieee80211_edmg_config request_edmg)
3416{
3417 enum hostapd_hw_mode hw_mode;
3418 struct hostapd_hw_modes *mode = NULL;
3419 u8 primary_channel;
3420
3421 if (!wpa_s->hw.modes)
3422 goto fail;
3423
3424 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3425 if (hw_mode == NUM_HOSTAPD_MODES)
3426 goto fail;
3427
Hai Shalom60840252021-02-19 19:02:11 -08003428 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003429 if (!mode)
3430 goto fail;
3431
3432 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3433
3434fail:
3435 request_edmg.channels = 0;
3436 request_edmg.bw_config = 0;
3437 return request_edmg;
3438}
3439
3440
Hai Shalom021b0b52019-04-10 11:17:58 -07003441#ifdef CONFIG_MBO
3442void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3443{
3444 struct wpa_driver_associate_params params;
3445 u8 *wpa_ie;
3446
3447 /*
3448 * Update MBO connect params only in case of change of MBO attributes
3449 * when connected, if the AP support MBO.
3450 */
3451
3452 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3453 !wpa_s->current_bss ||
3454 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3455 return;
3456
3457 os_memset(&params, 0, sizeof(params));
3458 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3459 wpa_s->current_ssid, &params, NULL);
3460 if (!wpa_ie)
3461 return;
3462
3463 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3464 os_free(wpa_ie);
3465}
3466#endif /* CONFIG_MBO */
3467
3468
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003469static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3470{
3471 struct wpa_connect_work *cwork = work->ctx;
3472 struct wpa_bss *bss = cwork->bss;
3473 struct wpa_ssid *ssid = cwork->ssid;
3474 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003476 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003477 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003479 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003480#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003481 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003482#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003483 int assoc_failed = 0;
3484 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003485 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003486#ifdef CONFIG_HT_OVERRIDES
3487 struct ieee80211_ht_capabilities htcaps;
3488 struct ieee80211_ht_capabilities htcaps_mask;
3489#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003490#ifdef CONFIG_VHT_OVERRIDES
3491 struct ieee80211_vht_capabilities vhtcaps;
3492 struct ieee80211_vht_capabilities vhtcaps_mask;
3493#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003494
3495 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003496 if (work->started) {
3497 wpa_s->connect_work = NULL;
3498
3499 /* cancel possible auth. timeout */
3500 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3501 NULL);
3502 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003503 wpas_connect_work_free(cwork);
3504 return;
3505 }
3506
3507 wpa_s->connect_work = work;
3508
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003509 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3510 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003511 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3512 wpas_connect_work_done(wpa_s);
3513 return;
3514 }
3515
Dmitry Shmidte4663042016-04-04 10:07:49 -07003516 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517 os_memset(&params, 0, sizeof(params));
3518 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003519 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003520
3521 /* Starting new association, so clear the possibly used WPA IE from the
3522 * previous association. */
3523 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3524 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3525 wpa_s->rsnxe_len = 0;
3526 wpa_s->mscs_setup_done = false;
3527
3528 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3529 if (!wpa_ie) {
3530 wpas_connect_work_done(wpa_s);
3531 return;
3532 }
3533
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003534 if (bss &&
3535 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536#ifdef CONFIG_IEEE80211R
3537 const u8 *ie, *md = NULL;
3538#endif /* CONFIG_IEEE80211R */
3539 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3540 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3541 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3542 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3543 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3544 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3545 if (bssid_changed)
3546 wpas_notify_bssid_changed(wpa_s);
3547#ifdef CONFIG_IEEE80211R
3548 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3549 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3550 md = ie + 2;
3551 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3552 if (md) {
3553 /* Prepare for the next transition */
3554 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3555 }
3556#endif /* CONFIG_IEEE80211R */
3557#ifdef CONFIG_WPS
3558 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3559 wpa_s->conf->ap_scan == 2 &&
3560 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3561 /* Use ap_scan==1 style network selection to find the network
3562 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003563 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003564 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003565 wpa_s->reassociate = 1;
3566 wpa_supplicant_req_scan(wpa_s, 0, 0);
3567 return;
3568#endif /* CONFIG_WPS */
3569 } else {
3570 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3571 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003572 if (bss)
3573 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3574 else
3575 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003576 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003577 if (!wpa_s->pno)
3578 wpa_supplicant_cancel_sched_scan(wpa_s);
3579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003580 wpa_supplicant_cancel_scan(wpa_s);
3581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003582 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3583 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003584 cipher_pairwise = wpa_s->pairwise_cipher;
3585 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003586 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3588 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3589 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3590 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003591#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 if (wpa_set_wep_keys(wpa_s, ssid)) {
3593 use_crypt = 1;
3594 wep_keys_set = 1;
3595 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003596#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 }
3598 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3599 use_crypt = 0;
3600
3601#ifdef IEEE8021X_EAPOL
3602 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3603 if ((ssid->eapol_flags &
3604 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3605 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3606 !wep_keys_set) {
3607 use_crypt = 0;
3608 } else {
3609 /* Assume that dynamic WEP-104 keys will be used and
3610 * set cipher suites in order for drivers to expect
3611 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003612 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 }
3614 }
3615#endif /* IEEE8021X_EAPOL */
3616
3617 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3618 /* Set the key before (and later after) association */
3619 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3620 }
3621
3622 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3623 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624 params.ssid = bss->ssid;
3625 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003626 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3627 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003628 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3629 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003630 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003631 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003632 ssid->bssid_set,
3633 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003634 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003635 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003636 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003637 params.bssid_hint = bss->bssid;
3638 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003639 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003640 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003641 if (ssid->bssid_hint_set)
3642 params.bssid_hint = ssid->bssid_hint;
3643
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003644 params.ssid = ssid->ssid;
3645 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003646 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003647 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003648
3649 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3650 wpa_s->conf->ap_scan == 2) {
3651 params.bssid = ssid->bssid;
3652 params.fixed_bssid = 1;
3653 }
3654
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003655 /* Initial frequency for IBSS/mesh */
3656 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003657 ssid->frequency > 0 && params.freq.freq == 0)
3658 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003659
3660 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003661 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003662 if (ssid->beacon_int)
3663 params.beacon_int = ssid->beacon_int;
3664 else
3665 params.beacon_int = wpa_s->conf->beacon_int;
3666 }
3667
Hai Shalomc3565922019-10-28 11:58:20 -07003668 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003669 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3670 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003671 else
3672 edmg_ie_oper = NULL;
3673
3674 if (edmg_ie_oper) {
3675 params.freq.edmg.channels =
3676 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3677 params.freq.edmg.bw_config =
3678 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3679 wpa_printf(MSG_DEBUG,
3680 "AP supports EDMG channels 0x%x, bw_config %d",
3681 params.freq.edmg.channels,
3682 params.freq.edmg.bw_config);
3683
3684 /* User may ask for specific EDMG channel for EDMG connection
3685 * (must be supported by AP)
3686 */
3687 if (ssid->edmg_channel) {
3688 struct ieee80211_edmg_config configured_edmg;
3689 enum hostapd_hw_mode hw_mode;
3690 u8 primary_channel;
3691
3692 hw_mode = ieee80211_freq_to_chan(bss->freq,
3693 &primary_channel);
3694 if (hw_mode == NUM_HOSTAPD_MODES)
3695 goto edmg_fail;
3696
3697 hostapd_encode_edmg_chan(ssid->enable_edmg,
3698 ssid->edmg_channel,
3699 primary_channel,
3700 &configured_edmg);
3701
3702 if (ieee802_edmg_is_allowed(params.freq.edmg,
3703 configured_edmg)) {
3704 params.freq.edmg = configured_edmg;
3705 wpa_printf(MSG_DEBUG,
3706 "Use EDMG channel %d for connection",
3707 ssid->edmg_channel);
3708 } else {
3709 edmg_fail:
3710 params.freq.edmg.channels = 0;
3711 params.freq.edmg.bw_config = 0;
3712 wpa_printf(MSG_WARNING,
3713 "EDMG channel %d not supported by AP, fallback to DMG",
3714 ssid->edmg_channel);
3715 }
3716 }
3717
3718 if (params.freq.edmg.channels) {
3719 wpa_printf(MSG_DEBUG,
3720 "EDMG before: channels 0x%x, bw_config %d",
3721 params.freq.edmg.channels,
3722 params.freq.edmg.bw_config);
3723 params.freq.edmg = get_supported_edmg(wpa_s,
3724 &params.freq,
3725 params.freq.edmg);
3726 wpa_printf(MSG_DEBUG,
3727 "EDMG after: channels 0x%x, bw_config %d",
3728 params.freq.edmg.channels,
3729 params.freq.edmg.bw_config);
3730 }
3731 }
3732
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 params.pairwise_suite = cipher_pairwise;
3734 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003735 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003736 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003737 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003738 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003739 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003740 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003741#ifdef CONFIG_WEP
3742 {
3743 int i;
3744
3745 for (i = 0; i < NUM_WEP_KEYS; i++) {
3746 if (ssid->wep_key_len[i])
3747 params.wep_key[i] = ssid->wep_key[i];
3748 params.wep_key_len[i] = ssid->wep_key_len[i];
3749 }
3750 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003752#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753
Hai Shalom74f70d42019-02-11 14:42:39 -08003754 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003755 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3756 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 params.passphrase = ssid->passphrase;
3758 if (ssid->psk_set)
3759 params.psk = ssid->psk;
3760 }
3761
Hai Shalom74f70d42019-02-11 14:42:39 -08003762 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3763 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3764 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3765 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3766 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003767 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003768
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003769 if (wpa_s->conf->key_mgmt_offload) {
3770 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3771 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003772 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3773 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003774 params.req_key_mgmt_offload =
3775 ssid->proactive_key_caching < 0 ?
3776 wpa_s->conf->okc : ssid->proactive_key_caching;
3777 else
3778 params.req_key_mgmt_offload = 1;
3779
3780 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3781 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3782 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3783 ssid->psk_set)
3784 params.psk = ssid->psk;
3785 }
3786
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 params.drop_unencrypted = use_crypt;
3788
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003789 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003790 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003791 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3792 struct wpa_ie_data ie;
3793 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3794 ie.capabilities &
3795 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3796 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3797 "MFP: require MFP");
3798 params.mgmt_frame_protection =
3799 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003800#ifdef CONFIG_OWE
3801 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3802 !ssid->owe_only) {
3803 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3804#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805 }
3806 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003807
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003808 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003809
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003810 if (wpa_s->p2pdev->set_sta_uapsd)
3811 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003812 else
3813 params.uapsd = -1;
3814
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003815#ifdef CONFIG_HT_OVERRIDES
3816 os_memset(&htcaps, 0, sizeof(htcaps));
3817 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3818 params.htcaps = (u8 *) &htcaps;
3819 params.htcaps_mask = (u8 *) &htcaps_mask;
3820 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3821#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003822#ifdef CONFIG_VHT_OVERRIDES
3823 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3824 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3825 params.vhtcaps = &vhtcaps;
3826 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003827 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003828#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003829#ifdef CONFIG_HE_OVERRIDES
3830 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3831#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003832
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003833#ifdef CONFIG_P2P
3834 /*
3835 * If multi-channel concurrency is not supported, check for any
3836 * frequency conflict. In case of any frequency conflict, remove the
3837 * least prioritized connection.
3838 */
3839 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003840 int freq, num;
3841 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003842 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003843 wpa_printf(MSG_DEBUG,
3844 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003845 freq, params.freq.freq);
3846 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003847 wpa_s, params.freq.freq, ssid) < 0) {
3848 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003849 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003850 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003851 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003852 }
3853 }
3854#endif /* CONFIG_P2P */
3855
Dmitry Shmidte4663042016-04-04 10:07:49 -07003856 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3857 wpa_s->current_ssid)
3858 params.prev_bssid = prev_bssid;
3859
Hai Shalom60840252021-02-19 19:02:11 -08003860#ifdef CONFIG_SAE
3861 params.sae_pwe = wpa_s->conf->sae_pwe;
3862#endif /* CONFIG_SAE */
3863
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003864 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003865 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 if (ret < 0) {
3867 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3868 "failed");
3869 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3870 /*
3871 * The driver is known to mean what is saying, so we
3872 * can stop right here; the association will not
3873 * succeed.
3874 */
3875 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08003876 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08003877 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003878 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003879 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3880 return;
3881 }
3882 /* try to continue anyway; new association will be tried again
3883 * after timeout */
3884 assoc_failed = 1;
3885 }
3886
3887 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3888 /* Set the key after the association just in case association
3889 * cleared the previously configured key. */
3890 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3891 /* No need to timeout authentication since there is no key
3892 * management. */
3893 wpa_supplicant_cancel_auth_timeout(wpa_s);
3894 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3895#ifdef CONFIG_IBSS_RSN
3896 } else if (ssid->mode == WPAS_MODE_IBSS &&
3897 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3898 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3899 /*
3900 * RSN IBSS authentication is per-STA and we can disable the
3901 * per-BSSID authentication.
3902 */
3903 wpa_supplicant_cancel_auth_timeout(wpa_s);
3904#endif /* CONFIG_IBSS_RSN */
3905 } else {
3906 /* Timeout for IEEE 802.11 authentication and association */
3907 int timeout = 60;
3908
3909 if (assoc_failed) {
3910 /* give IBSS a bit more time */
3911 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3912 } else if (wpa_s->conf->ap_scan == 1) {
3913 /* give IBSS a bit more time */
3914 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3915 }
3916 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3917 }
3918
Hai Shalomfdcde762020-04-02 11:19:20 -07003919#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003920 if (wep_keys_set &&
3921 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003922 /* Set static WEP keys again */
3923 wpa_set_wep_keys(wpa_s, ssid);
3924 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003925#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003926
3927 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3928 /*
3929 * Do not allow EAP session resumption between different
3930 * network configurations.
3931 */
3932 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3933 }
3934 old_ssid = wpa_s->current_ssid;
3935 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003936
3937 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003938 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003939#ifdef CONFIG_HS20
3940 hs20_configure_frame_filters(wpa_s);
3941#endif /* CONFIG_HS20 */
3942 }
3943
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003944 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3945 wpa_supplicant_initiate_eapol(wpa_s);
3946 if (old_ssid != wpa_s->current_ssid)
3947 wpas_notify_network_changed(wpa_s);
3948}
3949
3950
3951static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3952 const u8 *addr)
3953{
3954 struct wpa_ssid *old_ssid;
3955
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003956 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003957 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003959 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003960 wpa_sm_set_config(wpa_s->wpa, NULL);
3961 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3962 if (old_ssid != wpa_s->current_ssid)
3963 wpas_notify_network_changed(wpa_s);
3964 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3965}
3966
3967
3968/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3970 * @wpa_s: Pointer to wpa_supplicant data
3971 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3972 *
3973 * This function is used to request %wpa_supplicant to deauthenticate from the
3974 * current AP.
3975 */
3976void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003977 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978{
3979 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003980 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003981 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003982
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003983 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003984 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003985 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003986 reason_code, reason2str(reason_code),
3987 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003988
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003989 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3990 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3991 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003992 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003993 else if (!is_zero_ether_addr(wpa_s->bssid))
3994 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003995 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3996 /*
3997 * When using driver-based BSS selection, we may not know the
3998 * BSSID with which we are currently trying to associate. We
3999 * need to notify the driver of this disconnection even in such
4000 * a case, so use the all zeros address here.
4001 */
4002 addr = wpa_s->bssid;
4003 zero_addr = 1;
4004 }
4005
Hai Shalom74f70d42019-02-11 14:42:39 -08004006 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4007 wpa_s->enabled_4addr_mode = 0;
4008
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004009#ifdef CONFIG_TDLS
4010 wpa_tdls_teardown_peers(wpa_s->wpa);
4011#endif /* CONFIG_TDLS */
4012
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004013#ifdef CONFIG_MESH
4014 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004015 struct mesh_conf *mconf;
4016
4017 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004018 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4019 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004020 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4021 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004022 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004023 }
4024#endif /* CONFIG_MESH */
4025
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004026 if (addr) {
4027 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004028 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004029 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004030 event.deauth_info.locally_generated = 1;
4031 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004032 if (zero_addr)
4033 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004034 }
4035
4036 wpa_supplicant_clear_connection(wpa_s, addr);
4037}
4038
Hai Shalomfdcde762020-04-02 11:19:20 -07004039
4040void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4041{
4042 wpa_s->own_reconnect_req = 1;
4043 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4044
4045}
4046
4047
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004048static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4049 struct wpa_ssid *ssid)
4050{
4051 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4052 return;
4053
4054 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004055 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004056 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4057 wpas_notify_network_enabled_changed(wpa_s, ssid);
4058
4059 /*
4060 * Try to reassociate since there is no current configuration and a new
4061 * network was made available.
4062 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004063 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004064 wpa_s->reassociate = 1;
4065}
4066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004067
Roshan Pius950bec92016-07-19 09:49:24 -07004068/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004069 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004070 * @wpa_s: wpa_supplicant structure for a network interface
4071 * Returns: The new network configuration or %NULL if operation failed
4072 *
4073 * This function performs the following operations:
4074 * 1. Adds a new network.
4075 * 2. Send network addition notification.
4076 * 3. Marks the network disabled.
4077 * 4. Set network default parameters.
4078 */
4079struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4080{
4081 struct wpa_ssid *ssid;
4082
4083 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004084 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004085 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004086 wpas_notify_network_added(wpa_s, ssid);
4087 ssid->disabled = 1;
4088 wpa_config_set_network_defaults(ssid);
4089
4090 return ssid;
4091}
4092
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004093
Roshan Pius950bec92016-07-19 09:49:24 -07004094/**
4095 * wpa_supplicant_remove_network - Remove a configured network based on id
4096 * @wpa_s: wpa_supplicant structure for a network interface
4097 * @id: Unique network id to search for
4098 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4099 * could not be removed
4100 *
4101 * This function performs the following operations:
4102 * 1. Removes the network.
4103 * 2. Send network removal notification.
4104 * 3. Update internal state machines.
4105 * 4. Stop any running sched scans.
4106 */
4107int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4108{
4109 struct wpa_ssid *ssid;
4110 int was_disabled;
4111
4112 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004113 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004114 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004115 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004116
4117 if (wpa_s->last_ssid == ssid)
4118 wpa_s->last_ssid = NULL;
4119
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004120 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004121#ifdef CONFIG_SME
4122 wpa_s->sme.prev_bssid_set = 0;
4123#endif /* CONFIG_SME */
4124 /*
4125 * Invalidate the EAP session cache if the current or
4126 * previously used network is removed.
4127 */
4128 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4129 }
4130
4131 if (ssid == wpa_s->current_ssid) {
4132 wpa_sm_set_config(wpa_s->wpa, NULL);
4133 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4134
4135 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4136 wpa_s->own_disconnect_req = 1;
4137 wpa_supplicant_deauthenticate(wpa_s,
4138 WLAN_REASON_DEAUTH_LEAVING);
4139 }
4140
4141 was_disabled = ssid->disabled;
4142
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004143 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004144 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004145
4146 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004147 wpa_printf(MSG_DEBUG,
4148 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004149 wpa_supplicant_cancel_sched_scan(wpa_s);
4150 wpa_supplicant_req_scan(wpa_s, 0, 0);
4151 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004152
Roshan Pius950bec92016-07-19 09:49:24 -07004153 return 0;
4154}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004156
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004157/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004158 * wpa_supplicant_remove_all_networks - Remove all configured networks
4159 * @wpa_s: wpa_supplicant structure for a network interface
4160 * Returns: 0 on success (errors are currently ignored)
4161 *
4162 * This function performs the following operations:
4163 * 1. Remove all networks.
4164 * 2. Send network removal notifications.
4165 * 3. Update internal state machines.
4166 * 4. Stop any running sched scans.
4167 */
4168int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4169{
4170 struct wpa_ssid *ssid;
4171
4172 if (wpa_s->sched_scanning)
4173 wpa_supplicant_cancel_sched_scan(wpa_s);
4174
4175 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4176 if (wpa_s->current_ssid) {
4177#ifdef CONFIG_SME
4178 wpa_s->sme.prev_bssid_set = 0;
4179#endif /* CONFIG_SME */
4180 wpa_sm_set_config(wpa_s->wpa, NULL);
4181 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4182 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4183 wpa_s->own_disconnect_req = 1;
4184 wpa_supplicant_deauthenticate(
4185 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4186 }
4187 ssid = wpa_s->conf->ssid;
4188 while (ssid) {
4189 struct wpa_ssid *remove_ssid = ssid;
4190 int id;
4191
4192 id = ssid->id;
4193 ssid = ssid->next;
4194 if (wpa_s->last_ssid == remove_ssid)
4195 wpa_s->last_ssid = NULL;
4196 wpas_notify_network_removed(wpa_s, remove_ssid);
4197 wpa_config_remove_network(wpa_s->conf, id);
4198 }
4199 return 0;
4200}
4201
4202
4203/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004204 * wpa_supplicant_enable_network - Mark a configured network as enabled
4205 * @wpa_s: wpa_supplicant structure for a network interface
4206 * @ssid: wpa_ssid structure for a configured network or %NULL
4207 *
4208 * Enables the specified network or all networks if no network specified.
4209 */
4210void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4211 struct wpa_ssid *ssid)
4212{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004213 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004214 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4215 wpa_supplicant_enable_one_network(wpa_s, ssid);
4216 } else
4217 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004218
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004219 if (wpa_s->reassociate && !wpa_s->disconnected &&
4220 (!wpa_s->current_ssid ||
4221 wpa_s->wpa_state == WPA_DISCONNECTED ||
4222 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004223 if (wpa_s->sched_scanning) {
4224 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4225 "new network to scan filters");
4226 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004227 }
4228
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004229 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4230 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004231 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004233 }
4234}
4235
4236
4237/**
4238 * wpa_supplicant_disable_network - Mark a configured network as disabled
4239 * @wpa_s: wpa_supplicant structure for a network interface
4240 * @ssid: wpa_ssid structure for a configured network or %NULL
4241 *
4242 * Disables the specified network or all networks if no network specified.
4243 */
4244void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4245 struct wpa_ssid *ssid)
4246{
4247 struct wpa_ssid *other_ssid;
4248 int was_disabled;
4249
4250 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004251 if (wpa_s->sched_scanning)
4252 wpa_supplicant_cancel_sched_scan(wpa_s);
4253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4255 other_ssid = other_ssid->next) {
4256 was_disabled = other_ssid->disabled;
4257 if (was_disabled == 2)
4258 continue; /* do not change persistent P2P group
4259 * data */
4260
4261 other_ssid->disabled = 1;
4262
4263 if (was_disabled != other_ssid->disabled)
4264 wpas_notify_network_enabled_changed(
4265 wpa_s, other_ssid);
4266 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004267 if (wpa_s->current_ssid) {
4268 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4269 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004270 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004272 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004274 if (ssid == wpa_s->current_ssid) {
4275 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4276 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004277 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004278 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004279 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004280
4281 was_disabled = ssid->disabled;
4282
4283 ssid->disabled = 1;
4284
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004285 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004286 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004287 if (wpa_s->sched_scanning) {
4288 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4289 "to remove network from filters");
4290 wpa_supplicant_cancel_sched_scan(wpa_s);
4291 wpa_supplicant_req_scan(wpa_s, 0, 0);
4292 }
4293 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004294 }
4295}
4296
4297
4298/**
4299 * wpa_supplicant_select_network - Attempt association with a network
4300 * @wpa_s: wpa_supplicant structure for a network interface
4301 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4302 */
4303void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4304 struct wpa_ssid *ssid)
4305{
4306
4307 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004308 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004309
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004310 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004311 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4312 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004313 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004315 disconnected = 1;
4316 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004318 if (ssid)
4319 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4320
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004321 /*
4322 * Mark all other networks disabled or mark all networks enabled if no
4323 * network specified.
4324 */
4325 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4326 other_ssid = other_ssid->next) {
4327 int was_disabled = other_ssid->disabled;
4328 if (was_disabled == 2)
4329 continue; /* do not change persistent P2P group data */
4330
4331 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004332 if (was_disabled && !other_ssid->disabled)
4333 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334
4335 if (was_disabled != other_ssid->disabled)
4336 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4337 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004338
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004339 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4340 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004341 /* We are already associated with the selected network */
4342 wpa_printf(MSG_DEBUG, "Already associated with the "
4343 "selected network - do nothing");
4344 return;
4345 }
4346
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004347 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004348 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004349 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004350 wpa_s->connect_without_scan =
4351 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004352
4353 /*
4354 * Don't optimize next scan freqs since a new ESS has been
4355 * selected.
4356 */
4357 os_free(wpa_s->next_scan_freqs);
4358 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004359 } else {
4360 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004361 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 wpa_s->disconnected = 0;
4364 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004365 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004366 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004367 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004368 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004369 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4370 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004371
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004372 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004373 wpa_supplicant_fast_associate(wpa_s) != 1) {
4374 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004375 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004376 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004377 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378
4379 if (ssid)
4380 wpas_notify_network_selected(wpa_s, ssid);
4381}
4382
4383
4384/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004385 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4386 * @wpa_s: wpa_supplicant structure for a network interface
4387 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4388 * @pkcs11_module_path: PKCS #11 module path or NULL
4389 * Returns: 0 on success; -1 on failure
4390 *
4391 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4392 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4393 * module path fails the paths will be reset to the default value (NULL).
4394 */
4395int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4396 const char *pkcs11_engine_path,
4397 const char *pkcs11_module_path)
4398{
4399 char *pkcs11_engine_path_copy = NULL;
4400 char *pkcs11_module_path_copy = NULL;
4401
4402 if (pkcs11_engine_path != NULL) {
4403 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4404 if (pkcs11_engine_path_copy == NULL)
4405 return -1;
4406 }
4407 if (pkcs11_module_path != NULL) {
4408 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004409 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004410 os_free(pkcs11_engine_path_copy);
4411 return -1;
4412 }
4413 }
4414
4415 os_free(wpa_s->conf->pkcs11_engine_path);
4416 os_free(wpa_s->conf->pkcs11_module_path);
4417 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4418 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4419
4420 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4421 eapol_sm_deinit(wpa_s->eapol);
4422 wpa_s->eapol = NULL;
4423 if (wpa_supplicant_init_eapol(wpa_s)) {
4424 /* Error -> Reset paths to the default value (NULL) once. */
4425 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4426 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4427 NULL);
4428
4429 return -1;
4430 }
4431 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4432
4433 return 0;
4434}
4435
4436
4437/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004438 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4439 * @wpa_s: wpa_supplicant structure for a network interface
4440 * @ap_scan: AP scan mode
4441 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4442 *
4443 */
4444int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4445{
4446
4447 int old_ap_scan;
4448
4449 if (ap_scan < 0 || ap_scan > 2)
4450 return -1;
4451
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004452 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4453 wpa_printf(MSG_INFO,
4454 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4455 }
4456
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004457#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004458 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4459 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4460 wpa_s->wpa_state < WPA_COMPLETED) {
4461 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4462 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004463 return 0;
4464 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004465#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467 old_ap_scan = wpa_s->conf->ap_scan;
4468 wpa_s->conf->ap_scan = ap_scan;
4469
4470 if (old_ap_scan != wpa_s->conf->ap_scan)
4471 wpas_notify_ap_scan_changed(wpa_s);
4472
4473 return 0;
4474}
4475
4476
4477/**
4478 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4479 * @wpa_s: wpa_supplicant structure for a network interface
4480 * @expire_age: Expiration age in seconds
4481 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4482 *
4483 */
4484int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4485 unsigned int bss_expire_age)
4486{
4487 if (bss_expire_age < 10) {
4488 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4489 bss_expire_age);
4490 return -1;
4491 }
4492 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4493 bss_expire_age);
4494 wpa_s->conf->bss_expiration_age = bss_expire_age;
4495
4496 return 0;
4497}
4498
4499
4500/**
4501 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4502 * @wpa_s: wpa_supplicant structure for a network interface
4503 * @expire_count: number of scans after which an unseen BSS is reclaimed
4504 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4505 *
4506 */
4507int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4508 unsigned int bss_expire_count)
4509{
4510 if (bss_expire_count < 1) {
4511 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4512 bss_expire_count);
4513 return -1;
4514 }
4515 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4516 bss_expire_count);
4517 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4518
4519 return 0;
4520}
4521
4522
4523/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004524 * wpa_supplicant_set_scan_interval - Set scan interval
4525 * @wpa_s: wpa_supplicant structure for a network interface
4526 * @scan_interval: scan interval in seconds
4527 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4528 *
4529 */
4530int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4531 int scan_interval)
4532{
4533 if (scan_interval < 0) {
4534 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4535 scan_interval);
4536 return -1;
4537 }
4538 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4539 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004540 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004541
4542 return 0;
4543}
4544
4545
4546/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547 * wpa_supplicant_set_debug_params - Set global debug params
4548 * @global: wpa_global structure
4549 * @debug_level: debug level
4550 * @debug_timestamp: determines if show timestamp in debug data
4551 * @debug_show_keys: determines if show keys in debug data
4552 * Returns: 0 if succeed or -1 if debug_level has wrong value
4553 */
4554int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4555 int debug_timestamp, int debug_show_keys)
4556{
4557
4558 int old_level, old_timestamp, old_show_keys;
4559
4560 /* check for allowed debuglevels */
4561 if (debug_level != MSG_EXCESSIVE &&
4562 debug_level != MSG_MSGDUMP &&
4563 debug_level != MSG_DEBUG &&
4564 debug_level != MSG_INFO &&
4565 debug_level != MSG_WARNING &&
4566 debug_level != MSG_ERROR)
4567 return -1;
4568
4569 old_level = wpa_debug_level;
4570 old_timestamp = wpa_debug_timestamp;
4571 old_show_keys = wpa_debug_show_keys;
4572
4573 wpa_debug_level = debug_level;
4574 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4575 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4576
4577 if (wpa_debug_level != old_level)
4578 wpas_notify_debug_level_changed(global);
4579 if (wpa_debug_timestamp != old_timestamp)
4580 wpas_notify_debug_timestamp_changed(global);
4581 if (wpa_debug_show_keys != old_show_keys)
4582 wpas_notify_debug_show_keys_changed(global);
4583
4584 return 0;
4585}
4586
4587
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004588#ifdef CONFIG_OWE
4589static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4590 const u8 *entry_ssid, size_t entry_ssid_len)
4591{
4592 const u8 *owe, *pos, *end;
4593 u8 ssid_len;
4594 struct wpa_bss *bss;
4595
4596 /* Check network profile SSID aganst the SSID in the
4597 * OWE Transition Mode element. */
4598
4599 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4600 if (!bss)
4601 return 0;
4602
4603 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4604 if (!owe)
4605 return 0;
4606
4607 pos = owe + 6;
4608 end = owe + 2 + owe[1];
4609
4610 if (end - pos < ETH_ALEN + 1)
4611 return 0;
4612 pos += ETH_ALEN;
4613 ssid_len = *pos++;
4614 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4615 return 0;
4616
4617 return entry_ssid_len == ssid_len &&
4618 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4619}
4620#endif /* CONFIG_OWE */
4621
4622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004623/**
4624 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4625 * @wpa_s: Pointer to wpa_supplicant data
4626 * Returns: A pointer to the current network structure or %NULL on failure
4627 */
4628struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4629{
4630 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004631 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632 int res;
4633 size_t ssid_len;
4634 u8 bssid[ETH_ALEN];
4635 int wired;
4636
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004637 res = wpa_drv_get_ssid(wpa_s, ssid);
4638 if (res < 0) {
4639 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4640 "driver");
4641 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004643 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004644
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004645 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004646 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4647 "driver");
4648 return NULL;
4649 }
4650
4651 wired = wpa_s->conf->ap_scan == 0 &&
4652 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4653
4654 entry = wpa_s->conf->ssid;
4655 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004656 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004657 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004658 (!entry->ssid ||
4659 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4660 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004661 (!entry->bssid_set ||
4662 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4663 return entry;
4664#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004665 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004666 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4667 (entry->ssid == NULL || entry->ssid_len == 0) &&
4668 (!entry->bssid_set ||
4669 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4670 return entry;
4671#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004672
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004673#ifdef CONFIG_OWE
4674 if (!wpas_network_disabled(wpa_s, entry) &&
4675 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4676 entry->ssid_len) &&
4677 (!entry->bssid_set ||
4678 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4679 return entry;
4680#endif /* CONFIG_OWE */
4681
Dmitry Shmidt04949592012-07-19 12:16:46 -07004682 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004683 entry->ssid_len == 0 &&
4684 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4685 return entry;
4686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004687 entry = entry->next;
4688 }
4689
4690 return NULL;
4691}
4692
4693
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004694static int select_driver(struct wpa_supplicant *wpa_s, int i)
4695{
4696 struct wpa_global *global = wpa_s->global;
4697
4698 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004699 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004700 if (global->drv_priv[i] == NULL) {
4701 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4702 "'%s'", wpa_drivers[i]->name);
4703 return -1;
4704 }
4705 }
4706
4707 wpa_s->driver = wpa_drivers[i];
4708 wpa_s->global_drv_priv = global->drv_priv[i];
4709
4710 return 0;
4711}
4712
4713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004714static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4715 const char *name)
4716{
4717 int i;
4718 size_t len;
4719 const char *pos, *driver = name;
4720
4721 if (wpa_s == NULL)
4722 return -1;
4723
4724 if (wpa_drivers[0] == NULL) {
4725 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4726 "wpa_supplicant");
4727 return -1;
4728 }
4729
4730 if (name == NULL) {
4731 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004732 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004733 }
4734
4735 do {
4736 pos = os_strchr(driver, ',');
4737 if (pos)
4738 len = pos - driver;
4739 else
4740 len = os_strlen(driver);
4741
4742 for (i = 0; wpa_drivers[i]; i++) {
4743 if (os_strlen(wpa_drivers[i]->name) == len &&
4744 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004745 0) {
4746 /* First driver that succeeds wins */
4747 if (select_driver(wpa_s, i) == 0)
4748 return 0;
4749 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004750 }
4751
4752 driver = pos + 1;
4753 } while (pos);
4754
4755 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4756 return -1;
4757}
4758
4759
4760/**
4761 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4762 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4763 * with struct wpa_driver_ops::init()
4764 * @src_addr: Source address of the EAPOL frame
4765 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4766 * @len: Length of the EAPOL data
4767 *
4768 * This function is called for each received EAPOL frame. Most driver
4769 * interfaces rely on more generic OS mechanism for receiving frames through
4770 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4771 * take care of received EAPOL frames and deliver them to the core supplicant
4772 * code by calling this function.
4773 */
4774void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4775 const u8 *buf, size_t len)
4776{
4777 struct wpa_supplicant *wpa_s = ctx;
4778
4779 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4780 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4781
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004782#ifdef CONFIG_TESTING_OPTIONS
4783 if (wpa_s->ignore_auth_resp) {
4784 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4785 return;
4786 }
4787#endif /* CONFIG_TESTING_OPTIONS */
4788
Jouni Malinena05074c2012-12-21 21:35:35 +02004789 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4790 (wpa_s->last_eapol_matches_bssid &&
4791#ifdef CONFIG_AP
4792 !wpa_s->ap_iface &&
4793#endif /* CONFIG_AP */
4794 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 /*
4796 * There is possible race condition between receiving the
4797 * association event and the EAPOL frame since they are coming
4798 * through different paths from the driver. In order to avoid
4799 * issues in trying to process the EAPOL frame before receiving
4800 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004801 * the association event is received. This may also be needed in
4802 * driver-based roaming case, so also use src_addr != BSSID as a
4803 * trigger if we have previously confirmed that the
4804 * Authenticator uses BSSID as the src_addr (which is not the
4805 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806 */
4807 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004808 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4809 wpa_supplicant_state_txt(wpa_s->wpa_state),
4810 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004811 wpabuf_free(wpa_s->pending_eapol_rx);
4812 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4813 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004814 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4816 ETH_ALEN);
4817 }
4818 return;
4819 }
4820
Jouni Malinena05074c2012-12-21 21:35:35 +02004821 wpa_s->last_eapol_matches_bssid =
4822 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824#ifdef CONFIG_AP
4825 if (wpa_s->ap_iface) {
4826 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4827 return;
4828 }
4829#endif /* CONFIG_AP */
4830
4831 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4832 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4833 "no key management is configured");
4834 return;
4835 }
4836
4837 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004838 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004839 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4840 wpa_s->wpa_state != WPA_COMPLETED) &&
4841 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004842 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004843 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004844 int timeout = 10;
4845
4846 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4847 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4848 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4849 /* Use longer timeout for IEEE 802.1X/EAP */
4850 timeout = 70;
4851 }
4852
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004853#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004854 if (wpa_s->current_ssid && wpa_s->current_bss &&
4855 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4856 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4857 /*
4858 * Use shorter timeout if going through WPS AP iteration
4859 * for PIN config method with an AP that does not
4860 * advertise Selected Registrar.
4861 */
4862 struct wpabuf *wps_ie;
4863
4864 wps_ie = wpa_bss_get_vendor_ie_multi(
4865 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4866 if (wps_ie &&
4867 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4868 timeout = 10;
4869 wpabuf_free(wps_ie);
4870 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004871#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004872
4873 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 }
4875 wpa_s->eapol_received++;
4876
4877 if (wpa_s->countermeasures) {
4878 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4879 "EAPOL packet");
4880 return;
4881 }
4882
4883#ifdef CONFIG_IBSS_RSN
4884 if (wpa_s->current_ssid &&
4885 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4886 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4887 return;
4888 }
4889#endif /* CONFIG_IBSS_RSN */
4890
4891 /* Source address of the incoming EAPOL frame could be compared to the
4892 * current BSSID. However, it is possible that a centralized
4893 * Authenticator could be using another MAC address than the BSSID of
4894 * an AP, so just allow any address to be used for now. The replies are
4895 * still sent to the current BSSID (if available), though. */
4896
4897 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4898 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004899 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4900 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004901 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4902 return;
4903 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004904 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4906 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4907 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004908 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909 * handshake processing which would normally set portValid. We
4910 * need this to allow the EAPOL state machines to be completed
4911 * without going through EAPOL-Key handshake.
4912 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004913 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004914 }
4915}
4916
4917
Hai Shalomb755a2a2020-04-23 21:49:02 -07004918static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4919{
4920 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4921 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4922}
4923
4924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004925int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004926{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004927 if ((!wpa_s->p2p_mgmt ||
4928 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4929 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004930 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004931 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4932 wpa_drv_get_mac_addr(wpa_s),
4933 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004934 wpas_eapol_needs_l2_packet(wpa_s) ?
4935 wpa_supplicant_rx_eapol : NULL,
4936 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004937 if (wpa_s->l2 == NULL)
4938 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004939
4940 if (l2_packet_set_packet_filter(wpa_s->l2,
4941 L2_PACKET_FILTER_PKTTYPE))
4942 wpa_dbg(wpa_s, MSG_DEBUG,
4943 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004944
4945 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4946 wpa_msg(wpa_s, MSG_ERROR,
4947 "Failed to get own L2 address");
4948 return -1;
4949 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004950 } else {
4951 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4952 if (addr)
4953 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4954 }
4955
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004956 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004957 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004958
Hai Shalomc3565922019-10-28 11:58:20 -07004959#ifdef CONFIG_FST
4960 if (wpa_s->fst)
4961 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4962#endif /* CONFIG_FST */
4963
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004964 return 0;
4965}
4966
4967
Dmitry Shmidt04949592012-07-19 12:16:46 -07004968static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4969 const u8 *buf, size_t len)
4970{
4971 struct wpa_supplicant *wpa_s = ctx;
4972 const struct l2_ethhdr *eth;
4973
4974 if (len < sizeof(*eth))
4975 return;
4976 eth = (const struct l2_ethhdr *) buf;
4977
4978 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4979 !(eth->h_dest[0] & 0x01)) {
4980 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4981 " (bridge - not for this interface - ignore)",
4982 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4983 return;
4984 }
4985
4986 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4987 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4988 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4989 len - sizeof(*eth));
4990}
4991
4992
Hai Shalom899fcc72020-10-19 14:38:18 -07004993int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
4994 const char *bridge_ifname)
4995{
4996 if (wpa_s->wpa_state > WPA_SCANNING)
4997 return -EBUSY;
4998
4999 if (bridge_ifname &&
5000 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5001 return -EINVAL;
5002
5003 if (!bridge_ifname)
5004 bridge_ifname = "";
5005
5006 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5007 return 0;
5008
5009 if (wpa_s->l2_br) {
5010 l2_packet_deinit(wpa_s->l2_br);
5011 wpa_s->l2_br = NULL;
5012 }
5013
5014 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5015 sizeof(wpa_s->bridge_ifname));
5016
5017 if (wpa_s->bridge_ifname[0]) {
5018 wpa_dbg(wpa_s, MSG_DEBUG,
5019 "Receiving packets from bridge interface '%s'",
5020 wpa_s->bridge_ifname);
5021 wpa_s->l2_br = l2_packet_init_bridge(
5022 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5023 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5024 if (!wpa_s->l2_br) {
5025 wpa_msg(wpa_s, MSG_ERROR,
5026 "Failed to open l2_packet connection for the bridge interface '%s'",
5027 wpa_s->bridge_ifname);
5028 goto fail;
5029 }
5030 }
5031
5032#ifdef CONFIG_TDLS
5033 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5034 goto fail;
5035#endif /* CONFIG_TDLS */
5036
5037 return 0;
5038fail:
5039 wpa_s->bridge_ifname[0] = 0;
5040 if (wpa_s->l2_br) {
5041 l2_packet_deinit(wpa_s->l2_br);
5042 wpa_s->l2_br = NULL;
5043 }
5044#ifdef CONFIG_TDLS
5045 if (!wpa_s->p2p_mgmt)
5046 wpa_tdls_init(wpa_s->wpa);
5047#endif /* CONFIG_TDLS */
5048 return -EIO;
5049}
5050
5051
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005052/**
5053 * wpa_supplicant_driver_init - Initialize driver interface parameters
5054 * @wpa_s: Pointer to wpa_supplicant data
5055 * Returns: 0 on success, -1 on failure
5056 *
5057 * This function is called to initialize driver interface parameters.
5058 * wpa_drv_init() must have been called before this function to initialize the
5059 * driver interface.
5060 */
5061int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5062{
5063 static int interface_count = 0;
5064
5065 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5066 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005067
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005068 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5069 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005070 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005071 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5072
Hai Shalomb755a2a2020-04-23 21:49:02 -07005073 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005074 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5075 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005076 wpa_s->l2_br = l2_packet_init_bridge(
5077 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5078 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005079 if (wpa_s->l2_br == NULL) {
5080 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5081 "connection for the bridge interface '%s'",
5082 wpa_s->bridge_ifname);
5083 return -1;
5084 }
5085 }
5086
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005087 if (wpa_s->conf->ap_scan == 2 &&
5088 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5089 wpa_printf(MSG_INFO,
5090 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5091 }
5092
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005093 wpa_clear_keys(wpa_s, NULL);
5094
5095 /* Make sure that TKIP countermeasures are not left enabled (could
5096 * happen if wpa_supplicant is killed during countermeasures. */
5097 wpa_drv_set_countermeasures(wpa_s, 0);
5098
5099 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5100 wpa_drv_flush_pmkid(wpa_s);
5101
5102 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005103 wpa_s->prev_scan_wildcard = 0;
5104
Dmitry Shmidt04949592012-07-19 12:16:46 -07005105 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005106 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5107 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5108 interface_count = 0;
5109 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005110#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005111 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005112 wpa_supplicant_delayed_sched_scan(wpa_s,
5113 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005114 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005115 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005116 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005117#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005118 interface_count++;
5119 } else
5120 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5121
5122 return 0;
5123}
5124
5125
5126static int wpa_supplicant_daemon(const char *pid_file)
5127{
5128 wpa_printf(MSG_DEBUG, "Daemonize..");
5129 return os_daemonize(pid_file);
5130}
5131
5132
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005133static struct wpa_supplicant *
5134wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005135{
5136 struct wpa_supplicant *wpa_s;
5137
5138 wpa_s = os_zalloc(sizeof(*wpa_s));
5139 if (wpa_s == NULL)
5140 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005141 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005142 wpa_s->scan_interval = 5;
5143 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005144 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005145 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005146 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005147 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005148
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005149 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005150 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005151#ifdef CONFIG_TESTING_OPTIONS
5152 dl_list_init(&wpa_s->drv_signal_override);
5153#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005154
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005155 return wpa_s;
5156}
5157
5158
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005159#ifdef CONFIG_HT_OVERRIDES
5160
5161static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5162 struct ieee80211_ht_capabilities *htcaps,
5163 struct ieee80211_ht_capabilities *htcaps_mask,
5164 const char *ht_mcs)
5165{
5166 /* parse ht_mcs into hex array */
5167 int i;
5168 const char *tmp = ht_mcs;
5169 char *end = NULL;
5170
5171 /* If ht_mcs is null, do not set anything */
5172 if (!ht_mcs)
5173 return 0;
5174
5175 /* This is what we are setting in the kernel */
5176 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5177
5178 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5179
5180 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005181 long v;
5182
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005183 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005184 v = strtol(tmp, &end, 16);
5185
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005186 if (errno == 0) {
5187 wpa_msg(wpa_s, MSG_DEBUG,
5188 "htcap value[%i]: %ld end: %p tmp: %p",
5189 i, v, end, tmp);
5190 if (end == tmp)
5191 break;
5192
5193 htcaps->supported_mcs_set[i] = v;
5194 tmp = end;
5195 } else {
5196 wpa_msg(wpa_s, MSG_ERROR,
5197 "Failed to parse ht-mcs: %s, error: %s\n",
5198 ht_mcs, strerror(errno));
5199 return -1;
5200 }
5201 }
5202
5203 /*
5204 * If we were able to parse any values, then set mask for the MCS set.
5205 */
5206 if (i) {
5207 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5208 IEEE80211_HT_MCS_MASK_LEN - 1);
5209 /* skip the 3 reserved bits */
5210 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5211 0x1f;
5212 }
5213
5214 return 0;
5215}
5216
5217
5218static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5219 struct ieee80211_ht_capabilities *htcaps,
5220 struct ieee80211_ht_capabilities *htcaps_mask,
5221 int disabled)
5222{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005223 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005224
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005225 if (disabled == -1)
5226 return 0;
5227
Hai Shalom74f70d42019-02-11 14:42:39 -08005228 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5229
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005230 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5231 htcaps_mask->ht_capabilities_info |= msk;
5232 if (disabled)
5233 htcaps->ht_capabilities_info &= msk;
5234 else
5235 htcaps->ht_capabilities_info |= msk;
5236
5237 return 0;
5238}
5239
5240
5241static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5242 struct ieee80211_ht_capabilities *htcaps,
5243 struct ieee80211_ht_capabilities *htcaps_mask,
5244 int factor)
5245{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005246 if (factor == -1)
5247 return 0;
5248
Hai Shalom74f70d42019-02-11 14:42:39 -08005249 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5250
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005251 if (factor < 0 || factor > 3) {
5252 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5253 "Must be 0-3 or -1", factor);
5254 return -EINVAL;
5255 }
5256
5257 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5258 htcaps->a_mpdu_params &= ~0x3;
5259 htcaps->a_mpdu_params |= factor & 0x3;
5260
5261 return 0;
5262}
5263
5264
5265static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5266 struct ieee80211_ht_capabilities *htcaps,
5267 struct ieee80211_ht_capabilities *htcaps_mask,
5268 int density)
5269{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005270 if (density == -1)
5271 return 0;
5272
Hai Shalom74f70d42019-02-11 14:42:39 -08005273 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5274
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005275 if (density < 0 || density > 7) {
5276 wpa_msg(wpa_s, MSG_ERROR,
5277 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5278 density);
5279 return -EINVAL;
5280 }
5281
5282 htcaps_mask->a_mpdu_params |= 0x1C;
5283 htcaps->a_mpdu_params &= ~(0x1C);
5284 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5285
5286 return 0;
5287}
5288
5289
5290static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5291 struct ieee80211_ht_capabilities *htcaps,
5292 struct ieee80211_ht_capabilities *htcaps_mask,
5293 int disabled)
5294{
Hai Shalom74f70d42019-02-11 14:42:39 -08005295 if (disabled)
5296 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005297
Paul Stewart092955c2017-02-06 09:13:09 -08005298 set_disable_ht40(htcaps, disabled);
5299 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005300
5301 return 0;
5302}
5303
5304
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005305static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5306 struct ieee80211_ht_capabilities *htcaps,
5307 struct ieee80211_ht_capabilities *htcaps_mask,
5308 int disabled)
5309{
5310 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005311 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5312 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005313
Hai Shalom74f70d42019-02-11 14:42:39 -08005314 if (disabled)
5315 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005316
5317 if (disabled)
5318 htcaps->ht_capabilities_info &= ~msk;
5319 else
5320 htcaps->ht_capabilities_info |= msk;
5321
5322 htcaps_mask->ht_capabilities_info |= msk;
5323
5324 return 0;
5325}
5326
5327
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005328static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5329 struct ieee80211_ht_capabilities *htcaps,
5330 struct ieee80211_ht_capabilities *htcaps_mask,
5331 int disabled)
5332{
5333 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005334 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005335
Hai Shalom74f70d42019-02-11 14:42:39 -08005336 if (disabled)
5337 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005338
5339 if (disabled)
5340 htcaps->ht_capabilities_info &= ~msk;
5341 else
5342 htcaps->ht_capabilities_info |= msk;
5343
5344 htcaps_mask->ht_capabilities_info |= msk;
5345
5346 return 0;
5347}
5348
5349
Hai Shalom74f70d42019-02-11 14:42:39 -08005350static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5351 struct ieee80211_ht_capabilities *htcaps,
5352 struct ieee80211_ht_capabilities *htcaps_mask,
5353 int tx_stbc)
5354{
5355 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5356
5357 if (tx_stbc == -1)
5358 return 0;
5359
5360 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5361
5362 if (tx_stbc < 0 || tx_stbc > 1) {
5363 wpa_msg(wpa_s, MSG_ERROR,
5364 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5365 return -EINVAL;
5366 }
5367
5368 htcaps_mask->ht_capabilities_info |= msk;
5369 htcaps->ht_capabilities_info &= ~msk;
5370 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5371
5372 return 0;
5373}
5374
5375
5376static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5377 struct ieee80211_ht_capabilities *htcaps,
5378 struct ieee80211_ht_capabilities *htcaps_mask,
5379 int rx_stbc)
5380{
5381 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5382
5383 if (rx_stbc == -1)
5384 return 0;
5385
5386 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5387
5388 if (rx_stbc < 0 || rx_stbc > 3) {
5389 wpa_msg(wpa_s, MSG_ERROR,
5390 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5391 return -EINVAL;
5392 }
5393
5394 htcaps_mask->ht_capabilities_info |= msk;
5395 htcaps->ht_capabilities_info &= ~msk;
5396 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5397
5398 return 0;
5399}
5400
5401
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005402void wpa_supplicant_apply_ht_overrides(
5403 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5404 struct wpa_driver_associate_params *params)
5405{
5406 struct ieee80211_ht_capabilities *htcaps;
5407 struct ieee80211_ht_capabilities *htcaps_mask;
5408
5409 if (!ssid)
5410 return;
5411
5412 params->disable_ht = ssid->disable_ht;
5413 if (!params->htcaps || !params->htcaps_mask)
5414 return;
5415
5416 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5417 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5418 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5419 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5420 ssid->disable_max_amsdu);
5421 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5422 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5423 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005424 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005425 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005426 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5427 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005428
5429 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005430 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005431 htcaps->ht_capabilities_info |= bit;
5432 htcaps_mask->ht_capabilities_info |= bit;
5433 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005434}
5435
5436#endif /* CONFIG_HT_OVERRIDES */
5437
5438
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005439#ifdef CONFIG_VHT_OVERRIDES
5440void wpa_supplicant_apply_vht_overrides(
5441 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5442 struct wpa_driver_associate_params *params)
5443{
5444 struct ieee80211_vht_capabilities *vhtcaps;
5445 struct ieee80211_vht_capabilities *vhtcaps_mask;
5446
5447 if (!ssid)
5448 return;
5449
5450 params->disable_vht = ssid->disable_vht;
5451
5452 vhtcaps = (void *) params->vhtcaps;
5453 vhtcaps_mask = (void *) params->vhtcaps_mask;
5454
5455 if (!vhtcaps || !vhtcaps_mask)
5456 return;
5457
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005458 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5459 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005460
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005461#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005462 if (ssid->disable_sgi) {
5463 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5464 VHT_CAP_SHORT_GI_160);
5465 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5466 VHT_CAP_SHORT_GI_160);
5467 wpa_msg(wpa_s, MSG_DEBUG,
5468 "disable-sgi override specified, vht-caps: 0x%x",
5469 vhtcaps->vht_capabilities_info);
5470 }
5471
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005472 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005473 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5474 int max_ampdu;
5475
5476 max_ampdu = (ssid->vht_capa &
5477 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5478 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005479
5480 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5481 wpa_set_ampdu_factor(wpa_s,
5482 (void *) params->htcaps,
5483 (void *) params->htcaps_mask,
5484 max_ampdu);
5485 }
5486#endif /* CONFIG_HT_OVERRIDES */
5487
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005488#define OVERRIDE_MCS(i) \
5489 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5490 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005491 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005492 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005493 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5494 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005495 } \
5496 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5497 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005498 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005499 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005500 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5501 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005502 }
5503
5504 OVERRIDE_MCS(1);
5505 OVERRIDE_MCS(2);
5506 OVERRIDE_MCS(3);
5507 OVERRIDE_MCS(4);
5508 OVERRIDE_MCS(5);
5509 OVERRIDE_MCS(6);
5510 OVERRIDE_MCS(7);
5511 OVERRIDE_MCS(8);
5512}
5513#endif /* CONFIG_VHT_OVERRIDES */
5514
5515
Hai Shalomfdcde762020-04-02 11:19:20 -07005516#ifdef CONFIG_HE_OVERRIDES
5517void wpa_supplicant_apply_he_overrides(
5518 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5519 struct wpa_driver_associate_params *params)
5520{
5521 if (!ssid)
5522 return;
5523
5524 params->disable_he = ssid->disable_he;
5525}
5526#endif /* CONFIG_HE_OVERRIDES */
5527
5528
Dmitry Shmidt04949592012-07-19 12:16:46 -07005529static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5530{
5531#ifdef PCSC_FUNCS
5532 size_t len;
5533
5534 if (!wpa_s->conf->pcsc_reader)
5535 return 0;
5536
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005537 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005538 if (!wpa_s->scard)
5539 return 1;
5540
5541 if (wpa_s->conf->pcsc_pin &&
5542 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5543 scard_deinit(wpa_s->scard);
5544 wpa_s->scard = NULL;
5545 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5546 return -1;
5547 }
5548
5549 len = sizeof(wpa_s->imsi) - 1;
5550 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5551 scard_deinit(wpa_s->scard);
5552 wpa_s->scard = NULL;
5553 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5554 return -1;
5555 }
5556 wpa_s->imsi[len] = '\0';
5557
5558 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5559
5560 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5561 wpa_s->imsi, wpa_s->mnc_len);
5562
5563 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5564 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5565#endif /* PCSC_FUNCS */
5566
5567 return 0;
5568}
5569
5570
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005571int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5572{
5573 char *val, *pos;
5574
5575 ext_password_deinit(wpa_s->ext_pw);
5576 wpa_s->ext_pw = NULL;
5577 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5578
5579 if (!wpa_s->conf->ext_password_backend)
5580 return 0;
5581
5582 val = os_strdup(wpa_s->conf->ext_password_backend);
5583 if (val == NULL)
5584 return -1;
5585 pos = os_strchr(val, ':');
5586 if (pos)
5587 *pos++ = '\0';
5588
5589 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5590
5591 wpa_s->ext_pw = ext_password_init(val, pos);
5592 os_free(val);
5593 if (wpa_s->ext_pw == NULL) {
5594 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5595 return -1;
5596 }
5597 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5598
5599 return 0;
5600}
5601
5602
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005603#ifdef CONFIG_FST
5604
5605static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5606{
5607 struct wpa_supplicant *wpa_s = ctx;
5608
5609 return (is_zero_ether_addr(wpa_s->bssid) ||
5610 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5611}
5612
5613
5614static void wpas_fst_get_channel_info_cb(void *ctx,
5615 enum hostapd_hw_mode *hw_mode,
5616 u8 *channel)
5617{
5618 struct wpa_supplicant *wpa_s = ctx;
5619
5620 if (wpa_s->current_bss) {
5621 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5622 channel);
5623 } else if (wpa_s->hw.num_modes) {
5624 *hw_mode = wpa_s->hw.modes[0].mode;
5625 } else {
5626 WPA_ASSERT(0);
5627 *hw_mode = 0;
5628 }
5629}
5630
5631
5632static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5633{
5634 struct wpa_supplicant *wpa_s = ctx;
5635
5636 *modes = wpa_s->hw.modes;
5637 return wpa_s->hw.num_modes;
5638}
5639
5640
5641static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5642{
5643 struct wpa_supplicant *wpa_s = ctx;
5644
5645 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5646 wpa_s->fst_ies = fst_ies;
5647}
5648
5649
5650static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5651{
5652 struct wpa_supplicant *wpa_s = ctx;
5653
Paul Stewart092955c2017-02-06 09:13:09 -08005654 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5655 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5656 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5657 return -1;
5658 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005659 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005660 wpa_s->own_addr, wpa_s->bssid,
5661 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005662 0);
5663}
5664
5665
5666static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5667{
5668 struct wpa_supplicant *wpa_s = ctx;
5669
5670 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5671 return wpa_s->received_mb_ies;
5672}
5673
5674
5675static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5676 const u8 *buf, size_t size)
5677{
5678 struct wpa_supplicant *wpa_s = ctx;
5679 struct mb_ies_info info;
5680
5681 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5682
5683 if (!mb_ies_info_by_ies(&info, buf, size)) {
5684 wpabuf_free(wpa_s->received_mb_ies);
5685 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5686 }
5687}
5688
5689
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005690static const u8 * wpas_fst_get_peer_first(void *ctx,
5691 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005692 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005693{
5694 struct wpa_supplicant *wpa_s = ctx;
5695
5696 *get_ctx = NULL;
5697 if (!is_zero_ether_addr(wpa_s->bssid))
5698 return (wpa_s->received_mb_ies || !mb_only) ?
5699 wpa_s->bssid : NULL;
5700 return NULL;
5701}
5702
5703
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005704static const u8 * wpas_fst_get_peer_next(void *ctx,
5705 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005706 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005707{
5708 return NULL;
5709}
5710
5711void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5712 struct fst_wpa_obj *iface_obj)
5713{
5714 iface_obj->ctx = wpa_s;
5715 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5716 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5717 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5718 iface_obj->set_ies = wpas_fst_set_ies_cb;
5719 iface_obj->send_action = wpas_fst_send_action_cb;
5720 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5721 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5722 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5723 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5724}
5725#endif /* CONFIG_FST */
5726
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005727static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005728 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005729{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005730 struct wowlan_triggers *triggers;
5731 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005732
5733 if (!wpa_s->conf->wowlan_triggers)
5734 return 0;
5735
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005736 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5737 if (triggers) {
5738 ret = wpa_drv_wowlan(wpa_s, triggers);
5739 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005740 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005741 return ret;
5742}
5743
5744
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005745enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005746{
5747 if (freq < 3000)
5748 return BAND_2_4_GHZ;
5749 if (freq > 50000)
5750 return BAND_60_GHZ;
5751 return BAND_5_GHZ;
5752}
5753
5754
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005755unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005756{
5757 int i;
5758 unsigned int band = 0;
5759
5760 if (freqs) {
5761 /* freqs are specified for the radio work */
5762 for (i = 0; freqs[i]; i++)
5763 band |= wpas_freq_to_band(freqs[i]);
5764 } else {
5765 /*
5766 * freqs are not specified, implies all
5767 * the supported freqs by HW
5768 */
5769 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5770 if (wpa_s->hw.modes[i].num_channels != 0) {
5771 if (wpa_s->hw.modes[i].mode ==
5772 HOSTAPD_MODE_IEEE80211B ||
5773 wpa_s->hw.modes[i].mode ==
5774 HOSTAPD_MODE_IEEE80211G)
5775 band |= BAND_2_4_GHZ;
5776 else if (wpa_s->hw.modes[i].mode ==
5777 HOSTAPD_MODE_IEEE80211A)
5778 band |= BAND_5_GHZ;
5779 else if (wpa_s->hw.modes[i].mode ==
5780 HOSTAPD_MODE_IEEE80211AD)
5781 band |= BAND_60_GHZ;
5782 else if (wpa_s->hw.modes[i].mode ==
5783 HOSTAPD_MODE_IEEE80211ANY)
5784 band = BAND_2_4_GHZ | BAND_5_GHZ |
5785 BAND_60_GHZ;
5786 }
5787 }
5788 }
5789
5790 return band;
5791}
5792
5793
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005794static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5795 const char *rn)
5796{
5797 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5798 struct wpa_radio *radio;
5799
5800 while (rn && iface) {
5801 radio = iface->radio;
5802 if (radio && os_strcmp(rn, radio->name) == 0) {
5803 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5804 wpa_s->ifname, rn);
5805 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5806 return radio;
5807 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005808
5809 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005810 }
5811
5812 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5813 wpa_s->ifname, rn ? rn : "N/A");
5814 radio = os_zalloc(sizeof(*radio));
5815 if (radio == NULL)
5816 return NULL;
5817
5818 if (rn)
5819 os_strlcpy(radio->name, rn, sizeof(radio->name));
5820 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005821 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005822 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5823
5824 return radio;
5825}
5826
5827
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005828static void radio_work_free(struct wpa_radio_work *work)
5829{
5830 if (work->wpa_s->scan_work == work) {
5831 /* This should not really happen. */
5832 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5833 work->type, work, work->started);
5834 work->wpa_s->scan_work = NULL;
5835 }
5836
5837#ifdef CONFIG_P2P
5838 if (work->wpa_s->p2p_scan_work == work) {
5839 /* This should not really happen. */
5840 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5841 work->type, work, work->started);
5842 work->wpa_s->p2p_scan_work = NULL;
5843 }
5844#endif /* CONFIG_P2P */
5845
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005846 if (work->started) {
5847 work->wpa_s->radio->num_active_works--;
5848 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005849 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005850 work->type, work,
5851 work->wpa_s->radio->num_active_works);
5852 }
5853
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005854 dl_list_del(&work->list);
5855 os_free(work);
5856}
5857
5858
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005859static int radio_work_is_connect(struct wpa_radio_work *work)
5860{
5861 return os_strcmp(work->type, "sme-connect") == 0 ||
5862 os_strcmp(work->type, "connect") == 0;
5863}
5864
5865
5866static int radio_work_is_scan(struct wpa_radio_work *work)
5867{
5868 return os_strcmp(work->type, "scan") == 0 ||
5869 os_strcmp(work->type, "p2p-scan") == 0;
5870}
5871
5872
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005873static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5874{
5875 struct wpa_radio_work *active_work = NULL;
5876 struct wpa_radio_work *tmp;
5877
5878 /* Get the active work to know the type and band. */
5879 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5880 if (tmp->started) {
5881 active_work = tmp;
5882 break;
5883 }
5884 }
5885
5886 if (!active_work) {
5887 /* No active work, start one */
5888 radio->num_active_works = 0;
5889 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5890 list) {
5891 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005892 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005893 (((struct wpa_driver_scan_params *)
5894 tmp->ctx)->only_new_results ||
5895 tmp->wpa_s->clear_driver_scan_cache))
5896 continue;
5897 return tmp;
5898 }
5899 return NULL;
5900 }
5901
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005902 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005903 /*
5904 * If the active work is either connect or sme-connect,
5905 * do not parallelize them with other radio works.
5906 */
5907 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5908 "Do not parallelize radio work with %s",
5909 active_work->type);
5910 return NULL;
5911 }
5912
5913 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5914 if (tmp->started)
5915 continue;
5916
5917 /*
5918 * If connect or sme-connect are enqueued, parallelize only
5919 * those operations ahead of them in the queue.
5920 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005921 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005922 break;
5923
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005924 /* Serialize parallel scan and p2p_scan operations on the same
5925 * interface since the driver_nl80211 mechanism for tracking
5926 * scan cookies does not yet have support for this. */
5927 if (active_work->wpa_s == tmp->wpa_s &&
5928 radio_work_is_scan(active_work) &&
5929 radio_work_is_scan(tmp)) {
5930 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5931 "Do not start work '%s' when another work '%s' is already scheduled",
5932 tmp->type, active_work->type);
5933 continue;
5934 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005935 /*
5936 * Check that the radio works are distinct and
5937 * on different bands.
5938 */
5939 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5940 (active_work->bands != tmp->bands)) {
5941 /*
5942 * If a scan has to be scheduled through nl80211 scan
5943 * interface and if an external scan is already running,
5944 * do not schedule the scan since it is likely to get
5945 * rejected by kernel.
5946 */
5947 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08005948 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005949 (((struct wpa_driver_scan_params *)
5950 tmp->ctx)->only_new_results ||
5951 tmp->wpa_s->clear_driver_scan_cache))
5952 continue;
5953
5954 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5955 "active_work:%s new_work:%s",
5956 active_work->type, tmp->type);
5957 return tmp;
5958 }
5959 }
5960
5961 /* Did not find a radio work to schedule in parallel. */
5962 return NULL;
5963}
5964
5965
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005966static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5967{
5968 struct wpa_radio *radio = eloop_ctx;
5969 struct wpa_radio_work *work;
5970 struct os_reltime now, diff;
5971 struct wpa_supplicant *wpa_s;
5972
5973 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005974 if (work == NULL) {
5975 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005976 return;
5977 }
5978
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005979 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5980 radio_list);
5981
5982 if (!(wpa_s &&
5983 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5984 if (work->started)
5985 return; /* already started and still in progress */
5986
Hai Shalom60840252021-02-19 19:02:11 -08005987 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005988 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5989 return;
5990 }
5991 } else {
5992 work = NULL;
5993 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5994 /* get the work to schedule next */
5995 work = radio_work_get_next_work(radio);
5996 }
5997 if (!work)
5998 return;
5999 }
6000
6001 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006002 os_get_reltime(&now);
6003 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006004 wpa_dbg(wpa_s, MSG_DEBUG,
6005 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006006 work->type, work, diff.sec, diff.usec);
6007 work->started = 1;
6008 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006009 radio->num_active_works++;
6010
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006011 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006012
6013 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6014 radio->num_active_works < MAX_ACTIVE_WORKS)
6015 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006016}
6017
6018
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006019/*
6020 * This function removes both started and pending radio works running on
6021 * the provided interface's radio.
6022 * Prior to the removal of the radio work, its callback (cb) is called with
6023 * deinit set to be 1. Each work's callback is responsible for clearing its
6024 * internal data and restoring to a correct state.
6025 * @wpa_s: wpa_supplicant data
6026 * @type: type of works to be removed
6027 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6028 * this interface's works.
6029 */
6030void radio_remove_works(struct wpa_supplicant *wpa_s,
6031 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006032{
6033 struct wpa_radio_work *work, *tmp;
6034 struct wpa_radio *radio = wpa_s->radio;
6035
6036 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6037 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006038 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006039 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006040
6041 /* skip other ifaces' works */
6042 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006043 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006044
6045 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6046 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006047 work->cb(work, 1);
6048 radio_work_free(work);
6049 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006050
6051 /* in case we removed the started work */
6052 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006053}
6054
6055
Roshan Pius3a1667e2018-07-03 15:17:14 -07006056void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6057{
6058 struct wpa_radio_work *work;
6059 struct wpa_radio *radio = wpa_s->radio;
6060
6061 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6062 if (work->ctx != ctx)
6063 continue;
6064 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6065 work->type, work, work->started ? " (started)" : "");
6066 radio_work_free(work);
6067 break;
6068 }
6069}
6070
6071
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006072static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6073{
6074 struct wpa_radio *radio = wpa_s->radio;
6075
6076 if (!radio)
6077 return;
6078
6079 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6080 wpa_s->ifname, radio->name);
6081 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006082 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006083 /* If the interface that triggered the external scan was removed, the
6084 * external scan is no longer running. */
6085 if (wpa_s == radio->external_scan_req_interface)
6086 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006087 wpa_s->radio = NULL;
6088 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006089 return; /* Interfaces remain for this radio */
6090
6091 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006092 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006093 os_free(radio);
6094}
6095
6096
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006097void radio_work_check_next(struct wpa_supplicant *wpa_s)
6098{
6099 struct wpa_radio *radio = wpa_s->radio;
6100
6101 if (dl_list_empty(&radio->work))
6102 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006103 if (wpa_s->ext_work_in_progress) {
6104 wpa_printf(MSG_DEBUG,
6105 "External radio work in progress - delay start of pending item");
6106 return;
6107 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006108 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6109 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6110}
6111
6112
6113/**
6114 * radio_add_work - Add a radio work item
6115 * @wpa_s: Pointer to wpa_supplicant data
6116 * @freq: Frequency of the offchannel operation in MHz or 0
6117 * @type: Unique identifier for each type of work
6118 * @next: Force as the next work to be executed
6119 * @cb: Callback function for indicating when radio is available
6120 * @ctx: Context pointer for the work (work->ctx in cb())
6121 * Returns: 0 on success, -1 on failure
6122 *
6123 * This function is used to request time for an operation that requires
6124 * exclusive radio control. Once the radio is available, the registered callback
6125 * function will be called. radio_work_done() must be called once the exclusive
6126 * radio operation has been completed, so that the radio is freed for other
6127 * operations. The special case of deinit=1 is used to free the context data
6128 * during interface removal. That does not allow the callback function to start
6129 * the radio operation, i.e., it must free any resources allocated for the radio
6130 * work and return.
6131 *
6132 * The @freq parameter can be used to indicate a single channel on which the
6133 * offchannel operation will occur. This may allow multiple radio work
6134 * operations to be performed in parallel if they apply for the same channel.
6135 * Setting this to 0 indicates that the work item may use multiple channels or
6136 * requires exclusive control of the radio.
6137 */
6138int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6139 const char *type, int next,
6140 void (*cb)(struct wpa_radio_work *work, int deinit),
6141 void *ctx)
6142{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006143 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006144 struct wpa_radio_work *work;
6145 int was_empty;
6146
6147 work = os_zalloc(sizeof(*work));
6148 if (work == NULL)
6149 return -1;
6150 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6151 os_get_reltime(&work->time);
6152 work->freq = freq;
6153 work->type = type;
6154 work->wpa_s = wpa_s;
6155 work->cb = cb;
6156 work->ctx = ctx;
6157
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006158 if (freq)
6159 work->bands = wpas_freq_to_band(freq);
6160 else if (os_strcmp(type, "scan") == 0 ||
6161 os_strcmp(type, "p2p-scan") == 0)
6162 work->bands = wpas_get_bands(wpa_s,
6163 ((struct wpa_driver_scan_params *)
6164 ctx)->freqs);
6165 else
6166 work->bands = wpas_get_bands(wpa_s, NULL);
6167
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006168 was_empty = dl_list_empty(&wpa_s->radio->work);
6169 if (next)
6170 dl_list_add(&wpa_s->radio->work, &work->list);
6171 else
6172 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6173 if (was_empty) {
6174 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6175 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006176 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6177 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6178 wpa_dbg(wpa_s, MSG_DEBUG,
6179 "Try to schedule a radio work (num_active_works=%u)",
6180 radio->num_active_works);
6181 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006182 }
6183
6184 return 0;
6185}
6186
6187
6188/**
6189 * radio_work_done - Indicate that a radio work item has been completed
6190 * @work: Completed work
6191 *
6192 * This function is called once the callback function registered with
6193 * radio_add_work() has completed its work.
6194 */
6195void radio_work_done(struct wpa_radio_work *work)
6196{
6197 struct wpa_supplicant *wpa_s = work->wpa_s;
6198 struct os_reltime now, diff;
6199 unsigned int started = work->started;
6200
6201 os_get_reltime(&now);
6202 os_reltime_sub(&now, &work->time, &diff);
6203 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6204 work->type, work, started ? "done" : "canceled",
6205 diff.sec, diff.usec);
6206 radio_work_free(work);
6207 if (started)
6208 radio_work_check_next(wpa_s);
6209}
6210
6211
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006212struct wpa_radio_work *
6213radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006214{
6215 struct wpa_radio_work *work;
6216 struct wpa_radio *radio = wpa_s->radio;
6217
6218 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6219 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006220 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006221 }
6222
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006223 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006224}
6225
6226
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006227static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006228 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006229{
6230 const char *ifname, *driver, *rn;
6231
6232 driver = iface->driver;
6233next_driver:
6234 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6235 return -1;
6236
6237 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6238 if (wpa_s->drv_priv == NULL) {
6239 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006240 int level = MSG_ERROR;
6241
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006242 pos = driver ? os_strchr(driver, ',') : NULL;
6243 if (pos) {
6244 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6245 "driver interface - try next driver wrapper");
6246 driver = pos + 1;
6247 goto next_driver;
6248 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006249
6250#ifdef CONFIG_MATCH_IFACE
6251 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6252 level = MSG_DEBUG;
6253#endif /* CONFIG_MATCH_IFACE */
6254 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006255 return -1;
6256 }
6257 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6258 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6259 "driver_param '%s'", wpa_s->conf->driver_param);
6260 return -1;
6261 }
6262
6263 ifname = wpa_drv_get_ifname(wpa_s);
6264 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6265 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6266 "interface name with '%s'", ifname);
6267 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6268 }
6269
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006270 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006271 if (rn && rn[0] == '\0')
6272 rn = NULL;
6273
6274 wpa_s->radio = radio_add_interface(wpa_s, rn);
6275 if (wpa_s->radio == NULL)
6276 return -1;
6277
6278 return 0;
6279}
6280
6281
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006282#ifdef CONFIG_GAS_SERVER
6283
6284static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6285 unsigned int freq, const u8 *dst,
6286 const u8 *src, const u8 *bssid,
6287 const u8 *data, size_t data_len,
6288 enum offchannel_send_action_result result)
6289{
6290 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6291 " result=%s",
6292 freq, MAC2STR(dst),
6293 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6294 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6295 "FAILED"));
6296 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6297 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6298}
6299
6300
6301static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6302 struct wpabuf *buf, unsigned int wait_time)
6303{
6304 struct wpa_supplicant *wpa_s = ctx;
6305 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6306
6307 if (wait_time > wpa_s->max_remain_on_chan)
6308 wait_time = wpa_s->max_remain_on_chan;
6309
6310 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6311 wpabuf_head(buf), wpabuf_len(buf),
6312 wait_time, wpas_gas_server_tx_status, 0);
6313}
6314
6315#endif /* CONFIG_GAS_SERVER */
6316
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006317static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006318 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006319{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006320 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006321 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006322 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006323
6324 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6325 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6326 iface->confname ? iface->confname : "N/A",
6327 iface->driver ? iface->driver : "default",
6328 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6329 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6330
6331 if (iface->confname) {
6332#ifdef CONFIG_BACKEND_FILE
6333 wpa_s->confname = os_rel2abs_path(iface->confname);
6334 if (wpa_s->confname == NULL) {
6335 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6336 "for configuration file '%s'.",
6337 iface->confname);
6338 return -1;
6339 }
6340 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6341 iface->confname, wpa_s->confname);
6342#else /* CONFIG_BACKEND_FILE */
6343 wpa_s->confname = os_strdup(iface->confname);
6344#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006345 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346 if (wpa_s->conf == NULL) {
6347 wpa_printf(MSG_ERROR, "Failed to read or parse "
6348 "configuration '%s'.", wpa_s->confname);
6349 return -1;
6350 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006351 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006352 if (wpa_s->confanother &&
6353 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6354 wpa_printf(MSG_ERROR,
6355 "Failed to read or parse configuration '%s'.",
6356 wpa_s->confanother);
6357 return -1;
6358 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006359
6360 /*
6361 * Override ctrl_interface and driver_param if set on command
6362 * line.
6363 */
6364 if (iface->ctrl_interface) {
6365 os_free(wpa_s->conf->ctrl_interface);
6366 wpa_s->conf->ctrl_interface =
6367 os_strdup(iface->ctrl_interface);
6368 }
6369
6370 if (iface->driver_param) {
6371 os_free(wpa_s->conf->driver_param);
6372 wpa_s->conf->driver_param =
6373 os_strdup(iface->driver_param);
6374 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006375
6376 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6377 os_free(wpa_s->conf->ctrl_interface);
6378 wpa_s->conf->ctrl_interface = NULL;
6379 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006380 } else
6381 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6382 iface->driver_param);
6383
6384 if (wpa_s->conf == NULL) {
6385 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6386 return -1;
6387 }
6388
6389 if (iface->ifname == NULL) {
6390 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6391 return -1;
6392 }
6393 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6394 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6395 iface->ifname);
6396 return -1;
6397 }
6398 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006399#ifdef CONFIG_MATCH_IFACE
6400 wpa_s->matched = iface->matched;
6401#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006402
6403 if (iface->bridge_ifname) {
6404 if (os_strlen(iface->bridge_ifname) >=
6405 sizeof(wpa_s->bridge_ifname)) {
6406 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6407 "name '%s'.", iface->bridge_ifname);
6408 return -1;
6409 }
6410 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6411 sizeof(wpa_s->bridge_ifname));
6412 }
6413
6414 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006415 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6416 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006417
6418 /* Initialize driver interface and register driver event handler before
6419 * L2 receive handler so that association events are processed before
6420 * EAPOL-Key packets if both become available for the same select()
6421 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006422 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006423 return -1;
6424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006425 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6426 return -1;
6427
6428 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6429 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6430 NULL);
6431 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6432
6433 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6434 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6435 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6436 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6437 "dot11RSNAConfigPMKLifetime");
6438 return -1;
6439 }
6440
6441 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6442 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6443 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6444 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6445 "dot11RSNAConfigPMKReauthThreshold");
6446 return -1;
6447 }
6448
6449 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6450 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6451 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6452 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6453 "dot11RSNAConfigSATimeout");
6454 return -1;
6455 }
6456
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006457 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6458 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006459 &wpa_s->hw.flags,
6460 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006461 if (wpa_s->hw.modes) {
6462 u16 i;
6463
6464 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6465 if (wpa_s->hw.modes[i].vht_capab) {
6466 wpa_s->hw_capab = CAPAB_VHT;
6467 break;
6468 }
6469
6470 if (wpa_s->hw.modes[i].ht_capab &
6471 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6472 wpa_s->hw_capab = CAPAB_HT40;
6473 else if (wpa_s->hw.modes[i].ht_capab &&
6474 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6475 wpa_s->hw_capab = CAPAB_HT;
6476 }
6477 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006478
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006479 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6480 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006481 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006482 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006483 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006484 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006485 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006486 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006487 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006488 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006489 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6490 wpa_s->max_sched_scan_plan_interval =
6491 capa.max_sched_scan_plan_interval;
6492 wpa_s->max_sched_scan_plan_iterations =
6493 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006494 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6495 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6497 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006498 wpa_s->extended_capa = capa.extended_capa;
6499 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6500 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006501 wpa_s->num_multichan_concurrent =
6502 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006503 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6504
6505 if (capa.mac_addr_rand_scan_supported)
6506 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6507 if (wpa_s->sched_scan_supported &&
6508 capa.mac_addr_rand_sched_scan_supported)
6509 wpa_s->mac_addr_rand_supported |=
6510 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006511
6512 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6513 if (wpa_s->extended_capa &&
6514 wpa_s->extended_capa_len >= 3 &&
6515 wpa_s->extended_capa[2] & 0x40)
6516 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006517 }
6518 if (wpa_s->max_remain_on_chan == 0)
6519 wpa_s->max_remain_on_chan = 1000;
6520
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006521 /*
6522 * Only take p2p_mgmt parameters when P2P Device is supported.
6523 * Doing it here as it determines whether l2_packet_init() will be done
6524 * during wpa_supplicant_driver_init().
6525 */
6526 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6527 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006528
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006529 if (wpa_s->num_multichan_concurrent == 0)
6530 wpa_s->num_multichan_concurrent = 1;
6531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006532 if (wpa_supplicant_driver_init(wpa_s) < 0)
6533 return -1;
6534
6535#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006536 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006537 return -1;
6538#endif /* CONFIG_TDLS */
6539
6540 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6541 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6542 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6543 return -1;
6544 }
6545
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006546#ifdef CONFIG_FST
6547 if (wpa_s->conf->fst_group_id) {
6548 struct fst_iface_cfg cfg;
6549 struct fst_wpa_obj iface_obj;
6550
6551 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6552 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6553 sizeof(cfg.group_id));
6554 cfg.priority = wpa_s->conf->fst_priority;
6555 cfg.llt = wpa_s->conf->fst_llt;
6556
6557 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6558 &iface_obj, &cfg);
6559 if (!wpa_s->fst) {
6560 wpa_msg(wpa_s, MSG_ERROR,
6561 "FST: Cannot attach iface %s to group %s",
6562 wpa_s->ifname, cfg.group_id);
6563 return -1;
6564 }
6565 }
6566#endif /* CONFIG_FST */
6567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006568 if (wpas_wps_init(wpa_s))
6569 return -1;
6570
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006571#ifdef CONFIG_GAS_SERVER
6572 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6573 if (!wpa_s->gas_server) {
6574 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6575 return -1;
6576 }
6577#endif /* CONFIG_GAS_SERVER */
6578
6579#ifdef CONFIG_DPP
6580 if (wpas_dpp_init(wpa_s) < 0)
6581 return -1;
6582#endif /* CONFIG_DPP */
6583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006584 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6585 return -1;
6586 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6587
6588 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6589 if (wpa_s->ctrl_iface == NULL) {
6590 wpa_printf(MSG_ERROR,
6591 "Failed to initialize control interface '%s'.\n"
6592 "You may have another wpa_supplicant process "
6593 "already running or the file was\n"
6594 "left by an unclean termination of wpa_supplicant "
6595 "in which case you will need\n"
6596 "to manually remove this file before starting "
6597 "wpa_supplicant again.\n",
6598 wpa_s->conf->ctrl_interface);
6599 return -1;
6600 }
6601
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006602 wpa_s->gas = gas_query_init(wpa_s);
6603 if (wpa_s->gas == NULL) {
6604 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6605 return -1;
6606 }
6607
Roshan Pius3a1667e2018-07-03 15:17:14 -07006608 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6609 wpa_s->p2p_mgmt) &&
6610 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006611 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6612 return -1;
6613 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006614
6615 if (wpa_bss_init(wpa_s) < 0)
6616 return -1;
6617
Paul Stewart092955c2017-02-06 09:13:09 -08006618#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6619#ifdef CONFIG_MESH
6620 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6621#endif /* CONFIG_MESH */
6622#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6623
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006624 /*
6625 * Set Wake-on-WLAN triggers, if configured.
6626 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6627 * have effect anyway when the interface is down).
6628 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006629 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006630 return -1;
6631
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006632#ifdef CONFIG_EAP_PROXY
6633{
6634 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006635 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6636 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006637 if (wpa_s->mnc_len > 0) {
6638 wpa_s->imsi[len] = '\0';
6639 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6640 wpa_s->imsi, wpa_s->mnc_len);
6641 } else {
6642 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6643 }
6644}
6645#endif /* CONFIG_EAP_PROXY */
6646
Dmitry Shmidt04949592012-07-19 12:16:46 -07006647 if (pcsc_reader_init(wpa_s) < 0)
6648 return -1;
6649
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006650 if (wpas_init_ext_pw(wpa_s) < 0)
6651 return -1;
6652
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006653 wpas_rrm_reset(wpa_s);
6654
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006655 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6656
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006657#ifdef CONFIG_HS20
6658 hs20_init(wpa_s);
6659#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006660#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006661 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006662 if ((wpa_s->conf->oce & OCE_STA) &&
6663 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6664 wpa_s->enable_oce = OCE_STA;
6665 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6666 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6667 /* TODO: Need to add STA-CFON support */
6668 wpa_printf(MSG_ERROR,
6669 "OCE STA-CFON feature is not yet supported");
6670 }
6671 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006672 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6673#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006674
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006675 wpa_supplicant_set_default_scan_ies(wpa_s);
6676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006677 return 0;
6678}
6679
6680
6681static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006682 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006683{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006684 struct wpa_global *global = wpa_s->global;
6685 struct wpa_supplicant *iface, *prev;
6686
6687 if (wpa_s == wpa_s->parent)
6688 wpas_p2p_group_remove(wpa_s, "*");
6689
6690 iface = global->ifaces;
6691 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006692 if (iface->p2pdev == wpa_s)
6693 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006694 if (iface == wpa_s || iface->parent != wpa_s) {
6695 iface = iface->next;
6696 continue;
6697 }
6698 wpa_printf(MSG_DEBUG,
6699 "Remove remaining child interface %s from parent %s",
6700 iface->ifname, wpa_s->ifname);
6701 prev = iface;
6702 iface = iface->next;
6703 wpa_supplicant_remove_iface(global, prev, terminate);
6704 }
6705
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006706 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006707 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08006708 /*
6709 * Don't deauthenticate if WoWLAN is enable and not explicitly
6710 * been configured to disconnect.
6711 */
6712 if (!wpa_drv_get_wowlan(wpa_s) ||
6713 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006714 wpa_supplicant_deauthenticate(
6715 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006716
Hai Shalomfdcde762020-04-02 11:19:20 -07006717 wpa_drv_set_countermeasures(wpa_s, 0);
6718 wpa_clear_keys(wpa_s, NULL);
6719 } else {
6720 wpa_msg(wpa_s, MSG_INFO,
6721 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6722 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006723 }
6724
6725 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006726 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006727
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006728 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006729 radio_remove_interface(wpa_s);
6730
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006731#ifdef CONFIG_FST
6732 if (wpa_s->fst) {
6733 fst_detach(wpa_s->fst);
6734 wpa_s->fst = NULL;
6735 }
6736 if (wpa_s->received_mb_ies) {
6737 wpabuf_free(wpa_s->received_mb_ies);
6738 wpa_s->received_mb_ies = NULL;
6739 }
6740#endif /* CONFIG_FST */
6741
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006742 if (wpa_s->drv_priv)
6743 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006744
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006745 if (notify)
6746 wpas_notify_iface_removed(wpa_s);
6747
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006748 if (terminate)
6749 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006750
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02006751 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
6752 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006753
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}